Merge "Apply "Dominant Palette A - 800" color to the background of One-Handed mode" into sc-dev
diff --git a/Android.bp b/Android.bp
index 8b15f02..e5aeea6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -424,6 +424,7 @@
":libbluetooth-binder-aidl",
":libcamera_client_aidl",
":libcamera_client_framework_aidl",
+ ":packagemanager_aidl",
":libupdate_engine_aidl",
":resourcemanager_aidl",
":storaged_aidl",
@@ -509,15 +510,6 @@
],
}
-filegroup {
- name: "framework-all-sources",
- srcs: [
- ":framework-mime-sources",
- ":framework-non-updatable-sources",
- ":framework-updatable-sources",
- ],
-}
-
// AIDL files under these paths are mixture of public and private ones.
// They shouldn't be exported across module boundaries.
java_defaults {
@@ -858,10 +850,14 @@
srcs: [
"core/java/android/annotation/AnyThread.java",
"core/java/android/annotation/AppIdInt.java",
- "core/java/android/annotation/CallSuper.java",
+ "core/java/android/annotation/BytesLong.java",
"core/java/android/annotation/CallbackExecutor.java",
+ "core/java/android/annotation/CallSuper.java",
"core/java/android/annotation/CheckResult.java",
"core/java/android/annotation/CurrentTimeMillisLong.java",
+ "core/java/android/annotation/CurrentTimeSecondsLong.java",
+ "core/java/android/annotation/DrawableRes.java",
+ "core/java/android/annotation/DurationMillisLong.java",
"core/java/android/annotation/Hide.java",
"core/java/android/annotation/IntDef.java",
"core/java/android/annotation/IntRange.java",
@@ -872,15 +868,14 @@
"core/java/android/annotation/RequiresPermission.java",
"core/java/android/annotation/SdkConstant.java",
"core/java/android/annotation/StringDef.java",
- "core/java/android/annotation/SuppressLint.java",
"core/java/android/annotation/SystemApi.java",
"core/java/android/annotation/SystemService.java",
"core/java/android/annotation/TestApi.java",
"core/java/android/annotation/UserIdInt.java",
"core/java/android/annotation/WorkerThread.java",
"core/java/com/android/internal/annotations/GuardedBy.java",
- "core/java/com/android/internal/annotations/VisibleForTesting.java",
"core/java/com/android/internal/annotations/Immutable.java",
+ "core/java/com/android/internal/annotations/VisibleForTesting.java",
],
}
@@ -894,7 +889,6 @@
name: "framework-ike-shared-srcs",
visibility: ["//packages/modules/IPsec"],
srcs: [
- "core/java/android/annotation/StringDef.java",
"core/java/android/net/annotations/PolicyDirection.java",
"core/java/com/android/internal/util/HexDump.java",
"core/java/com/android/internal/util/IState.java",
@@ -1368,36 +1362,6 @@
],
}
-filegroup {
- name: "framework-media-annotation-srcs",
- srcs: [
- ":framework-annotations",
- "core/java/android/annotation/CallbackExecutor.java",
- "core/java/android/annotation/CallSuper.java",
- "core/java/android/annotation/DrawableRes.java",
- "core/java/android/annotation/LongDef.java",
- "core/java/android/annotation/StringDef.java",
- ],
-}
-
-filegroup {
- name: "framework-mediaprovider-annotation-sources",
- srcs: [
- ":framework-annotations",
- "core/java/android/annotation/BytesLong.java",
- "core/java/android/annotation/CurrentTimeSecondsLong.java",
- "core/java/android/annotation/DurationMillisLong.java",
- ],
-}
-
-// Creates an index of AIDL methods; used for adding UnsupportedAppUsage
-// annotations to private apis
-aidl_mapping {
- name: "framework-aidl-mappings",
- srcs: [":framework-all-sources"],
- output: "framework-aidl-mappings.txt",
-}
-
// Avoid including Parcelable classes as we don't want to have two copies of
// Parcelable cross the libraries. This is used by telephony-common (frameworks/opt/telephony)
// and TeleService app (packages/services/Telephony).
@@ -1513,6 +1477,19 @@
"--api-lint-ignore-prefix junit. " +
"--api-lint-ignore-prefix org. "
+filegroup {
+ name: "framework-non-updatable-stub-sources",
+ srcs: [
+ ":framework-mime-sources", // mimemap builds separately but has no separate droidstubs.
+ ":framework-non-updatable-sources",
+ ":opt-telephony-srcs",
+ ":opt-net-voip-srcs",
+ "core/java/**/*.logtags",
+ "**/package.html",
+ ],
+ visibility: ["//visibility:private"],
+}
+
build = [
"StubLibraries.bp",
"ApiDocs.bp",
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 5f4f3c2..a786bf4 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -58,13 +58,9 @@
stubs_defaults {
name: "framework-doc-stubs-default",
srcs: [
- ":framework-mime-sources",
- ":framework-non-updatable-sources",
+ ":framework-non-updatable-stub-sources",
":framework-updatable-sources",
- "core/java/**/*.logtags",
"test-base/src/**/*.java",
- ":opt-telephony-srcs",
- ":opt-net-voip-srcs",
":art.module.public.api{.public.stubs.source}",
":conscrypt.module.public.api{.public.stubs.source}",
":i18n.module.public.api{.public.stubs.source}",
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 9b43749..32123fd8 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -42,13 +42,7 @@
stubs_defaults {
name: "metalava-non-updatable-api-stubs-default",
- srcs: [
- ":framework-non-updatable-sources",
- "core/java/**/*.logtags",
- ":opt-telephony-srcs",
- ":opt-net-voip-srcs",
- "**/package.html",
- ],
+ srcs: [":framework-non-updatable-stub-sources"],
sdk_version: "none",
system_modules: "none",
java_version: "1.8",
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index 0f6468a..4dd1b79 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -32,13 +32,11 @@
import com.android.internal.util.Preconditions;
import java.io.Closeable;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -158,68 +156,16 @@
schemasPackageAccessibleBundles,
callbackExecutor,
callback);
- return;
- }
-
- try {
- // Migration process
- // 1. Generate the current and the final version map.
- // TODO(b/182855402) Release binder thread and move the heavy work into worker thread.
- AndroidFuture<AppSearchResult<GetSchemaResponse>> future = new AndroidFuture<>();
- getSchema(callbackExecutor, future::complete);
- AppSearchResult<GetSchemaResponse> getSchemaResult = future.get();
- if (!getSchemaResult.isSuccess()) {
- callback.accept(AppSearchResult.newFailedResult(getSchemaResult));
- return;
- }
- GetSchemaResponse getSchemaResponse = getSchemaResult.getResultValue();
- Set<AppSearchSchema> currentSchemas = getSchemaResponse.getSchemas();
- Map<String, Integer> currentVersionMap =
- SchemaMigrationUtil.buildVersionMap(currentSchemas,
- getSchemaResponse.getVersion());
- Map<String, Integer> finalVersionMap =
- SchemaMigrationUtil.buildVersionMap(request.getSchemas(), request.getVersion());
-
- // 2. SetSchema with forceOverride=false, to retrieve the list of incompatible/deleted
- // types.
- mService.setSchema(
- mPackageName,
- mDatabaseName,
+ } else {
+ setSchemaWithMigrations(
+ request,
schemaBundles,
- new ArrayList<>(request.getSchemasNotDisplayedBySystem()),
schemasPackageAccessibleBundles,
- /*forceOverride=*/ false,
- mUserId,
- request.getVersion(),
- new IAppSearchResultCallback.Stub() {
- public void onResult(AppSearchResult result) {
- callbackExecutor.execute(() -> {
- if (result.isSuccess()) {
- // TODO(b/183177268): once migration is implemented, run
- // it on workExecutor.
- try {
- Bundle bundle = (Bundle) result.getResultValue();
- SetSchemaResponse setSchemaResponse =
- new SetSchemaResponse(bundle);
- setSchemaMigration(
- request, setSchemaResponse, schemaBundles,
- schemasPackageAccessibleBundles, currentVersionMap,
- finalVersionMap, callback);
- } catch (Throwable t) {
- callback.accept(AppSearchResult.throwableToFailedResult(t));
- }
- } else {
- callback.accept(result);
- }
- });
- }
- });
- mIsMutated = true;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (Throwable t) {
- callback.accept(AppSearchResult.throwableToFailedResult(t));
+ workExecutor,
+ callbackExecutor,
+ callback);
}
+ mIsMutated = true;
}
/**
@@ -641,8 +587,28 @@
Objects.requireNonNull(executor);
Objects.requireNonNull(callback);
Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
- // TODO(b/182909475): Implement getStorageInfo
- throw new UnsupportedOperationException();
+ try {
+ mService.getStorageInfo(
+ mPackageName,
+ mDatabaseName,
+ mUserId,
+ new IAppSearchResultCallback.Stub() {
+ public void onResult(AppSearchResult result) {
+ executor.execute(() -> {
+ if (result.isSuccess()) {
+ Bundle responseBundle = (Bundle) result.getResultValue();
+ StorageInfo response =
+ new StorageInfo(responseBundle);
+ callback.accept(AppSearchResult.newSuccessfulResult(response));
+ } else {
+ callback.accept(result);
+ }
+ });
+ }
+ });
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -667,7 +633,8 @@
* <p>We only need one time {@link #setSchema} call for no-migration scenario by using the
* forceoverride in the request.
*/
- private void setSchemaNoMigrations(@NonNull SetSchemaRequest request,
+ private void setSchemaNoMigrations(
+ @NonNull SetSchemaRequest request,
@NonNull List<Bundle> schemaBundles,
@NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
@NonNull @CallbackExecutor Executor executor,
@@ -709,7 +676,6 @@
});
}
});
- mIsMutated = true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -721,86 +687,144 @@
* <p>First time {@link #setSchema} call with forceOverride is false gives us all incompatible
* changes. After trigger migrations, the second time call {@link #setSchema} will actually
* apply the changes.
- *
- * @param setSchemaResponse the result of the first setSchema call with forceOverride=false.
*/
- private void setSchemaMigration(@NonNull SetSchemaRequest request,
- @NonNull SetSchemaResponse setSchemaResponse,
+ private void setSchemaWithMigrations(
+ @NonNull SetSchemaRequest request,
@NonNull List<Bundle> schemaBundles,
@NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
- @NonNull Map<String, Integer> currentVersionMap, Map<String, Integer> finalVersionMap,
- @NonNull Consumer<AppSearchResult<SetSchemaResponse>> callback)
- throws AppSearchException, IOException, RemoteException, ExecutionException,
- InterruptedException {
- // 1. If forceOverride is false, check that all incompatible types will be migrated.
- // If some aren't we must throw an error, rather than proceeding and deleting those
- // types.
- if (!request.isForceOverride()) {
- Set<String> unmigratedTypes = SchemaMigrationUtil.getUnmigratedIncompatibleTypes(
- setSchemaResponse.getIncompatibleTypes(),
- request.getMigrators(),
- currentVersionMap,
- finalVersionMap);
- // check if there are any unmigrated types or deleted types. If there are, we will throw
- // an exception.
- // Since the force override is false, the schema will not have been set if there are any
- // incompatible or deleted types.
- checkDeletedAndIncompatible(setSchemaResponse.getDeletedTypes(),
- unmigratedTypes);
- }
-
- try (AppSearchMigrationHelper migrationHelper =
- new AppSearchMigrationHelper(mService, mUserId, currentVersionMap,
- finalVersionMap, mPackageName, mDatabaseName)) {
- Map<String, Migrator> migratorMap = request.getMigrators();
-
- // 2. Trigger migration for all migrators.
- // TODO(b/177266929) trigger migration for all types together rather than separately.
- Set<String> migratedTypes = new ArraySet<>();
- for (Map.Entry<String, Migrator> entry : migratorMap.entrySet()) {
- String schemaType = entry.getKey();
- Migrator migrator = entry.getValue();
- if (SchemaMigrationUtil.shouldTriggerMigration(
- schemaType, migrator, currentVersionMap, finalVersionMap)) {
- migrationHelper.queryAndTransform(schemaType, migrator);
- migratedTypes.add(schemaType);
+ @NonNull Executor workExecutor,
+ @NonNull @CallbackExecutor Executor callbackExecutor,
+ @NonNull Consumer<AppSearchResult<SetSchemaResponse>> callback) {
+ workExecutor.execute(() -> {
+ try {
+ // Migration process
+ // 1. Generate the current and the final version map.
+ AndroidFuture<AppSearchResult<GetSchemaResponse>> getSchemaFuture =
+ new AndroidFuture<>();
+ getSchema(callbackExecutor, getSchemaFuture::complete);
+ AppSearchResult<GetSchemaResponse> getSchemaResult = getSchemaFuture.get();
+ if (!getSchemaResult.isSuccess()) {
+ callbackExecutor.execute(() ->
+ callback.accept(AppSearchResult.newFailedResult(getSchemaResult)));
+ return;
}
- }
+ GetSchemaResponse getSchemaResponse = getSchemaResult.getResultValue();
+ Set<AppSearchSchema> currentSchemas = getSchemaResponse.getSchemas();
+ Map<String, Integer> currentVersionMap = SchemaMigrationUtil.buildVersionMap(
+ currentSchemas, getSchemaResponse.getVersion());
+ Map<String, Integer> finalVersionMap = SchemaMigrationUtil.buildVersionMap(
+ request.getSchemas(), request.getVersion());
- // 3. SetSchema a second time with forceOverride=true if the first attempted failed.
- if (!setSchemaResponse.getIncompatibleTypes().isEmpty()
- || !setSchemaResponse.getDeletedTypes().isEmpty()) {
- AndroidFuture<AppSearchResult<SetSchemaResponse>> future = new AndroidFuture<>();
- // only trigger second setSchema() call if the first one is fail.
+ // 2. SetSchema with forceOverride=false, to retrieve the list of
+ // incompatible/deleted types.
+ AndroidFuture<AppSearchResult<Bundle>> setSchemaFuture = new AndroidFuture<>();
mService.setSchema(
mPackageName,
mDatabaseName,
schemaBundles,
new ArrayList<>(request.getSchemasNotDisplayedBySystem()),
schemasPackageAccessibleBundles,
- /*forceOverride=*/ true,
+ /*forceOverride=*/ false,
mUserId,
request.getVersion(),
new IAppSearchResultCallback.Stub() {
- @Override
- public void onResult(AppSearchResult result) throws RemoteException {
- future.complete(result);
+ public void onResult(AppSearchResult result) {
+ setSchemaFuture.complete(result);
}
});
- AppSearchResult<SetSchemaResponse> secondSetSchemaResult = future.get();
- if (!secondSetSchemaResult.isSuccess()) {
- // we failed to set the schema in second time with force override = true, which
- // is an impossible case. Since we only swallow the incompatible error in the
- // first setSchema call, all other errors will be thrown at the first time.
- callback.accept(secondSetSchemaResult);
+ AppSearchResult<Bundle> setSchemaResult = setSchemaFuture.get();
+ if (!setSchemaResult.isSuccess()) {
+ callbackExecutor.execute(() ->
+ callback.accept(AppSearchResult.newFailedResult(setSchemaResult)));
return;
}
- }
+ SetSchemaResponse setSchemaResponse =
+ new SetSchemaResponse(setSchemaResult.getResultValue());
- SetSchemaResponse.Builder responseBuilder = setSchemaResponse.toBuilder()
- .addMigratedTypes(migratedTypes);
- callback.accept(migrationHelper.putMigratedDocuments(responseBuilder));
- }
+ // 1. If forceOverride is false, check that all incompatible types will be migrated.
+ // If some aren't we must throw an error, rather than proceeding and deleting those
+ // types.
+ if (!request.isForceOverride()) {
+ Set<String> unmigratedTypes =
+ SchemaMigrationUtil.getUnmigratedIncompatibleTypes(
+ setSchemaResponse.getIncompatibleTypes(),
+ request.getMigrators(),
+ currentVersionMap,
+ finalVersionMap);
+
+ // check if there are any unmigrated types or deleted types. If there are, we
+ // will throw an exception.
+ // Since the force override is false, the schema will not have been set if there
+ // are any incompatible or deleted types.
+ checkDeletedAndIncompatible(
+ setSchemaResponse.getDeletedTypes(), unmigratedTypes);
+ }
+
+ try (AppSearchMigrationHelper migrationHelper =
+ new AppSearchMigrationHelper(
+ mService, mUserId, currentVersionMap, finalVersionMap,
+ mPackageName, mDatabaseName)) {
+ Map<String, Migrator> migratorMap = request.getMigrators();
+
+ // 2. Trigger migration for all migrators.
+ // TODO(b/177266929) trigger migration for all types together rather than
+ // separately.
+ Set<String> migratedTypes = new ArraySet<>();
+ for (Map.Entry<String, Migrator> entry : migratorMap.entrySet()) {
+ String schemaType = entry.getKey();
+ Migrator migrator = entry.getValue();
+ if (SchemaMigrationUtil.shouldTriggerMigration(
+ schemaType, migrator, currentVersionMap, finalVersionMap)) {
+ migrationHelper.queryAndTransform(schemaType, migrator);
+ migratedTypes.add(schemaType);
+ }
+ }
+
+ // 3. SetSchema a second time with forceOverride=true if the first attempted
+ // failed.
+ if (!setSchemaResponse.getIncompatibleTypes().isEmpty()
+ || !setSchemaResponse.getDeletedTypes().isEmpty()) {
+ AndroidFuture<AppSearchResult<Bundle>> setSchema2Future =
+ new AndroidFuture<>();
+ // only trigger second setSchema() call if the first one is fail.
+ mService.setSchema(
+ mPackageName,
+ mDatabaseName,
+ schemaBundles,
+ new ArrayList<>(request.getSchemasNotDisplayedBySystem()),
+ schemasPackageAccessibleBundles,
+ /*forceOverride=*/ true,
+ request.getVersion(),
+ mUserId,
+ new IAppSearchResultCallback.Stub() {
+ @Override
+ public void onResult(AppSearchResult result) {
+ setSchema2Future.complete(result);
+ }
+ });
+ AppSearchResult<Bundle> setSchema2Result = setSchema2Future.get();
+ if (!setSchema2Result.isSuccess()) {
+ // we failed to set the schema in second time with forceOverride = true,
+ // which is an impossible case. Since we only swallow the incompatible
+ // error in the first setSchema call, all other errors will be thrown at
+ // the first time.
+ callbackExecutor.execute(() -> callback.accept(
+ AppSearchResult.newFailedResult(setSchemaResult)));
+ return;
+ }
+ }
+
+ SetSchemaResponse.Builder responseBuilder = setSchemaResponse.toBuilder()
+ .addMigratedTypes(migratedTypes);
+ AppSearchResult<SetSchemaResponse> putResult =
+ migrationHelper.putMigratedDocuments(responseBuilder);
+ callbackExecutor.execute(() -> callback.accept(putResult));
+ }
+ } catch (Throwable t) {
+ callbackExecutor.execute(() -> callback.accept(
+ AppSearchResult.throwableToFailedResult(t)));
+ }
+ });
}
/** Checks the setSchema() call won't delete any types or has incompatible types. */
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index 48c397f..a8ac27c 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -307,6 +307,22 @@
in IAppSearchResultCallback callback);
/**
+ * Gets the storage info.
+ *
+ * @param packageName The name of the package to get the storage info for.
+ * @param databaseName The databaseName to get the storage info for.
+ * @param userId Id of the calling user
+ * @param callback {@link IAppSearchResultCallback#onResult} will be called with an
+ * {@link AppSearchResult}<{@link Bundle}>, where the value is a
+ * {@link StorageInfo}.
+ */
+ void getStorageInfo(
+ in String packageName,
+ in String databaseName,
+ in int userId,
+ in IAppSearchResultCallback callback);
+
+ /**
* Persists all update/delete requests to the disk.
*
* @param userId Id of the calling user
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 91ed6cd..877dacb 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -33,6 +33,7 @@
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
import android.app.appsearch.SetSchemaResponse;
+import android.app.appsearch.StorageInfo;
import android.content.Context;
import android.content.pm.PackageManagerInternal;
import android.os.Binder;
@@ -159,7 +160,7 @@
Preconditions.checkNotNull(packageName);
Preconditions.checkNotNull(databaseName);
Preconditions.checkNotNull(callback);
- int callingUid = Binder.getCallingUidOrThrow();
+ int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
final long callingIdentity = Binder.clearCallingIdentity();
try {
@@ -186,7 +187,7 @@
Preconditions.checkNotNull(packageName);
Preconditions.checkNotNull(databaseName);
Preconditions.checkNotNull(callback);
- int callingUid = Binder.getCallingUidOrThrow();
+ int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
final long callingIdentity = Binder.clearCallingIdentity();
try {
@@ -610,8 +611,36 @@
}
@Override
+ public void getStorageInfo(
+ @NonNull String packageName,
+ @NonNull String databaseName,
+ @UserIdInt int userId,
+ @NonNull IAppSearchResultCallback callback) {
+ Preconditions.checkNotNull(packageName);
+ Preconditions.checkNotNull(databaseName);
+ Preconditions.checkNotNull(callback);
+ int callingUid = Binder.getCallingUid();
+ int callingUserId = handleIncomingUser(userId, callingUid);
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ verifyUserUnlocked(callingUserId);
+ verifyCallingPackage(callingUid, packageName);
+ AppSearchImpl impl =
+ mImplInstanceManager.getAppSearchImpl(callingUserId);
+ StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName, databaseName);
+ Bundle storageInfoBundle = storageInfo.getBundle();
+ invokeCallbackOnResult(
+ callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
+ } catch (Throwable t) {
+ invokeCallbackOnError(callback, t);
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
+ @Override
public void persistToDisk(@UserIdInt int userId) {
- int callingUid = Binder.getCallingUidOrThrow();
+ int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
final long callingIdentity = Binder.clearCallingIdentity();
try {
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
index 38500af..22ee501 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
@@ -258,7 +258,8 @@
public @NonNull ParcelFileDescriptor openBlob(@NonNull BlobHandle blobHandle)
throws IOException {
try {
- return mService.openBlob(blobHandle, mContext.getOpPackageName());
+ return mService.openBlob(blobHandle, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
throw new RuntimeException(e);
@@ -315,7 +316,7 @@
@CurrentTimeMillisLong long leaseExpiryTimeMillis) throws IOException {
try {
mService.acquireLease(blobHandle, descriptionResId, null, leaseExpiryTimeMillis,
- mContext.getOpPackageName());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
e.maybeRethrow(LimitExceededException.class);
@@ -378,7 +379,7 @@
@CurrentTimeMillisLong long leaseExpiryTimeMillis) throws IOException {
try {
mService.acquireLease(blobHandle, INVALID_RES_ID, description, leaseExpiryTimeMillis,
- mContext.getOpPackageName());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
e.maybeRethrow(LimitExceededException.class);
@@ -497,7 +498,8 @@
*/
public void releaseLease(@NonNull BlobHandle blobHandle) throws IOException {
try {
- mService.releaseLease(blobHandle, mContext.getOpPackageName());
+ mService.releaseLease(blobHandle, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
throw new RuntimeException(e);
@@ -602,7 +604,8 @@
@Nullable
public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle) throws IOException {
try {
- return mService.getLeaseInfo(blobHandle, mContext.getOpPackageName());
+ return mService.getLeaseInfo(blobHandle, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
throw new RuntimeException(e);
@@ -897,6 +900,64 @@
}
/**
+ * Allow apps with location permission to access this blob data once it is committed using
+ * a {@link BlobHandle} representing the blob.
+ *
+ * <p> This needs to be called before committing the blob using
+ * {@link #commit(Executor, Consumer)}.
+ *
+ * Note that if a caller allows access to the blob using this API in addition to other APIs
+ * like {@link #allowPackageAccess(String, byte[])}, then apps satisfying any one of these
+ * access conditions will be allowed to access the blob.
+ *
+ * @param permissionName the name of the location permission that needs to be granted
+ * for the app. This can be either one of
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
+ *
+ * @throws IOException when there is an I/O error while changing the access.
+ * @throws SecurityException when the caller is not the owner of the session.
+ * @throws IllegalStateException when the caller tries to change access for a blob which is
+ * already committed.
+ */
+ public void allowPackagesWithLocationPermission(@NonNull String permissionName)
+ throws IOException {
+ try {
+ mSession.allowPackagesWithLocationPermission(permissionName);
+ } catch (ParcelableException e) {
+ e.maybeRethrow(IOException.class);
+ throw new RuntimeException(e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns {@code true} if access has been allowed for apps with location permission by
+ * using {@link #allowPackagesWithLocationPermission(String)}.
+ *
+ * @param permissionName the name of the location permission that needs to be granted
+ * for the app. This can be either one of
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
+ *
+ * @throws IOException when there is an I/O error while getting the access type.
+ * @throws IllegalStateException when the caller tries to get access type from a session
+ * which is closed or abandoned.
+ */
+ public boolean arePackagesWithLocationPermissionAllowed(@NonNull String permissionName)
+ throws IOException {
+ try {
+ return mSession.arePackagesWithLocationPermissionAllowed(permissionName);
+ } catch (ParcelableException e) {
+ e.maybeRethrow(IOException.class);
+ throw new RuntimeException(e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Commit the file that was written so far to this session to the blob store maintained by
* the system.
*
diff --git a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
index 39a9fb4..db6cb5c9 100644
--- a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
+++ b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
@@ -25,12 +25,13 @@
interface IBlobStoreManager {
long createSession(in BlobHandle handle, in String packageName);
IBlobStoreSession openSession(long sessionId, in String packageName);
- ParcelFileDescriptor openBlob(in BlobHandle handle, in String packageName);
+ ParcelFileDescriptor openBlob(in BlobHandle handle, in String packageName,
+ in String attributionTag);
void abandonSession(long sessionId, in String packageName);
void acquireLease(in BlobHandle handle, int descriptionResId, in CharSequence description,
- long leaseTimeoutMillis, in String packageName);
- void releaseLease(in BlobHandle handle, in String packageName);
+ long leaseTimeoutMillis, in String packageName, in String attributionTag);
+ void releaseLease(in BlobHandle handle, in String packageName, in String attributionTag);
long getRemainingLeaseQuotaBytes(String packageName);
void waitForIdle(in RemoteCallback callback);
@@ -39,5 +40,6 @@
void deleteBlob(long blobId);
List<BlobHandle> getLeasedBlobs(in String packageName);
- LeaseInfo getLeaseInfo(in BlobHandle blobHandle, in String packageName);
+ LeaseInfo getLeaseInfo(in BlobHandle blobHandle, in String packageName,
+ in String attributionTag);
}
\ No newline at end of file
diff --git a/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl b/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
index 4035b96..e3ccfb8 100644
--- a/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
+++ b/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
@@ -26,10 +26,12 @@
void allowPackageAccess(in String packageName, in byte[] certificate);
void allowSameSignatureAccess();
void allowPublicAccess();
+ void allowPackagesWithLocationPermission(in String permissionName);
boolean isPackageAccessAllowed(in String packageName, in byte[] certificate);
boolean isSameSignatureAccessAllowed();
boolean isPublicAccessAllowed();
+ boolean arePackagesWithLocationPermissionAllowed(in String permissionName);
long getSize();
void close();
diff --git a/apex/blobstore/framework/java/android/app/blob/XmlTags.java b/apex/blobstore/framework/java/android/app/blob/XmlTags.java
index bfc5826..6e4b2f7 100644
--- a/apex/blobstore/framework/java/android/app/blob/XmlTags.java
+++ b/apex/blobstore/framework/java/android/app/blob/XmlTags.java
@@ -38,6 +38,7 @@
public static final String ATTR_TYPE = "t";
public static final String TAG_ALLOWED_PACKAGE = "wl";
public static final String ATTR_CERTIFICATE = "ct";
+ public static final String TAG_ALLOWED_PERMISSION = "ap";
// For BlobHandle
public static final String TAG_BLOB_HANDLE = "bh";
@@ -55,4 +56,7 @@
public static final String TAG_LEASEE = "l";
public static final String ATTR_DESCRIPTION_RES_NAME = "rn";
public static final String ATTR_DESCRIPTION = "d";
+
+ // Generic
+ public static final String ATTR_VALUE = "val";
}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
index 4a527ad..ca588c5 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
@@ -15,18 +15,29 @@
*/
package com.android.server.blob;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.app.blob.XmlTags.ATTR_CERTIFICATE;
import static android.app.blob.XmlTags.ATTR_PACKAGE;
import static android.app.blob.XmlTags.ATTR_TYPE;
+import static android.app.blob.XmlTags.ATTR_VALUE;
import static android.app.blob.XmlTags.TAG_ALLOWED_PACKAGE;
+import static android.app.blob.XmlTags.TAG_ALLOWED_PERMISSION;
+
+import static com.android.server.blob.BlobStoreConfig.TAG;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.permission.PermissionManager;
import android.util.ArraySet;
import android.util.Base64;
import android.util.DebugUtils;
+import android.util.Slog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
@@ -53,21 +64,27 @@
ACCESS_TYPE_PUBLIC,
ACCESS_TYPE_SAME_SIGNATURE,
ACCESS_TYPE_ALLOWLIST,
+ ACCESS_TYPE_LOCATION_PERMISSION,
})
@interface AccessType {}
public static final int ACCESS_TYPE_PRIVATE = 1 << 0;
public static final int ACCESS_TYPE_PUBLIC = 1 << 1;
public static final int ACCESS_TYPE_SAME_SIGNATURE = 1 << 2;
public static final int ACCESS_TYPE_ALLOWLIST = 1 << 3;
+ public static final int ACCESS_TYPE_LOCATION_PERMISSION = 1 << 4;
private int mAccessType = ACCESS_TYPE_PRIVATE;
private final ArraySet<PackageIdentifier> mAllowedPackages = new ArraySet<>();
+ private final ArraySet<String> mAllowedPermissions = new ArraySet<>();
void allow(BlobAccessMode other) {
if ((other.mAccessType & ACCESS_TYPE_ALLOWLIST) != 0) {
mAllowedPackages.addAll(other.mAllowedPackages);
}
+ if ((other.mAccessType & ACCESS_TYPE_LOCATION_PERMISSION) != 0) {
+ mAllowedPermissions.addAll(other.mAllowedPermissions);
+ }
mAccessType |= other.mAccessType;
}
@@ -84,6 +101,11 @@
mAllowedPackages.add(PackageIdentifier.create(packageName, certificate));
}
+ void allowPackagesWithLocationPermission(@NonNull String permissionName) {
+ mAccessType |= ACCESS_TYPE_LOCATION_PERMISSION;
+ mAllowedPermissions.add(permissionName);
+ }
+
boolean isPublicAccessAllowed() {
return (mAccessType & ACCESS_TYPE_PUBLIC) != 0;
}
@@ -99,8 +121,15 @@
return mAllowedPackages.contains(PackageIdentifier.create(packageName, certificate));
}
- boolean isAccessAllowedForCaller(Context context,
- @NonNull String callingPackage, @NonNull String committerPackage) {
+ boolean arePackagesWithLocationPermissionAllowed(@NonNull String permissionName) {
+ if ((mAccessType & ACCESS_TYPE_LOCATION_PERMISSION) == 0) {
+ return false;
+ }
+ return mAllowedPermissions.contains(permissionName);
+ }
+
+ boolean isAccessAllowedForCaller(Context context, @NonNull String callingPackage,
+ @NonNull String committerPackage, int callingUid, @Nullable String attributionTag) {
if ((mAccessType & ACCESS_TYPE_PUBLIC) != 0) {
return true;
}
@@ -124,9 +153,37 @@
}
}
+ if ((mAccessType & ACCESS_TYPE_LOCATION_PERMISSION) != 0) {
+ final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+ for (int i = 0; i < mAllowedPermissions.size(); ++i) {
+ final String permission = mAllowedPermissions.valueAt(i);
+ if (PermissionManager.checkPackageNamePermission(permission, callingPackage,
+ UserHandle.getUserId(callingUid)) != PackageManager.PERMISSION_GRANTED) {
+ continue;
+ }
+ // TODO: Add appropriate message
+ if (appOpsManager.noteOpNoThrow(getAppOp(permission), callingUid, callingPackage,
+ attributionTag, null /* message */) == AppOpsManager.MODE_ALLOWED) {
+ return true;
+ }
+ }
+ }
+
return false;
}
+ private static String getAppOp(String permission) {
+ switch (permission) {
+ case ACCESS_FINE_LOCATION:
+ return AppOpsManager.OPSTR_FINE_LOCATION;
+ case ACCESS_COARSE_LOCATION:
+ return AppOpsManager.OPSTR_COARSE_LOCATION;
+ default:
+ Slog.w(TAG, "Unknown permission found: " + permission);
+ return null;
+ }
+ }
+
int getAccessType() {
return mAccessType;
}
@@ -148,6 +205,16 @@
}
fout.decreaseIndent();
}
+ fout.print("Allowed permissions:");
+ if (mAllowedPermissions.isEmpty()) {
+ fout.println(" (Empty)");
+ } else {
+ fout.increaseIndent();
+ for (int i = 0, count = mAllowedPermissions.size(); i < count; ++i) {
+ fout.println(mAllowedPermissions.valueAt(i).toString());
+ }
+ fout.decreaseIndent();
+ }
}
void writeToXml(@NonNull XmlSerializer out) throws IOException {
@@ -159,6 +226,12 @@
XmlUtils.writeByteArrayAttribute(out, ATTR_CERTIFICATE, packageIdentifier.certificate);
out.endTag(null, TAG_ALLOWED_PACKAGE);
}
+ for (int i = 0, count = mAllowedPermissions.size(); i < count; ++i) {
+ out.startTag(null, TAG_ALLOWED_PERMISSION);
+ final String permission = mAllowedPermissions.valueAt(i);
+ XmlUtils.writeStringAttribute(out, ATTR_VALUE, permission);
+ out.endTag(null, TAG_ALLOWED_PERMISSION);
+ }
}
@NonNull
@@ -176,6 +249,10 @@
final byte[] certificate = XmlUtils.readByteArrayAttribute(in, ATTR_CERTIFICATE);
blobAccessMode.allowPackageAccess(packageName, certificate);
}
+ if (TAG_ALLOWED_PERMISSION.equals(in.getName())) {
+ final String permission = XmlUtils.readStringAttribute(in, ATTR_VALUE);
+ blobAccessMode.allowPackagesWithLocationPermission(permission);
+ }
}
return blobAccessMode;
}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
index fb02e96..8b12beb 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
@@ -229,7 +229,8 @@
return getBlobFile().length();
}
- boolean isAccessAllowedForCaller(@NonNull String callingPackage, int callingUid) {
+ boolean isAccessAllowedForCaller(@NonNull String callingPackage, int callingUid,
+ @Nullable String attributionTag) {
// Don't allow the blob to be accessed after it's expiry time has passed.
if (getBlobHandle().isExpired()) {
return false;
@@ -254,7 +255,7 @@
// Check if the caller is allowed access as per the access mode specified
// by the committer.
if (committer.blobAccessMode.isAccessAllowedForCaller(mContext,
- callingPackage, committer.packageName)) {
+ callingPackage, committer.packageName, callingUid, attributionTag)) {
return true;
}
}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index f77f6c6..0e73547 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -402,12 +402,12 @@
}
private ParcelFileDescriptor openBlobInternal(BlobHandle blobHandle, int callingUid,
- String callingPackage) throws IOException {
+ String callingPackage, String attributionTag) throws IOException {
synchronized (mBlobsLock) {
final BlobMetadata blobMetadata = getUserBlobsLocked(UserHandle.getUserId(callingUid))
.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
- callingPackage, callingUid)) {
+ callingPackage, callingUid, attributionTag)) {
if (blobMetadata == null) {
FrameworkStatsLog.write(FrameworkStatsLog.BLOB_OPENED, callingUid,
INVALID_BLOB_ID, INVALID_BLOB_SIZE,
@@ -455,7 +455,7 @@
private void acquireLeaseInternal(BlobHandle blobHandle, int descriptionResId,
CharSequence description, long leaseExpiryTimeMillis,
- int callingUid, String callingPackage) {
+ int callingUid, String callingPackage, String attributionTag) {
synchronized (mBlobsLock) {
final int leasesCount = getLeasedBlobsCountLocked(callingUid, callingPackage);
if (leasesCount >= getMaxLeasedBlobs()) {
@@ -468,7 +468,7 @@
final BlobMetadata blobMetadata = getUserBlobsLocked(UserHandle.getUserId(callingUid))
.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
- callingPackage, callingUid)) {
+ callingPackage, callingUid, attributionTag)) {
if (blobMetadata == null) {
FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
INVALID_BLOB_ID, INVALID_BLOB_SIZE,
@@ -527,13 +527,13 @@
}
private void releaseLeaseInternal(BlobHandle blobHandle, int callingUid,
- String callingPackage) {
+ String callingPackage, String attributionTag) {
synchronized (mBlobsLock) {
final ArrayMap<BlobHandle, BlobMetadata> userBlobs =
getUserBlobsLocked(UserHandle.getUserId(callingUid));
final BlobMetadata blobMetadata = userBlobs.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
- callingPackage, callingUid)) {
+ callingPackage, callingUid, attributionTag)) {
throw new SecurityException("Caller not allowed to access " + blobHandle
+ "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
}
@@ -634,12 +634,12 @@
}
private LeaseInfo getLeaseInfoInternal(BlobHandle blobHandle,
- int callingUid, @NonNull String callingPackage) {
+ int callingUid, @NonNull String callingPackage, String attributionTag) {
synchronized (mBlobsLock) {
final BlobMetadata blobMetadata = getUserBlobsLocked(UserHandle.getUserId(callingUid))
.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
- callingPackage, callingUid)) {
+ callingPackage, callingUid, attributionTag)) {
throw new SecurityException("Caller not allowed to access " + blobHandle
+ "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
}
@@ -1465,7 +1465,7 @@
@Override
public ParcelFileDescriptor openBlob(@NonNull BlobHandle blobHandle,
- @NonNull String packageName) {
+ @NonNull String packageName, @Nullable String attributionTag) {
Objects.requireNonNull(blobHandle, "blobHandle must not be null");
blobHandle.assertIsValid();
Objects.requireNonNull(packageName, "packageName must not be null");
@@ -1480,7 +1480,7 @@
}
try {
- return openBlobInternal(blobHandle, callingUid, packageName);
+ return openBlobInternal(blobHandle, callingUid, packageName, attributionTag);
} catch (IOException e) {
throw ExceptionUtils.wrap(e);
}
@@ -1489,7 +1489,8 @@
@Override
public void acquireLease(@NonNull BlobHandle blobHandle, @IdRes int descriptionResId,
@Nullable CharSequence description,
- @CurrentTimeSecondsLong long leaseExpiryTimeMillis, @NonNull String packageName) {
+ @CurrentTimeSecondsLong long leaseExpiryTimeMillis, @NonNull String packageName,
+ @Nullable String attributionTag) {
Objects.requireNonNull(blobHandle, "blobHandle must not be null");
blobHandle.assertIsValid();
Preconditions.checkArgument(
@@ -1513,7 +1514,7 @@
try {
acquireLeaseInternal(blobHandle, descriptionResId, description,
- leaseExpiryTimeMillis, callingUid, packageName);
+ leaseExpiryTimeMillis, callingUid, packageName, attributionTag);
} catch (Resources.NotFoundException e) {
throw new IllegalArgumentException(e);
} catch (LimitExceededException e) {
@@ -1522,7 +1523,8 @@
}
@Override
- public void releaseLease(@NonNull BlobHandle blobHandle, @NonNull String packageName) {
+ public void releaseLease(@NonNull BlobHandle blobHandle, @NonNull String packageName,
+ @Nullable String attributionTag) {
Objects.requireNonNull(blobHandle, "blobHandle must not be null");
blobHandle.assertIsValid();
Objects.requireNonNull(packageName, "packageName must not be null");
@@ -1536,7 +1538,7 @@
+ "callingUid=" + callingUid + ", callingPackage=" + packageName);
}
- releaseLeaseInternal(blobHandle, callingUid, packageName);
+ releaseLeaseInternal(blobHandle, callingUid, packageName, attributionTag);
}
@Override
@@ -1606,7 +1608,8 @@
@Override
@Nullable
- public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle, @NonNull String packageName) {
+ public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle, @NonNull String packageName,
+ @Nullable String attributionTag) {
Objects.requireNonNull(blobHandle, "blobHandle must not be null");
blobHandle.assertIsValid();
Objects.requireNonNull(packageName, "packageName must not be null");
@@ -1620,7 +1623,7 @@
+ "callingUid=" + callingUid + ", callingPackage=" + packageName);
}
- return getLeaseInfoInternal(blobHandle, callingUid, packageName);
+ return getLeaseInfoInternal(blobHandle, callingUid, packageName, attributionTag);
}
@Override
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
index fe68882..2c3f682 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
@@ -15,6 +15,8 @@
*/
package com.android.server.blob;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.app.blob.BlobStoreManager.COMMIT_RESULT_ERROR;
import static android.app.blob.XmlTags.ATTR_CREATION_TIME_MS;
import static android.app.blob.XmlTags.ATTR_ID;
@@ -366,6 +368,21 @@
}
@Override
+ public void allowPackagesWithLocationPermission(@NonNull String permissionName) {
+ assertCallerIsOwner();
+ Preconditions.checkArgument(ACCESS_FINE_LOCATION.equals(permissionName)
+ || ACCESS_COARSE_LOCATION.equals(permissionName),
+ "permissionName is unknown: " + permissionName);
+ synchronized (mSessionLock) {
+ if (mState != STATE_OPENED) {
+ throw new IllegalStateException("Not allowed to change access type in state: "
+ + stateToString(mState));
+ }
+ mBlobAccessMode.allowPackagesWithLocationPermission(permissionName);
+ }
+ }
+
+ @Override
public boolean isPackageAccessAllowed(@NonNull String packageName,
@NonNull byte[] certificate) {
assertCallerIsOwner();
@@ -406,6 +423,21 @@
}
@Override
+ public boolean arePackagesWithLocationPermissionAllowed(@NonNull String permissionName) {
+ assertCallerIsOwner();
+ Preconditions.checkArgument(ACCESS_FINE_LOCATION.equals(permissionName)
+ || ACCESS_COARSE_LOCATION.equals(permissionName),
+ "permissionName is unknown: " + permissionName);
+ synchronized (mSessionLock) {
+ if (mState != STATE_OPENED) {
+ throw new IllegalStateException("Not allowed to change access type in state: "
+ + stateToString(mState));
+ }
+ return mBlobAccessMode.arePackagesWithLocationPermissionAllowed(permissionName);
+ }
+ }
+
+ @Override
public void close() {
closeSession(STATE_CLOSED, false /* sendCallback */);
}
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
index fea7a11..cb1fccf 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
@@ -83,6 +83,12 @@
}
/**
+ * Does not place the app on any temporary allow list. Nullifies the previous call to
+ * {@link android.app.BroadcastOptions#setTemporaryAppAllowlist(long, int, int, String)}.
+ * Note: this will not remove the receiver app from the temp allow list.
+ */
+ public static final int TEMPORARY_ALLOW_LIST_TYPE_NONE = -1;
+ /**
* Allow the temp allow list behavior, plus allow foreground service start from background.
*/
public static final int TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0;
@@ -96,6 +102,7 @@
* @hide
*/
@IntDef(flag = true, prefix = { "TEMPORARY_ALLOW_LIST_TYPE_" }, value = {
+ TEMPORARY_ALLOW_LIST_TYPE_NONE,
TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED,
})
diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
index 9bd57a1..a9ca5cf 100644
--- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
@@ -17,9 +17,9 @@
package com.android.server;
import android.annotation.Nullable;
-import android.os.PowerWhitelistManager;
-import android.os.PowerWhitelistManager.ReasonCode;
-import android.os.PowerWhitelistManager.TempAllowListType;
+import android.os.PowerExemptionManager;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
import com.android.server.deviceidle.IDeviceIdleConstraint;
@@ -35,7 +35,7 @@
/**
* Same as {@link #addPowerSaveTempWhitelistApp(int, String, long, int, boolean, int, String)}
- * with {@link PowerWhitelistManager#TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED}.
+ * with {@link PowerExemptionManager#TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED}.
*/
void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
long durationMs, int userId, boolean sync, @ReasonCode int reasonCode,
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 667fc60..57c8300 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -16,9 +16,9 @@
package com.android.server;
-import static android.os.PowerWhitelistManager.REASON_SHELL;
-import static android.os.PowerWhitelistManager.REASON_UNKNOWN;
-import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerExemptionManager.REASON_SHELL;
+import static android.os.PowerExemptionManager.REASON_UNKNOWN;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
import static android.os.Process.INVALID_UID;
import android.Manifest;
@@ -58,11 +58,11 @@
import android.os.IDeviceIdleController;
import android.os.Looper;
import android.os.Message;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
-import android.os.PowerWhitelistManager.ReasonCode;
-import android.os.PowerWhitelistManager.TempAllowListType;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -1947,7 +1947,7 @@
long durationMs, int userId, boolean sync, @ReasonCode int reasonCode,
@Nullable String reason) {
addPowerSaveTempAllowlistAppInternal(callingUid, packageName, durationMs,
- TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
userId, sync, reasonCode, reason);
}
@@ -2706,7 +2706,7 @@
final long token = Binder.clearCallingIdentity();
try {
addPowerSaveTempAllowlistAppInternal(callingUid,
- packageName, duration, TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ packageName, duration, TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
userId, true, reasonCode, reason);
} finally {
Binder.restoreCallingIdentity(token);
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 3c9496f..901daa7 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -472,8 +472,7 @@
private static final long DEFAULT_ALLOW_WHILE_IDLE_WINDOW = 60 * 60 * 1000; // 1 hour.
private static final long DEFAULT_ALLOW_WHILE_IDLE_COMPAT_WINDOW = 9 * 60 * 1000; // 9 mins.
- // TODO (b/171306433): Change to true by default.
- private static final boolean DEFAULT_CRASH_NON_CLOCK_APPS = false;
+ private static final boolean DEFAULT_CRASH_NON_CLOCK_APPS = true;
private static final long DEFAULT_PRIORITY_ALARM_DELAY = 9 * 60_000;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 8ac237e..af867b9 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -746,11 +746,14 @@
Slog.d(TAG, "Removing jobs for package " + pkgName
+ " in user " + userId);
}
- // By the time we get here, the process should have already
- // been stopped, so the app wouldn't get the stop reason,
- // so just put USER instead of UNINSTALL or DISABLED.
- cancelJobsForPackageAndUid(pkgName, pkgUid,
- JobParameters.STOP_REASON_USER, "app disabled");
+ synchronized (mLock) {
+ // By the time we get here, the process should have
+ // already been stopped, so the app wouldn't get the
+ // stop reason, so just put USER instead of UNINSTALL
+ // or DISABLED.
+ cancelJobsForPackageAndUidLocked(pkgName, pkgUid,
+ JobParameters.STOP_REASON_USER, "app disabled");
+ }
}
} catch (RemoteException|IllegalArgumentException e) {
/*
@@ -791,9 +794,9 @@
// By the time we get here, the process should have already
// been stopped, so the app wouldn't get the stop reason,
// so just put USER instead of UNINSTALL or DISABLED.
- cancelJobsForPackageAndUid(pkgName, uidRemoved,
- JobParameters.STOP_REASON_USER, "app uninstalled");
synchronized (mLock) {
+ cancelJobsForPackageAndUidLocked(pkgName, uidRemoved,
+ JobParameters.STOP_REASON_USER, "app uninstalled");
for (int c = 0; c < mControllers.size(); ++c) {
mControllers.get(c).onAppRemovedLocked(pkgName, pkgUid);
}
@@ -812,8 +815,8 @@
if (DEBUG) {
Slog.d(TAG, "Removing jobs for user: " + userId);
}
- cancelJobsForUser(userId);
synchronized (mLock) {
+ cancelJobsForUserLocked(userId);
for (int c = 0; c < mControllers.size(); ++c) {
mControllers.get(c).onUserRemovedLocked(userId);
}
@@ -844,8 +847,10 @@
if (DEBUG) {
Slog.d(TAG, "Removing jobs for pkg " + pkgName + " at uid " + pkgUid);
}
- cancelJobsForPackageAndUid(pkgName, pkgUid,
- JobParameters.STOP_REASON_USER, "app force stopped");
+ synchronized (mLock) {
+ cancelJobsForPackageAndUidLocked(pkgName, pkgUid,
+ JobParameters.STOP_REASON_USER, "app force stopped");
+ }
}
}
}
@@ -1046,7 +1051,7 @@
FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED,
uId, null, jobStatus.getBatteryName(),
FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__SCHEDULED,
- JobProtoEnums.STOP_REASON_CANCELLED, jobStatus.getStandbyBucket(),
+ JobProtoEnums.STOP_REASON_UNKNOWN, jobStatus.getStandbyBucket(),
jobStatus.getJobId(),
jobStatus.hasChargingConstraint(),
jobStatus.hasBatteryNotLowConstraint(),
@@ -1055,7 +1060,9 @@
jobStatus.hasDeadlineConstraint(),
jobStatus.hasIdleConstraint(),
jobStatus.hasConnectivityConstraint(),
- jobStatus.hasContentTriggerConstraint());
+ jobStatus.hasContentTriggerConstraint(),
+ jobStatus.isRequestedExpeditedJob(),
+ /* isRunningAsExpeditedJob */ false);
// If the job is immediately ready to run, then we can just immediately
// put it in the pending list and try to schedule it. This is especially
@@ -1104,16 +1111,14 @@
}
}
- void cancelJobsForUser(int userHandle) {
- synchronized (mLock) {
- final List<JobStatus> jobsForUser = mJobs.getJobsByUser(userHandle);
- for (int i=0; i<jobsForUser.size(); i++) {
- JobStatus toRemove = jobsForUser.get(i);
- // By the time we get here, the process should have already been stopped, so the
- // app wouldn't get the stop reason, so just put USER instead of UNINSTALL.
- cancelJobImplLocked(toRemove, null, JobParameters.STOP_REASON_USER,
- "user removed");
- }
+ private void cancelJobsForUserLocked(int userHandle) {
+ final List<JobStatus> jobsForUser = mJobs.getJobsByUser(userHandle);
+ for (int i = 0; i < jobsForUser.size(); i++) {
+ JobStatus toRemove = jobsForUser.get(i);
+ // By the time we get here, the process should have already been stopped, so the
+ // app wouldn't get the stop reason, so just put USER instead of UNINSTALL.
+ cancelJobImplLocked(toRemove, null, JobParameters.STOP_REASON_USER,
+ "user removed");
}
}
@@ -1124,19 +1129,17 @@
}
}
- void cancelJobsForPackageAndUid(String pkgName, int uid, @JobParameters.StopReason int reason,
- String debugReason) {
+ private void cancelJobsForPackageAndUidLocked(String pkgName, int uid,
+ @JobParameters.StopReason int reason, String debugReason) {
if ("android".equals(pkgName)) {
Slog.wtfStack(TAG, "Can't cancel all jobs for system package");
return;
}
- synchronized (mLock) {
- final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
- for (int i = jobsForUid.size() - 1; i >= 0; i--) {
- final JobStatus job = jobsForUid.get(i);
- if (job.getSourcePackageName().equals(pkgName)) {
- cancelJobImplLocked(job, null, reason, debugReason);
- }
+ final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
+ for (int i = jobsForUid.size() - 1; i >= 0; i--) {
+ final JobStatus job = jobsForUid.get(i);
+ if (job.getSourcePackageName().equals(pkgName)) {
+ cancelJobImplLocked(job, null, reason, debugReason);
}
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index ce4fd7a..44b3e3e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -322,7 +322,9 @@
job.hasDeadlineConstraint(),
job.hasIdleConstraint(),
job.hasConnectivityConstraint(),
- job.hasContentTriggerConstraint());
+ job.hasContentTriggerConstraint(),
+ job.isRequestedExpeditedJob(),
+ job.shouldTreatAsExpeditedJob());
try {
mBatteryStats.noteJobStart(job.getBatteryName(), job.getSourceUid());
} catch (RemoteException e) {
@@ -904,7 +906,9 @@
completedJob.hasDeadlineConstraint(),
completedJob.hasIdleConstraint(),
completedJob.hasConnectivityConstraint(),
- completedJob.hasContentTriggerConstraint());
+ completedJob.hasContentTriggerConstraint(),
+ completedJob.isRequestedExpeditedJob(),
+ completedJob.startedAsExpeditedJob);
try {
mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(), mRunningJob.getSourceUid(),
legacyStopReason);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index 370b3c9..36d3f16 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -27,10 +27,8 @@
import android.app.job.JobInfo;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
-import android.net.INetworkPolicyListener;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
import android.os.Handler;
import android.os.Looper;
@@ -86,7 +84,6 @@
private static final long MIN_STATS_UPDATE_INTERVAL_MS = 30_000L;
private final ConnectivityManager mConnManager;
- private final NetworkPolicyManager mNetPolicyManager;
private final NetworkPolicyManagerInternal mNetPolicyManagerInternal;
/** List of tracked jobs keyed by source UID. */
@@ -170,8 +167,6 @@
*/
private final List<UidStats> mSortedStats = new ArrayList<>();
- private static final int MSG_DATA_SAVER_TOGGLED = 0;
- private static final int MSG_UID_RULES_CHANGES = 1;
private static final int MSG_REEVALUATE_JOBS = 2;
private final Handler mHandler;
@@ -181,15 +176,12 @@
mHandler = new CcHandler(mContext.getMainLooper());
mConnManager = mContext.getSystemService(ConnectivityManager.class);
- mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
mNetPolicyManagerInternal = LocalServices.getService(NetworkPolicyManagerInternal.class);
// We're interested in all network changes; internally we match these
// network changes against the active network for each UID with jobs.
final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
mConnManager.registerNetworkCallback(request, mNetworkCallback);
-
- mNetPolicyManager.registerListener(mNetPolicyListener);
}
@GuardedBy("mLock")
@@ -234,9 +226,22 @@
jobs.remove(jobStatus);
}
UidStats us = mUidStats.get(jobStatus.getSourceUid());
- us.numReadyWithConnectivity--;
- if (jobStatus.madeActive != 0) {
- us.numRunning--;
+ if (us == null) {
+ // This shouldn't be happening. We create a UidStats object for the app when the
+ // first job is scheduled in maybeStartTrackingJobLocked() and only ever drop the
+ // object if the app is uninstalled or the user is removed. That means that if we
+ // end up in this situation, onAppRemovedLocked() or onUserRemovedLocked() was
+ // called before maybeStopTrackingJobLocked(), which is the reverse order of what
+ // JobSchedulerService does (JSS calls maybeStopTrackingJobLocked() for all jobs
+ // before calling onAppRemovedLocked() or onUserRemovedLocked()).
+ Slog.wtfStack(TAG,
+ "UidStats was null after job for " + jobStatus.getSourcePackageName()
+ + " was registered");
+ } else {
+ us.numReadyWithConnectivity--;
+ if (jobStatus.madeActive != 0) {
+ us.numRunning--;
+ }
}
maybeRevokeStandbyExceptionLocked(jobStatus);
maybeAdjustRegisteredCallbacksLocked();
@@ -781,22 +786,22 @@
* @param filterNetwork only update jobs that would use this
* {@link Network}, or {@code null} to update all tracked jobs.
*/
- private void updateTrackedJobs(int filterUid, Network filterNetwork) {
- synchronized (mLock) {
- boolean changed = false;
- if (filterUid == -1) {
- for (int i = mTrackedJobs.size() - 1; i >= 0; i--) {
- changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i), filterNetwork);
- }
- } else {
- changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid), filterNetwork);
+ @GuardedBy("mLock")
+ private void updateTrackedJobsLocked(int filterUid, Network filterNetwork) {
+ boolean changed = false;
+ if (filterUid == -1) {
+ for (int i = mTrackedJobs.size() - 1; i >= 0; i--) {
+ changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i), filterNetwork);
}
- if (changed) {
- mStateChangedListener.onControllerStateChanged();
- }
+ } else {
+ changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid), filterNetwork);
+ }
+ if (changed) {
+ mStateChangedListener.onControllerStateChanged();
}
}
+ @GuardedBy("mLock")
private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork) {
if (jobs == null || jobs.size() == 0) {
return false;
@@ -883,9 +888,9 @@
}
synchronized (mLock) {
mAvailableNetworks.put(network, capabilities);
+ updateTrackedJobsLocked(-1, network);
+ maybeAdjustRegisteredCallbacksLocked();
}
- updateTrackedJobs(-1, network);
- maybeAdjustRegisteredCallbacksLocked();
}
@Override
@@ -901,27 +906,9 @@
callback.mDefaultNetwork = null;
}
}
+ updateTrackedJobsLocked(-1, network);
+ maybeAdjustRegisteredCallbacksLocked();
}
- updateTrackedJobs(-1, network);
- maybeAdjustRegisteredCallbacksLocked();
- }
- };
-
- private final INetworkPolicyListener mNetPolicyListener = new NetworkPolicyManager.Listener() {
- @Override
- public void onRestrictBackgroundChanged(boolean restrictBackground) {
- if (DEBUG) {
- Slog.v(TAG, "onRestrictBackgroundChanged: " + restrictBackground);
- }
- mHandler.obtainMessage(MSG_DATA_SAVER_TOGGLED).sendToTarget();
- }
-
- @Override
- public void onUidRulesChanged(int uid, int uidRules) {
- if (DEBUG) {
- Slog.v(TAG, "onUidRulesChanged: " + uid);
- }
- mHandler.obtainMessage(MSG_UID_RULES_CHANGES, uid, 0).sendToTarget();
}
};
@@ -934,14 +921,8 @@
public void handleMessage(Message msg) {
synchronized (mLock) {
switch (msg.what) {
- case MSG_DATA_SAVER_TOGGLED:
- updateTrackedJobs(-1, null);
- break;
- case MSG_UID_RULES_CHANGES:
- updateTrackedJobs(msg.arg1, null);
- break;
case MSG_REEVALUATE_JOBS:
- updateTrackedJobs(-1, null);
+ updateTrackedJobsLocked(-1, null);
break;
}
}
@@ -981,8 +962,8 @@
synchronized (mLock) {
mDefaultNetwork = network;
mBlocked = blocked;
+ updateTrackedJobsLocked(mUid, network);
}
- updateTrackedJobs(mUid, network);
}
// Network transitions have some complicated behavior that JS doesn't handle very well.
@@ -1025,8 +1006,8 @@
if (Objects.equals(mDefaultNetwork, network)) {
mDefaultNetwork = null;
}
+ updateTrackedJobsLocked(mUid, network);
}
- updateTrackedJobs(mUid, network);
}
private void dumpLocked(IndentingPrintWriter pw) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 8d999e1..80e68e9 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -142,13 +142,14 @@
* (Atom #21)
* * CONSTRAINT_BACKGROUND_NOT_RESTRICTED can be inferred with BatterySaverModeStateChanged
* (Atom #20)
+ * * CONSTRAINT_STORAGE_NOT_LOW can be inferred with LowStorageStateChanged (Atom #130)
*/
private static final int STATSD_CONSTRAINTS_TO_LOG = CONSTRAINT_CONTENT_TRIGGER
| CONSTRAINT_DEADLINE
| CONSTRAINT_IDLE
- | CONSTRAINT_STORAGE_NOT_LOW
| CONSTRAINT_TIMING_DELAY
- | CONSTRAINT_WITHIN_QUOTA;
+ | CONSTRAINT_WITHIN_QUOTA
+ | CONSTRAINT_WITHIN_EXPEDITED_QUOTA;
// TODO(b/129954980)
private static final boolean STATS_LOG_ENABLED = false;
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
index 20ce133..3cf585e 100644
--- a/apex/media/framework/Android.bp
+++ b/apex/media/framework/Android.bp
@@ -41,9 +41,7 @@
installable: true,
sdk_version: "module_current",
- libs: [
- "framework_media_annotation",
- ],
+ libs: ["framework-annotations-lib"],
static_libs: [
"exoplayer2-extractor",
"mediatranscoding_aidl_interface-java",
@@ -138,20 +136,9 @@
api_lint: {
enabled: false,
},
-
- libs: [
- "framework_media_annotation",
- ],
impl_library_visibility: ["//frameworks/av/apex:__subpackages__"],
}
-java_library {
- name: "framework_media_annotation",
- srcs: [":framework-media-annotation-srcs"],
- installable: false,
- sdk_version: "core_current",
-}
-
cc_library_shared {
name: "libmediaparser-jni",
srcs: [
diff --git a/apex/media/framework/api/system-current.txt b/apex/media/framework/api/system-current.txt
index ad68169..8d83309 100644
--- a/apex/media/framework/api/system-current.txt
+++ b/apex/media/framework/api/system-current.txt
@@ -25,7 +25,9 @@
}
public static final class MediaTranscodeManager.TranscodingSession {
+ method public void addClientUid(int);
method public void cancel();
+ method @NonNull public java.util.List<java.lang.Integer> getClientUids();
method public int getErrorCode();
method @IntRange(from=0, to=100) public int getProgress();
method public int getResult();
diff --git a/apex/media/framework/java/android/media/MediaTranscodeManager.java b/apex/media/framework/java/android/media/MediaTranscodeManager.java
index 7f4685e..fef4865 100644
--- a/apex/media/framework/java/android/media/MediaTranscodeManager.java
+++ b/apex/media/framework/java/android/media/MediaTranscodeManager.java
@@ -1352,6 +1352,8 @@
private @TranscodingSessionErrorCode int mErrorCode = ERROR_NONE;
@GuardedBy("mLock")
private boolean mHasRetried = false;
+ @GuardedBy("mLock")
+ private @NonNull List<Integer> mClientUidList = new ArrayList<>();
// The original request that associated with this session.
private final TranscodingRequest mRequest;
@@ -1370,6 +1372,7 @@
mListenerExecutor = executor;
mListener = listener;
mRequest = request;
+ mClientUidList.add(request.getClientUid());
}
/**
@@ -1515,6 +1518,36 @@
}
/**
+ * Adds a client uid that is also waiting for this transcoding session.
+ * <p>
+ * Only privilege caller with android.permission.WRITE_MEDIA_STORAGE could add the
+ * uid. Note that the permission check happens on the service side upon starting the
+ * transcoding. If the client does not have the permission, the transcoding will fail.
+ */
+ public void addClientUid(int uid) {
+ if (uid < 0) {
+ throw new IllegalArgumentException("Invalid Uid");
+ }
+ synchronized (mLock) {
+ if (!mClientUidList.contains(uid)) {
+ // see ag/14023202 for implementation
+ mClientUidList.add(uid);
+ }
+ }
+ }
+
+ /**
+ * Query all the client that waiting for this transcoding session
+ * @return a list containing all the client uids.
+ */
+ @NonNull
+ public List<Integer> getClientUids() {
+ synchronized (mLock) {
+ return mClientUidList;
+ }
+ }
+
+ /**
* Gets sessionId of the transcoding session.
* @return session id.
*/
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index ca1d598..f0ac530 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -19,6 +19,7 @@
import android.app.ActivityManager;
import android.app.ContentProviderHolder;
import android.app.IActivityManager;
+import android.content.AttributionSource;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.IContentProvider;
@@ -562,7 +563,8 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.insert(resolveCallingPackage(), null, mUri, mContentValues, mExtras);
+ provider.insert(new AttributionSource(Binder.getCallingUid(),
+ resolveCallingPackage(), null), mUri, mContentValues, mExtras);
}
}
@@ -576,7 +578,8 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.delete(resolveCallingPackage(), null, mUri, mExtras);
+ provider.delete(new AttributionSource(Binder.getCallingUid(),
+ resolveCallingPackage(), null), mUri, mExtras);
}
}
@@ -593,7 +596,8 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- Bundle result = provider.call(null, null, mUri.getAuthority(), mMethod, mArg, mExtras);
+ Bundle result = provider.call(new AttributionSource(Binder.getCallingUid(),
+ resolveCallingPackage(), null), mUri.getAuthority(), mMethod, mArg, mExtras);
if (result != null) {
result.size(); // unpack
}
@@ -620,7 +624,9 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- try (ParcelFileDescriptor fd = provider.openFile(null, null, mUri, "r", null, null)) {
+ try (ParcelFileDescriptor fd = provider.openFile(
+ new AttributionSource(Binder.getCallingUid(),
+ resolveCallingPackage(), null), mUri, "r", null)) {
FileUtils.copy(fd.getFileDescriptor(), FileDescriptor.out);
}
}
@@ -633,7 +639,8 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- try (ParcelFileDescriptor fd = provider.openFile(null, null, mUri, "w", null, null)) {
+ try (ParcelFileDescriptor fd = provider.openFile(new AttributionSource(
+ Binder.getCallingUid(), resolveCallingPackage(), null), mUri, "w", null)) {
FileUtils.copy(FileDescriptor.in, fd.getFileDescriptor());
}
}
@@ -651,8 +658,8 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- Cursor cursor = provider.query(resolveCallingPackage(), null, mUri, mProjection,
- mExtras, null);
+ Cursor cursor = provider.query(new AttributionSource(Binder.getCallingUid(),
+ resolveCallingPackage(), null), mUri, mProjection, mExtras, null);
if (cursor == null) {
System.out.println("No result found.");
return;
@@ -716,7 +723,8 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.update(resolveCallingPackage(), null, mUri, mValues, mExtras);
+ provider.update(new AttributionSource(Binder.getCallingUid(),
+ resolveCallingPackage(), null), mUri, mValues, mExtras);
}
}
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index b23bf5d..bc95986 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -20,6 +20,7 @@
import android.app.ContentProviderHolder;
import android.app.IActivityManager;
import android.app.UiAutomation;
+import android.content.AttributionSource;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
@@ -28,6 +29,7 @@
import android.os.Binder;
import android.os.IBinder;
import android.os.IPowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -67,7 +69,8 @@
throw new IllegalStateException("Could not find provider: " + providerName);
}
provider = holder.provider;
- cursor = provider.query(null, null, Settings.Secure.CONTENT_URI,
+ cursor = provider.query(new AttributionSource(Binder.getCallingUid(),
+ resolveCallingPackage(), null), Settings.Secure.CONTENT_URI,
new String[] {
Settings.Secure.VALUE
},
@@ -123,4 +126,18 @@
}
return ret;
}
+
+ private static String resolveCallingPackage() {
+ switch (Binder.getCallingUid()) {
+ case Process.ROOT_UID: {
+ return "root";
+ }
+ case Process.SHELL_UID: {
+ return "com.android.shell";
+ }
+ default: {
+ return null;
+ }
+ }
+ }
}
diff --git a/core/api/current.txt b/core/api/current.txt
index 3773d3b..a30191c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -867,6 +867,7 @@
field public static final int keycode = 16842949; // 0x10100c5
field public static final int killAfterRestore = 16843420; // 0x101029c
field public static final int knownCerts = 16844330; // 0x101062a
+ field public static final int lStar = 16844359; // 0x1010647
field public static final int label = 16842753; // 0x1010001
field public static final int labelFor = 16843718; // 0x10103c6
field @Deprecated public static final int labelTextSize = 16843317; // 0x1010235
@@ -1295,6 +1296,7 @@
field public static final int showDefault = 16843258; // 0x10101fa
field public static final int showDividers = 16843561; // 0x1010329
field public static final int showForAllUsers = 16844015; // 0x10104ef
+ field public static final int showInInputMethodPicker = 16844361; // 0x1010649
field public static final int showMetadataInPreview = 16844079; // 0x101052f
field @Deprecated public static final int showOnLockScreen = 16843721; // 0x10103c9
field public static final int showSilent = 16843259; // 0x10101fb
@@ -7133,6 +7135,8 @@
method public int getMaximumFailedPasswordsForWipe(@Nullable android.content.ComponentName);
method public long getMaximumTimeToLock(@Nullable android.content.ComponentName);
method @NonNull public java.util.List<java.lang.String> getMeteredDataDisabledPackages(@NonNull android.content.ComponentName);
+ method public int getNearbyAppStreamingPolicy();
+ method public int getNearbyNotificationStreamingPolicy();
method @Deprecated @ColorInt public int getOrganizationColor(@NonNull android.content.ComponentName);
method @Nullable public CharSequence getOrganizationName(@NonNull android.content.ComponentName);
method public java.util.List<android.telephony.data.ApnSetting> getOverrideApns(@NonNull android.content.ComponentName);
@@ -7276,6 +7280,8 @@
method public void setMaximumFailedPasswordsForWipe(@NonNull android.content.ComponentName, int);
method public void setMaximumTimeToLock(@NonNull android.content.ComponentName, long);
method @NonNull public java.util.List<java.lang.String> setMeteredDataDisabledPackages(@NonNull android.content.ComponentName, @NonNull java.util.List<java.lang.String>);
+ method public void setNearbyAppStreamingPolicy(int);
+ method public void setNearbyNotificationStreamingPolicy(int);
method public void setNetworkLoggingEnabled(@Nullable android.content.ComponentName, boolean);
method @Deprecated public void setOrganizationColor(@NonNull android.content.ComponentName, int);
method public void setOrganizationId(@NonNull String);
@@ -7444,6 +7450,9 @@
field public static final int LOCK_TASK_FEATURE_SYSTEM_INFO = 1; // 0x1
field public static final int MAKE_USER_EPHEMERAL = 2; // 0x2
field public static final String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning";
+ field public static final int NEARBY_STREAMING_DISABLED = 0; // 0x0
+ field public static final int NEARBY_STREAMING_ENABLED = 1; // 0x1
+ field public static final int NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY = 2; // 0x2
field public static final int OPERATION_SAFETY_REASON_DRIVING_DISTRACTION = 1; // 0x1
field public static final int PASSWORD_COMPLEXITY_HIGH = 327680; // 0x50000
field public static final int PASSWORD_COMPLEXITY_LOW = 65536; // 0x10000
@@ -7873,8 +7882,10 @@
public static class BlobStoreManager.Session implements java.io.Closeable {
method public void abandon() throws java.io.IOException;
method public void allowPackageAccess(@NonNull String, @NonNull byte[]) throws java.io.IOException;
+ method public void allowPackagesWithLocationPermission(@NonNull String) throws java.io.IOException;
method public void allowPublicAccess() throws java.io.IOException;
method public void allowSameSignatureAccess() throws java.io.IOException;
+ method public boolean arePackagesWithLocationPermissionAllowed(@NonNull String) throws java.io.IOException;
method public void close() throws java.io.IOException;
method public void commit(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws java.io.IOException;
method public long getSize() throws java.io.IOException;
@@ -9906,6 +9917,27 @@
method @Deprecated public void setUpdateThrottle(long);
}
+ public final class AttributionSource implements android.os.Parcelable {
+ method public boolean checkCallingUid();
+ method public int describeContents();
+ method public void enforceCallingUid();
+ method @Nullable public String getAttributionTag();
+ method @Nullable public android.content.AttributionSource getNext();
+ method @Nullable public String getPackageName();
+ method public int getUid();
+ method public boolean isTrusted(@NonNull android.content.Context);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.AttributionSource> CREATOR;
+ }
+
+ public static final class AttributionSource.Builder {
+ ctor public AttributionSource.Builder(int);
+ method @NonNull public android.content.AttributionSource build();
+ method @NonNull public android.content.AttributionSource.Builder setAttributionTag(@NonNull String);
+ method @NonNull public android.content.AttributionSource.Builder setNext(@NonNull android.content.AttributionSource);
+ method @NonNull public android.content.AttributionSource.Builder setPackageName(@NonNull String);
+ }
+
public abstract class BroadcastReceiver {
ctor public BroadcastReceiver();
method public final void abortBroadcast();
@@ -10075,6 +10107,7 @@
method public abstract int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]);
method public int delete(@NonNull android.net.Uri, @Nullable android.os.Bundle);
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
+ method @Nullable public final android.content.AttributionSource getCallingAttributionSource();
method @Nullable public final String getCallingAttributionTag();
method @Nullable public final String getCallingPackage();
method @Nullable public final String getCallingPackageUnchecked();
@@ -10437,6 +10470,7 @@
method public abstract android.content.Context getApplicationContext();
method public abstract android.content.pm.ApplicationInfo getApplicationInfo();
method public abstract android.content.res.AssetManager getAssets();
+ method @NonNull public android.content.AttributionSource getAttributionSource();
method @Nullable public String getAttributionTag();
method public abstract java.io.File getCacheDir();
method public abstract ClassLoader getClassLoader();
@@ -10642,8 +10676,7 @@
public final class ContextParams {
method @Nullable public String getAttributionTag();
- method @Nullable public String getReceiverAttributionTag();
- method @Nullable public String getReceiverPackage();
+ method @Nullable public android.content.AttributionSource getNextAttributionSource();
}
public static final class ContextParams.Builder {
@@ -10651,7 +10684,7 @@
ctor public ContextParams.Builder(@NonNull android.content.ContextParams);
method @NonNull public android.content.ContextParams build();
method @NonNull public android.content.ContextParams.Builder setAttributionTag(@Nullable String);
- method @NonNull public android.content.ContextParams.Builder setReceiverPackage(@Nullable String, @Nullable String);
+ method @NonNull public android.content.ContextParams.Builder setNextAttributionSource(@Nullable android.content.AttributionSource);
}
public class ContextWrapper extends android.content.Context {
@@ -13178,6 +13211,7 @@
method public boolean isStateful();
method @NonNull public static android.content.res.ColorStateList valueOf(@ColorInt int);
method @NonNull public android.content.res.ColorStateList withAlpha(int);
+ method @NonNull public android.content.res.ColorStateList withLStar(float);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.res.ColorStateList> CREATOR;
}
@@ -18809,9 +18843,14 @@
method public android.view.Display getDisplay(int);
method public android.view.Display[] getDisplays();
method public android.view.Display[] getDisplays(String);
+ method public int getMatchContentFrameRateUserPreference();
method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler);
method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
field public static final String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
+ field public static final int MATCH_CONTENT_FRAMERATE_ALWAYS = 2; // 0x2
+ field public static final int MATCH_CONTENT_FRAMERATE_NEVER = 0; // 0x0
+ field public static final int MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY = 1; // 0x1
+ field public static final int MATCH_CONTENT_FRAMERATE_UNKNOWN = -1; // 0xffffffff
field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10
field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
@@ -39080,6 +39119,7 @@
method public void bufferReceived(byte[]) throws android.os.RemoteException;
method public void endOfSpeech() throws android.os.RemoteException;
method public void error(int) throws android.os.RemoteException;
+ method @NonNull public android.content.AttributionSource getCallingAttributionSource();
method public int getCallingUid();
method public void partialResults(android.os.Bundle) throws android.os.RemoteException;
method public void readyForSpeech(android.os.Bundle) throws android.os.RemoteException;
@@ -40273,6 +40313,7 @@
field public static final int DURATION_MEDIUM = 2; // 0x2
field public static final int DURATION_SHORT = 1; // 0x1
field public static final int DURATION_VERY_SHORT = 0; // 0x0
+ field public static final long ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION = 157233955L; // 0x95f3323L
field public static final String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
field public static final String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
@@ -41879,7 +41920,7 @@
method @Deprecated public void onBarringInfoChanged(@NonNull android.telephony.BarringInfo);
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallDisconnectCauseChanged(int, int);
method @Deprecated public void onCallForwardingIndicatorChanged(boolean);
- method @Deprecated public void onCallStateChanged(int, String);
+ method @Deprecated @RequiresPermission(value=android.Manifest.permission.READ_PHONE_STATE, conditional=true) public void onCallStateChanged(int, String);
method @Deprecated public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
method @Deprecated public void onCellLocationChanged(android.telephony.CellLocation);
method @Deprecated public void onDataActivity(int);
@@ -42425,7 +42466,7 @@
}
public static interface TelephonyCallback.CallStateListener {
- method public void onCallStateChanged(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onCallStateChanged(int);
}
public static interface TelephonyCallback.CarrierNetworkListener {
@@ -42515,7 +42556,8 @@
method public int getActiveModemCount();
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCallComposerStatus();
- method public int getCallState();
+ method @Deprecated @RequiresPermission(value=android.Manifest.permission.READ_PHONE_STATE, conditional=true) public int getCallState();
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getCallStateForSubscription();
method public int getCardIdForDefaultEuicc();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @WorkerThread public android.os.PersistableBundle getCarrierConfig();
method public int getCarrierIdFromSimMccMnc();
@@ -48670,6 +48712,7 @@
method @Nullable public android.graphics.drawable.Drawable getVerticalScrollbarThumbDrawable();
method @Nullable public android.graphics.drawable.Drawable getVerticalScrollbarTrackDrawable();
method public int getVerticalScrollbarWidth();
+ method @Nullable public android.view.ViewRoot getViewRoot();
method @Nullable public android.view.translation.ViewTranslationCallback getViewTranslationCallback();
method public android.view.ViewTreeObserver getViewTreeObserver();
method public int getVisibility();
@@ -48771,6 +48814,7 @@
method protected int[] onCreateDrawableState(int);
method public android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo);
method @Nullable public android.view.translation.ViewTranslationRequest onCreateTranslationRequest(@NonNull int[]);
+ method public void onCreateTranslationRequests(@NonNull long[], @NonNull int[], @NonNull java.util.function.Consumer<android.view.translation.ViewTranslationRequest>);
method @CallSuper protected void onDetachedFromWindow();
method protected void onDisplayHint(int);
method public boolean onDragEvent(android.view.DragEvent);
@@ -48816,6 +48860,7 @@
method public boolean onTouchEvent(android.view.MotionEvent);
method public boolean onTrackballEvent(android.view.MotionEvent);
method public void onTranslationResponse(@NonNull android.view.translation.ViewTranslationResponse);
+ method public void onTranslationResponse(@NonNull android.util.LongSparseArray<android.view.translation.ViewTranslationResponse>);
method @CallSuper public void onVisibilityAggregated(boolean);
method protected void onVisibilityChanged(@NonNull android.view.View, int);
method public void onWindowFocusChanged(boolean);
@@ -49744,6 +49789,11 @@
method public android.view.ViewPropertyAnimator zBy(float);
}
+ @UiThread public interface ViewRoot {
+ method public boolean applyTransactionOnDraw(@NonNull android.view.SurfaceControl.Transaction);
+ method @Nullable public android.view.SurfaceControl.Transaction buildReparentTransaction(@NonNull android.view.SurfaceControl);
+ }
+
public abstract class ViewStructure {
ctor public ViewStructure();
method public abstract int addChildCount(int);
@@ -49939,6 +49989,7 @@
method @NonNull public java.util.List<android.graphics.Rect> getSystemGestureExclusionRects();
method public long getTransitionBackgroundFadeDuration();
method public android.transition.TransitionManager getTransitionManager();
+ method @Nullable public android.view.ViewRoot getViewRoot();
method public abstract int getVolumeControlStream();
method public android.view.WindowManager getWindowManager();
method public final android.content.res.TypedArray getWindowStyle();
@@ -51507,6 +51558,7 @@
field public static final int DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM = -5; // 0xfffffffb
field public static final int DISPLAY_HASH_ERROR_MISSING_WINDOW = -3; // 0xfffffffd
field public static final int DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN = -4; // 0xfffffffc
+ field public static final int DISPLAY_HASH_ERROR_TOO_MANY_REQUESTS = -6; // 0xfffffffa
field public static final int DISPLAY_HASH_ERROR_UNKNOWN = -1; // 0xffffffff
}
@@ -51869,6 +51921,7 @@
method public int describeContents();
method public void dump(android.util.Printer, String);
method public android.content.ComponentName getComponent();
+ method public int getConfigChanges();
method public String getId();
method public int getIsDefaultResourceId();
method public String getPackageName();
@@ -52737,11 +52790,16 @@
}
public final class TranslationManager {
- method public void addTranslationCapabilityUpdateListener(int, int, @NonNull android.app.PendingIntent);
- method @Nullable @WorkerThread public android.view.translation.Translator createTranslator(@NonNull android.view.translation.TranslationContext);
- method @NonNull @WorkerThread public java.util.Set<android.view.translation.TranslationCapability> getTranslationCapabilities(int, int);
- method @Nullable public android.app.PendingIntent getTranslationSettingsActivityIntent();
- method public void removeTranslationCapabilityUpdateListener(int, int, @NonNull android.app.PendingIntent);
+ method public void addOnDeviceTranslationCapabilityUpdateListener(int, int, @NonNull android.app.PendingIntent);
+ method @Deprecated public void addTranslationCapabilityUpdateListener(int, int, @NonNull android.app.PendingIntent);
+ method @Nullable @WorkerThread public android.view.translation.Translator createOnDeviceTranslator(@NonNull android.view.translation.TranslationContext);
+ method @Deprecated @Nullable @WorkerThread public android.view.translation.Translator createTranslator(@NonNull android.view.translation.TranslationContext);
+ method @NonNull @WorkerThread public java.util.Set<android.view.translation.TranslationCapability> getOnDeviceTranslationCapabilities(int, int);
+ method @Nullable public android.app.PendingIntent getOnDeviceTranslationSettingsActivityIntent();
+ method @Deprecated @NonNull @WorkerThread public java.util.Set<android.view.translation.TranslationCapability> getTranslationCapabilities(int, int);
+ method @Deprecated @Nullable public android.app.PendingIntent getTranslationSettingsActivityIntent();
+ method public void removeOnDeviceTranslationCapabilityUpdateListener(int, int, @NonNull android.app.PendingIntent);
+ method @Deprecated public void removeTranslationCapabilityUpdateListener(int, int, @NonNull android.app.PendingIntent);
}
public final class TranslationRequest implements android.os.Parcelable {
@@ -52865,8 +52923,9 @@
public static final class ViewTranslationRequest.Builder {
ctor public ViewTranslationRequest.Builder(@NonNull android.view.autofill.AutofillId);
+ ctor public ViewTranslationRequest.Builder(@NonNull android.view.autofill.AutofillId, long);
method @NonNull public android.view.translation.ViewTranslationRequest build();
- method public android.view.translation.ViewTranslationRequest.Builder setValue(String, android.view.translation.TranslationRequestValue);
+ method @NonNull public android.view.translation.ViewTranslationRequest.Builder setValue(@NonNull String, @NonNull android.view.translation.TranslationRequestValue);
}
public final class ViewTranslationResponse implements android.os.Parcelable {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 256337d..4fb9926 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -196,7 +196,6 @@
method @NonNull public static String blockedReasonsToString(int);
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getMultipathPreference(@NonNull android.net.Network);
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getRestrictBackgroundStatus(int);
- method public static boolean isUidBlocked(int, boolean);
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int, boolean);
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int);
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 49b8a90..99d8d07 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -180,6 +180,7 @@
field public static final String NETWORK_SIGNAL_STRENGTH_WAKEUP = "android.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP";
field public static final String NETWORK_STACK = "android.permission.NETWORK_STACK";
field public static final String NETWORK_STATS_PROVIDER = "android.permission.NETWORK_STATS_PROVIDER";
+ field public static final String NFC_SET_CONTROLLER_ALWAYS_ON = "android.permission.NFC_SET_CONTROLLER_ALWAYS_ON";
field public static final String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP";
field public static final String NOTIFY_TV_INPUTS = "android.permission.NOTIFY_TV_INPUTS";
field public static final String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
@@ -320,6 +321,7 @@
field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
field public static final int sdkVersion = 16844304; // 0x1010610
field public static final int supportsAmbientMode = 16844173; // 0x101058d
+ field public static final int throttleDurationMillis = 16844360; // 0x1010648
field public static final int userRestriction = 16844164; // 0x1010584
}
@@ -596,7 +598,7 @@
public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable {
method public int describeContents();
- method @Nullable public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOps(@NonNull String);
+ method @Nullable public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOps(@Nullable String);
method @NonNull public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOpsAt(@IntRange(from=0) int);
method @IntRange(from=0) public int getAttributedOpsCount();
method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
@@ -1733,10 +1735,20 @@
field public static final int CAPABILITY_POSSESSED = 40; // 0x28
}
+ public final class ExternalTimeSuggestion implements android.os.Parcelable {
+ ctor public ExternalTimeSuggestion(long, long);
+ method public void addDebugInfo(@NonNull java.lang.String...);
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getDebugInfo();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.time.ExternalTimeSuggestion> CREATOR;
+ }
+
public final class TimeManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public void addTimeZoneDetectorListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.time.TimeManager.TimeZoneDetectorListener);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public android.app.time.TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig();
method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public void removeTimeZoneDetectorListener(@NonNull android.app.time.TimeManager.TimeZoneDetectorListener);
+ method @RequiresPermission(android.Manifest.permission.SUGGEST_EXTERNAL_TIME) public void suggestExternalTime(@NonNull android.app.time.ExternalTimeSuggestion);
method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public boolean updateTimeZoneConfiguration(@NonNull android.app.time.TimeZoneConfiguration);
}
@@ -1835,6 +1847,7 @@
public final class UsageStatsManager {
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getAppStandbyBucket(String);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.Map<java.lang.String,java.lang.Integer> getAppStandbyBuckets();
+ method @RequiresPermission(allOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long getLastTimeAnyComponentUsed(@NonNull String);
method public int getUsageSource();
method @RequiresPermission(android.Manifest.permission.BIND_CARRIER_SERVICES) public void onCarrierPrivilegedAppsChanged();
method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @Nullable android.app.PendingIntent);
@@ -2217,6 +2230,14 @@
method @NonNull public java.io.File getDeviceProtectedDataDirForUser(@NonNull android.os.UserHandle);
}
+ public final class AttributionSource implements android.os.Parcelable {
+ method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public java.util.Set<java.lang.String> getRenouncedPermissions();
+ }
+
+ public static final class AttributionSource.Builder {
+ method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public android.content.AttributionSource.Builder setRenouncedPermissions(@NonNull java.util.Set<java.lang.String>);
+ }
+
public abstract class BroadcastReceiver {
method @NonNull public final android.os.UserHandle getSendingUser();
}
@@ -2291,7 +2312,7 @@
}
public final class ContextParams {
- method @Nullable @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public java.util.Set<java.lang.String> getRenouncedPermissions();
+ method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public java.util.Set<java.lang.String> getRenouncedPermissions();
}
public static final class ContextParams.Builder {
@@ -2347,9 +2368,12 @@
field public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
field public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED";
field public static final String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
+ field @RequiresPermission(android.Manifest.permission.START_VIEW_PERMISSION_USAGE) public static final String ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD = "android.intent.action.VIEW_PERMISSION_USAGE_FOR_PERIOD";
field public static final String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
field public static final String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS";
+ field public static final String EXTRA_ATTRIBUTION_TAGS = "android.intent.extra.ATTRIBUTION_TAGS";
field public static final String EXTRA_CALLING_PACKAGE = "android.intent.extra.CALLING_PACKAGE";
+ field public static final String EXTRA_END_TIME = "android.intent.extra.END_TIME";
field public static final String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET";
field public static final String EXTRA_INSTANT_APP_ACTION = "android.intent.extra.INSTANT_APP_ACTION";
field public static final String EXTRA_INSTANT_APP_BUNDLES = "android.intent.extra.INSTANT_APP_BUNDLES";
@@ -2368,6 +2392,7 @@
field public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
field public static final String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
field public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
+ field public static final String EXTRA_START_TIME = "android.intent.extra.START_TIME";
field public static final String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP";
field public static final String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE";
field public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 67108864; // 0x4000000
@@ -7888,10 +7913,10 @@
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isAlwaysOnEnabled();
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isAlwaysOnSupported();
+ method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
+ method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setAlwaysOn(boolean);
+ method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean);
method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
}
@@ -8318,6 +8343,7 @@
field public static final int REASON_UNKNOWN = 0; // 0x0
field public static final int TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; // 0x0
field public static final int TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; // 0x1
+ field public static final int TEMPORARY_ALLOW_LIST_TYPE_NONE = -1; // 0xffffffff
}
public final class PowerManager {
@@ -9774,6 +9800,7 @@
method @NonNull public abstract java.util.Map<java.lang.String,android.service.displayhash.DisplayHashParams> onGetDisplayHashAlgorithms();
method @Nullable public abstract android.view.displayhash.VerifiedDisplayHash onVerifyDisplayHash(@NonNull byte[], @NonNull android.view.displayhash.DisplayHash);
field public static final String SERVICE_INTERFACE = "android.service.displayhash.DisplayHasherService";
+ field public static final String SERVICE_META_DATA = "android.displayhash.display_hasher_service";
}
}
@@ -10372,6 +10399,7 @@
public abstract static class AlwaysOnHotwordDetector.Callback implements android.service.voice.HotwordDetector.Callback {
ctor public AlwaysOnHotwordDetector.Callback();
method public abstract void onAvailabilityChanged(int);
+ method public void onHotwordDetectionServiceInitialized(int);
method public void onRejected(@Nullable android.service.voice.HotwordRejectedResult);
}
@@ -10391,9 +10419,10 @@
method public int describeContents();
method public int getByteOffset();
method public int getConfidenceLevel();
- method @NonNull public android.os.Bundle getExtras();
- method @Nullable public String getHotwordPhrase();
+ method @NonNull public android.os.PersistableBundle getExtras();
+ method public int getHotwordPhraseId();
method public static int getMaxBundleSize();
+ method public static int getMaxHotwordPhraseId();
method public static int getMaxScore();
method public int getPersonalizedScore();
method public int getScore();
@@ -10407,8 +10436,8 @@
method @NonNull public android.service.voice.HotwordDetectedResult build();
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setByteOffset(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setConfidenceLevel(int);
- method @NonNull public android.service.voice.HotwordDetectedResult.Builder setExtras(@NonNull android.os.Bundle);
- method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordPhrase(@NonNull String);
+ method @NonNull public android.service.voice.HotwordDetectedResult.Builder setExtras(@NonNull android.os.PersistableBundle);
+ method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setPersonalizedScore(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setScore(int);
}
@@ -10419,7 +10448,11 @@
method public void onDetect(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, long, @NonNull android.service.voice.HotwordDetectionService.Callback);
method public void onDetect(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @NonNull android.service.voice.HotwordDetectionService.Callback);
method public void onDetect(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle, @NonNull android.service.voice.HotwordDetectionService.Callback);
- method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory);
+ method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, long, @Nullable java.util.function.IntConsumer);
+ field public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_1 = 1; // 0x1
+ field public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_2 = 2; // 0x2
+ field public static final int INITIALIZATION_STATUS_SUCCESS = 0; // 0x0
+ field public static final int INITIALIZATION_STATUS_UNKNOWN = 100; // 0x64
field public static final String SERVICE_INTERFACE = "android.service.voice.HotwordDetectionService";
}
@@ -10441,6 +10474,7 @@
public static interface HotwordDetector.Callback {
method public void onDetected(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload);
method public void onError();
+ method public void onHotwordDetectionServiceInitialized(int);
method public void onRecognitionPaused();
method public void onRecognitionResumed();
method public void onRejected(@Nullable android.service.voice.HotwordRejectedResult);
@@ -10861,7 +10895,7 @@
method public java.util.List<android.telecom.PhoneAccount> getAllPhoneAccounts();
method public int getAllPhoneAccountsCount();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts(boolean);
- method public int getCallState();
+ method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}, conditional=true) public int getCallState();
method public android.telecom.PhoneAccountHandle getConnectionManager();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCurrentTtyMode();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultDialerPackage(@NonNull android.os.UserHandle);
@@ -13643,13 +13677,13 @@
ctor @Deprecated public RcsFeature();
ctor public RcsFeature(@NonNull java.util.concurrent.Executor);
method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
- method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener);
+ method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.CapabilityExchangeEventListener);
+ method public void destroyCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase);
method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities);
method public void onFeatureReady();
method public void onFeatureRemoved();
method public boolean queryCapabilityConfiguration(int, int);
method @NonNull public final android.telephony.ims.feature.RcsFeature.RcsImsCapabilities queryCapabilityStatus();
- method public void removeCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase);
}
public static class RcsFeature.RcsImsCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
@@ -13862,7 +13896,7 @@
}
public class RcsCapabilityExchangeImplBase {
- ctor public RcsCapabilityExchangeImplBase(@NonNull java.util.concurrent.Executor);
+ ctor public RcsCapabilityExchangeImplBase();
method public void publishCapabilities(@NonNull String, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback);
method public void sendOptionsCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.Set<java.lang.String>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback);
method public void subscribeForCapabilities(@NonNull java.util.Collection<android.net.Uri>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback);
@@ -14719,6 +14753,7 @@
method public default boolean onCheckIsTextEditor();
method public void onConfigurationChanged(android.content.res.Configuration);
method public android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo);
+ method public default void onCreateTranslationRequests(@NonNull long[], @NonNull int[], @NonNull java.util.function.Consumer<android.view.translation.ViewTranslationRequest>);
method public void onDetachedFromWindow();
method public boolean onDragEvent(android.view.DragEvent);
method public void onDraw(android.graphics.Canvas);
@@ -14743,6 +14778,7 @@
method public void onStartTemporaryDetach();
method public boolean onTouchEvent(android.view.MotionEvent);
method public boolean onTrackballEvent(android.view.MotionEvent);
+ method public default void onTranslationResponse(@NonNull android.util.LongSparseArray<android.view.translation.ViewTranslationResponse>);
method public void onVisibilityChanged(android.view.View, int);
method public void onWindowFocusChanged(boolean);
method public void onWindowVisibilityChanged(int);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index a54bce7..6745a69 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -220,6 +220,7 @@
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void rebootHistory(long);
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void reloadNonHistoricalState();
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetHistoryParameters();
+ method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetPackageOpsNoHistory(@NonNull String);
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int);
method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(int, int, String, int);
method public static int strOpToOp(@NonNull String);
@@ -252,6 +253,14 @@
method public void offsetBeginAndEndTime(long);
}
+ public class BroadcastOptions {
+ ctor public BroadcastOptions(@NonNull android.os.Bundle);
+ method public long getTemporaryAppAllowlistDuration();
+ method @Nullable public String getTemporaryAppAllowlistReason();
+ method public int getTemporaryAppAllowlistReasonCode();
+ method public int getTemporaryAppAllowlistType();
+ }
+
public class DownloadManager {
field public static final String COLUMN_MEDIASTORE_URI = "mediastore_uri";
}
@@ -654,6 +663,11 @@
package android.content {
+ public final class AttributionSource implements android.os.Parcelable {
+ ctor public AttributionSource(int, @Nullable String, @Nullable String);
+ ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable android.content.AttributionSource);
+ }
+
public final class AutofillOptions implements android.os.Parcelable {
ctor public AutofillOptions(int, boolean);
method public int describeContents();
@@ -1141,7 +1155,7 @@
public final class DisplayManager {
method public boolean areUserDisabledHdrTypesAllowed();
- method @RequiresPermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) public int getRefreshRateSwitchingType();
+ method @NonNull public int[] getUserDisabledHdrTypes();
method public boolean isMinimalPostProcessingRequested(int);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAreUserDisabledHdrTypesAllowed(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) public void setRefreshRateSwitchingType(int);
@@ -1642,6 +1656,7 @@
field public static final int FIRST_ISOLATED_UID = 99000; // 0x182b8
field public static final int LAST_APP_ZYGOTE_ISOLATED_UID = 98999; // 0x182b7
field public static final int LAST_ISOLATED_UID = 99999; // 0x1869f
+ field public static final int NFC_UID = 1027; // 0x403
field public static final int NUM_UIDS_PER_APP_ZYGOTE = 100; // 0x64
}
@@ -2597,6 +2612,7 @@
}
public final class Display {
+ method @NonNull public int[] getReportedHdrTypes();
method @NonNull public android.graphics.ColorSpace[] getSupportedWideColorGamut();
method public int getType();
method public boolean hasAccess(int);
@@ -2861,6 +2877,14 @@
}
+package android.view.displayhash {
+
+ public final class DisplayHashManager {
+ method @RequiresPermission("android.permission.READ_FRAME_BUFFER") public void setDisplayHashThrottlingEnabled(boolean);
+ }
+
+}
+
package android.view.inputmethod {
public final class InlineSuggestion implements android.os.Parcelable {
@@ -2875,6 +2899,10 @@
method @NonNull public static android.view.inputmethod.InlineSuggestionsResponse newInlineSuggestionsResponse(@NonNull java.util.List<android.view.inputmethod.InlineSuggestion>);
}
+ public final class InputMethodInfo implements android.os.Parcelable {
+ ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, int);
+ }
+
public final class InputMethodManager {
method public int getDisplayId();
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public java.util.List<android.view.inputmethod.InputMethodInfo> getInputMethodListAsUser(int);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 86e2723..0f38b5f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -642,7 +642,7 @@
* protected void onCreate(Bundle savedInstanceState) {
* super.onCreate(savedInstanceState);
*
- * SharedPreferences mPrefs = getSharedPreferences();
+ * mPrefs = getSharedPreferences(getLocalClassName(), MODE_PRIVATE);
* mCurViewMode = mPrefs.getInt("view_mode", DAY_VIEW_MODE);
* }
*
@@ -5246,13 +5246,40 @@
if (requestCode < 0) {
throw new IllegalArgumentException("requestCode should be >= 0");
}
+
if (mHasCurrentPermissionsRequest) {
Log.w(TAG, "Can request only one set of permissions at a time");
// Dispatch the callback with empty arrays which means a cancellation.
onRequestPermissionsResult(requestCode, new String[0], new int[0]);
return;
}
- Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
+
+ List<String> filteredPermissions = null;
+
+ if (!getAttributionSource().getRenouncedPermissions().isEmpty()) {
+ final int permissionCount = permissions.length;
+ for (int i = 0; i < permissionCount; i++) {
+ if (getAttributionSource().getRenouncedPermissions().contains(permissions[i])) {
+ if (filteredPermissions == null) {
+ filteredPermissions = new ArrayList<>(i);
+ for (int j = 0; j < i; j++) {
+ filteredPermissions.add(permissions[i]);
+ }
+ }
+ } else if (filteredPermissions != null) {
+ filteredPermissions.add(permissions[i]);
+ }
+ }
+ }
+
+ final Intent intent;
+ if (filteredPermissions == null) {
+ intent = getPackageManager().buildRequestPermissionsIntent(permissions);
+ } else {
+ intent = getPackageManager().buildRequestPermissionsIntent(
+ filteredPermissions.toArray(new String[0]));
+ }
+
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
mHasCurrentPermissionsRequest = true;
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index f7a3514..a7d5b05 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -30,8 +30,8 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.PowerWhitelistManager.ReasonCode;
-import android.os.PowerWhitelistManager.TempAllowListType;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
import android.os.TransactionTooLargeException;
import android.os.WorkSource;
import android.util.ArraySet;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7298d87..e596e7c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4803,6 +4803,10 @@
}
if (r.isTopResumedActivity == onTop) {
+ if (!Build.IS_DEBUGGABLE) {
+ Slog.w(TAG, "Activity top position already set to onTop=" + onTop);
+ return;
+ }
throw new IllegalStateException("Activity top position already set to onTop=" + onTop);
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 7e4af1a..6ce0b22 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -50,6 +50,7 @@
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
+import android.content.AttributionSource;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -5955,7 +5956,7 @@
*
* @return The historical ops for the attribution.
*/
- public @Nullable AttributedHistoricalOps getAttributedOps(@NonNull String attributionTag) {
+ public @Nullable AttributedHistoricalOps getAttributedOps(@Nullable String attributionTag) {
if (mAttributedHistoricalOps == null) {
return null;
}
@@ -6480,7 +6481,7 @@
* Gets number of discrete historical app ops.
*
* @return The number historical app ops.
- * @see #getOpAt(int)
+ * @see #getDiscreteAccessAt(int)
*/
public @IntRange(from = 0) int getDiscreteAccessCount() {
if (mDiscreteAccesses == null) {
@@ -6494,7 +6495,7 @@
*
* @param index The index to lookup.
* @return The op at the given index.
- * @see #getOpCount()
+ * @see #getDiscreteAccessCount()
*/
public @NonNull AttributedOpEntry getDiscreteAccessAt(@IntRange(from = 0) int index) {
if (mDiscreteAccesses == null) {
@@ -7403,6 +7404,32 @@
}
/**
+ * Resolves special UID's pakcages such as root, shell, media, etc.
+ *
+ * @param uid The uid to resolve.
+ * @param packageName Optional package. If caller system and null returns "android"
+ * @return The resolved package name.
+ *
+ * @hide
+ */
+ public static @Nullable String resolvePackageName(int uid, @Nullable String packageName) {
+ if (uid == Process.ROOT_UID) {
+ return "root";
+ } else if (uid == Process.SHELL_UID) {
+ return "com.android.shell";
+ } else if (uid == Process.MEDIA_UID) {
+ return "media";
+ } else if (uid == Process.AUDIOSERVER_UID) {
+ return "audioserver";
+ } else if (uid == Process.CAMERASERVER_UID) {
+ return "cameraserver";
+ } else if (uid == Process.SYSTEM_UID && packageName == null) {
+ return "android";
+ }
+ return packageName;
+ }
+
+ /**
* Monitor for changes to the operating mode for the given op in the given app package.
* You can watch op changes only for your UID.
*
@@ -7979,7 +8006,7 @@
try {
collectNoteOpCallsForValidation(op);
int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
- boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID ? true : false;
+ boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID;
if (collectionMode == COLLECT_ASYNC) {
if (message == null) {
// Set stack trace as default message
@@ -8033,14 +8060,9 @@
*/
public int noteProxyOp(int op, @Nullable String proxiedPackageName, int proxiedUid,
@Nullable String proxiedAttributionTag, @Nullable String message) {
- int mode = noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, proxiedAttributionTag,
- message);
- if (mode == MODE_ERRORED) {
- throw new SecurityException("Proxy package " + mContext.getOpPackageName()
- + " from uid " + Process.myUid() + " or calling package " + proxiedPackageName
- + " from uid " + proxiedUid + " not allowed to perform " + sOpNames[op]);
- }
- return mode;
+ return noteProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
+ new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)),
+ message, /*skipProxyOperation*/ false);
}
/**
@@ -8069,6 +8091,36 @@
}
/**
+ * Make note of an application performing an operation on behalf of another application(s).
+ *
+ * @param op The operation to note. One of the OPSTR_* constants.
+ * @param attributionSource The permission identity for which to note.
+ * @param message A message describing the reason the op was noted
+ * @param skipProxyOperation Whether to skip the proxy note.
+ *
+ * @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 any proxying operations in the permission identityf
+ * chain fails.
+ *
+ * @hide
+ */
+ public int noteProxyOp(@NonNull int op, @NonNull AttributionSource attributionSource,
+ @Nullable String message, boolean skipProxyOperation) {
+ final int mode = noteProxyOpNoThrow(op, attributionSource, message, skipProxyOperation);
+ if (mode == MODE_ERRORED) {
+ throw new SecurityException("Proxy package "
+ + attributionSource.getPackageName() + " from uid "
+ + attributionSource.getUid() + " or calling package "
+ + attributionSource.getNextPackageName() + " from uid "
+ + attributionSource.getNextUid() + " not allowed to perform "
+ + sOpNames[op]);
+ }
+ return mode;
+ }
+
+ /**
* @deprecated Use {@link #noteProxyOpNoThrow(String, String, int, String, String)} instead
*/
@Deprecated
@@ -8093,24 +8145,36 @@
*/
public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName,
int proxiedUid, @Nullable String proxiedAttributionTag, @Nullable String message) {
- return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName, proxiedUid,
- proxiedAttributionTag, message);
+ return noteProxyOpNoThrow(strOpToOp(op), new AttributionSource(
+ mContext.getAttributionSource(), new AttributionSource(proxiedUid,
+ proxiedPackageName, proxiedAttributionTag)), message,
+ /*skipProxyOperation*/ false);
}
/**
- * @see #noteProxyOpNoThrow(String, String, int, String, String)
+ * Make note of an application performing an operation on behalf of another application(s).
+ *
+ * @param op The operation to note. One of the OPSTR_* constants.
+ * @param attributionSource The permission identity for which to note.
+ * @param message A message describing the reason the op was noted
+ * @param skipProxyOperation Whether to note op for the proxy
+ *
+ * @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).
*
* @hide
*/
@SuppressWarnings("AndroidFrameworkClientSidePermissionCheck")
- public int noteProxyOpNoThrow(int op, @Nullable String proxiedPackageName, int proxiedUid,
- @Nullable String proxiedAttributionTag, @Nullable String message) {
+ public int noteProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource,
+ @Nullable String message, boolean skipProxyOperation) {
int myUid = Process.myUid();
try {
collectNoteOpCallsForValidation(op);
- int collectionMode = getNotedOpCollectionMode(proxiedUid, proxiedPackageName, op);
- boolean shouldCollectMessage = myUid == Process.SYSTEM_UID ? true : false;
+ int collectionMode = getNotedOpCollectionMode(
+ attributionSource.getNextUid(),
+ attributionSource.getNextAttributionTag(), op);
+ boolean shouldCollectMessage = (myUid == Process.SYSTEM_UID);
if (collectionMode == COLLECT_ASYNC) {
if (message == null) {
// Set stack trace as default message
@@ -8119,20 +8183,19 @@
}
}
- int mode = mService.noteProxyOperation(op, proxiedUid, proxiedPackageName,
- proxiedAttributionTag, myUid, mContext.getOpPackageName(),
- mContext.getAttributionTag(), collectionMode == COLLECT_ASYNC, message,
- shouldCollectMessage);
+ int mode = mService.noteProxyOperation(op, attributionSource,
+ collectionMode == COLLECT_ASYNC, message,
+ shouldCollectMessage, skipProxyOperation);
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
- collectNotedOpForSelf(op, proxiedAttributionTag);
+ collectNotedOpForSelf(op, attributionSource.getNextAttributionTag());
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
&& (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
myUid) == PackageManager.PERMISSION_GRANTED ||
- Binder.getCallingUid() == proxiedUid)) {
- collectNotedOpSync(op, proxiedAttributionTag);
+ Binder.getCallingUid() == attributionSource.getNextUid())) {
+ collectNotedOpSync(op, attributionSource.getNextAttributionTag());
}
}
@@ -8424,7 +8487,7 @@
try {
collectNoteOpCallsForValidation(op);
int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
- boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID ? true : false;
+ boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID;
if (collectionMode == COLLECT_ASYNC) {
if (message == null) {
// Set stack trace as default message
@@ -8450,6 +8513,7 @@
throw e.rethrowFromSystemServer();
}
}
+
/**
* Report that an application has started executing a long-running operation on behalf of
* another application when handling an IPC. This function will verify that the calling uid and
@@ -8470,19 +8534,45 @@
*/
public int startProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName,
@Nullable String proxiedAttributionTag, @Nullable String message) {
- final int mode = startProxyOpNoThrow(op, proxiedUid, proxiedPackageName,
- proxiedAttributionTag, message);
+ return startProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
+ new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)),
+ message, /*skipProxyOperation*/ false);
+ }
+
+ /**
+ * Report that an application has started executing a long-running operation on behalf of
+ * another application for the attribution chain specified by the {@link AttributionSource}}.
+ *
+ * @param op The op to note
+ * @param attributionSource The permission identity for which to check
+ * @param message A message describing the reason the op was noted
+ * @param skipProxyOperation Whether to skip the proxy start.
+ *
+ * @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 any proxying operations in the permission identity
+ * chain fails.
+ *
+ * @hide
+ */
+ public int startProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource,
+ @Nullable String message, boolean skipProxyOperation) {
+ final int mode = startProxyOpNoThrow(AppOpsManager.strOpToOp(op), attributionSource,
+ message, skipProxyOperation);
if (mode == MODE_ERRORED) {
- throw new SecurityException("Proxy package " + mContext.getOpPackageName()
- + " from uid " + Process.myUid() + " or calling package " + proxiedPackageName
- + " from uid " + proxiedUid + " not allowed to perform "
- + sOpNames[strOpToOp(op)]);
+ throw new SecurityException("Proxy package "
+ + attributionSource.getPackageName() + " from uid "
+ + attributionSource.getUid() + " or calling package "
+ + attributionSource.getNextPackageName() + " from uid "
+ + attributionSource.getNextUid() + " not allowed to perform "
+ + op);
}
return mode;
}
/**
- *Like {@link #startProxyOp(String, int, String, String, String)} but instead
+ * Like {@link #startProxyOp(String, int, String, String, String)} but instead
* of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
*
* @see #startProxyOp(String, int, String, String, String)
@@ -8490,11 +8580,28 @@
public int startProxyOpNoThrow(@NonNull String op, int proxiedUid,
@NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag,
@Nullable String message) {
- try {
- int opInt = strOpToOp(op);
+ return startProxyOpNoThrow(AppOpsManager.strOpToOp(op), new AttributionSource(
+ mContext.getAttributionSource(), new AttributionSource(proxiedUid,
+ proxiedPackageName, proxiedAttributionTag)), message,
+ /*skipProxyOperation*/ false);
+ }
- collectNoteOpCallsForValidation(opInt);
- int collectionMode = getNotedOpCollectionMode(proxiedUid, proxiedPackageName, opInt);
+ /**
+ * Like {@link #startProxyOp(String, AttributionSource, String)} but instead
+ * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED} and
+ * the checks is for the attribution chain specified by the {@link AttributionSource}.
+ *
+ * @see #startProxyOp(String, AttributionSource, String)
+ *
+ * @hide
+ */
+ public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource,
+ @Nullable String message, boolean skipProxyOperation) {
+ try {
+ collectNoteOpCallsForValidation(op);
+ int collectionMode = getNotedOpCollectionMode(
+ attributionSource.getNextUid(),
+ attributionSource.getNextPackageName(), op);
boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID;
if (collectionMode == COLLECT_ASYNC) {
if (message == null) {
@@ -8504,24 +8611,23 @@
}
}
- int mode = mService.startProxyOperation(getClientId(), opInt, proxiedUid,
- proxiedPackageName, proxiedAttributionTag, Process.myUid(),
- mContext.getOpPackageName(), mContext.getAttributionTag(), false,
- collectionMode == COLLECT_ASYNC, message, shouldCollectMessage);
+ int mode = mService.startProxyOperation(getClientId(), op,
+ attributionSource, false, collectionMode == COLLECT_ASYNC, message,
+ shouldCollectMessage, skipProxyOperation);
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
- collectNotedOpForSelf(opInt, proxiedAttributionTag);
+ collectNotedOpForSelf(op,
+ attributionSource.getNextAttributionTag());
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
&& (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
Process.myUid()) == PackageManager.PERMISSION_GRANTED
- || Binder.getCallingUid() == proxiedUid)) {
- collectNotedOpSync(opInt, proxiedAttributionTag);
+ || Binder.getCallingUid() == attributionSource.getNextUid())) {
+ collectNotedOpSync(op, attributionSource.getNextAttributionTag());
}
}
-
return mode;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -8580,22 +8686,37 @@
}
/**
- * Report that an application is no longer performing an operation that had previously
+ * Report that an application is no longer performing an operation that had previously
* been started with {@link #startProxyOp(String, int, String, 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.
+ *
* @param op The operation which was started
- * @param proxiedUid The uid the op was started on behalf of
- * @param proxiedPackageName The package the op was started on behalf of
- * @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
- * attribution tag} or {@code null} for default attribution
+ * @param proxiedUid The proxied appp's UID
+ * @param proxiedPackageName The proxied appp's package name
+ * @param proxiedAttributionTag The proxied appp's attribution tag or
+ * {@code null} for default attribution
*/
public void finishProxyOp(@NonNull String op, int proxiedUid,
@NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag) {
+ finishProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
+ new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)));
+ }
+
+ /**
+ * Report that an application is no longer performing an operation that had previously
+ * been started with {@link #startProxyOp(String, AttributionSource, 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.
+ *
+ * @param op The operation which was started
+ * @param attributionSource The permission identity for which to finish
+ *
+ * @hide
+ */
+ public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource) {
try {
- mService.finishProxyOperation(getClientId(), strOpToOp(op), proxiedUid,
- proxiedPackageName, proxiedAttributionTag, Process.myUid(),
- mContext.getOpPackageName(), mContext.getAttributionTag());
+ mService.finishProxyOperation(getClientId(), strOpToOp(op), attributionSource);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -8616,6 +8737,46 @@
}
/**
+ * Get whether you are currently proxying to another package. That applies only
+ * for long running operations like {@link #OP_RECORD_AUDIO}.
+ *
+ * @param op The op.
+ * @param proxyAttributionTag Your attribution tag to query for.
+ * @param proxiedUid The proxied UID to query for.
+ * @param proxiedPackageName The proxied package to query for.
+ * @return Whether you are currently proxying to this target.
+ *
+ * @hide
+ */
+ public boolean isProxying(int op, @NonNull String proxyAttributionTag, int proxiedUid,
+ @NonNull String proxiedPackageName) {
+ try {
+ return mService.isProxying(op, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), proxiedUid, proxiedPackageName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Clears the op state (last accesses + op modes) for a package but not
+ * the historical state.
+ *
+ * @param packageName The package to reset.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.MANAGE_APPOPS)
+ public void resetPackageOpsNoHistory(@NonNull String packageName) {
+ try {
+ mService.resetPackageOpsNoHistory(packageName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Start collection of noted appops on this thread.
*
* <p>Called at the beginning of a two way binder transaction.
@@ -8771,7 +8932,7 @@
packageName = "android";
}
- // check it the appops needs to be collected and cache result
+ // check if the appops needs to be collected and cache result
if (sAppOpsToNote[op] == SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED) {
boolean shouldCollectNotes;
try {
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 5e032f0..a3d0cf2 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -18,12 +18,17 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.AttributionSource;
+import android.os.IBinder;
import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.TriFunction;
/**
* App ops service local interface.
@@ -76,6 +81,55 @@
@Nullable String message, boolean shouldCollectMessage,
@NonNull HeptFunction<Integer, Integer, String, String, Boolean, String, Boolean,
Integer> superImpl);
+
+ /**
+ * Allows overriding note proxy operation behavior.
+ *
+ * @param code The op code to note.
+ * @param attributionSource The permission identity of the caller.
+ * @param shouldCollectAsyncNotedOp If an {@link AsyncNotedAppOp} should be collected
+ * @param message The message in the async noted op
+ * @param shouldCollectMessage whether to collect messages
+ * @param skipProxyOperation Whether to skip the proxy portion of the operation
+ * @param superImpl The super implementation.
+ * @return The app op note result.
+ */
+ int noteProxyOperation(int code, @NonNull AttributionSource attributionSource,
+ boolean shouldCollectAsyncNotedOp, @Nullable String message,
+ boolean shouldCollectMessage, boolean skipProxyOperation,
+ @NonNull HexFunction<Integer, AttributionSource, Boolean, String, Boolean,
+ Boolean, Integer> superImpl);
+
+ /**
+ * Allows overriding start proxy operation behavior.
+ *
+ * @param code The op code to start.
+ * @param attributionSource The permission identity of the caller.
+ * @param startIfModeDefault Whether to start the op of the mode is default.
+ * @param shouldCollectAsyncNotedOp If an {@link AsyncNotedAppOp} should be collected
+ * @param message The message in the async noted op
+ * @param shouldCollectMessage whether to collect messages
+ * @param skipProxyOperation Whether to skip the proxy portion of the operation
+ * @param superImpl The super implementation.
+ * @return The app op note result.
+ */
+ int startProxyOperation(IBinder token, int code,
+ @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ boolean skipProxyOperation, @NonNull OctFunction<IBinder, Integer,
+ AttributionSource, Boolean, Boolean, String, Boolean, Boolean,
+ Integer> superImpl);
+
+ /**
+ * Allows overriding finish proxy op.
+ *
+ * @param clientId Client state token.
+ * @param code The op code to finish.
+ * @param attributionSource The permission identity of the caller.
+ */
+ void finishProxyOperation(IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource,
+ @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl);
}
/**
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 477e96b..9da2581 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -16,14 +16,16 @@
package android.app;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Build;
import android.os.Bundle;
-import android.os.PowerWhitelistManager;
-import android.os.PowerWhitelistManager.ReasonCode;
-import android.os.PowerWhitelistManager.TempAllowListType;
+import android.os.PowerExemptionManager;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
/**
* Helper class for building an options Bundle that can be used with
@@ -35,8 +37,7 @@
public class BroadcastOptions {
private long mTemporaryAppAllowlistDuration;
private @TempAllowListType int mTemporaryAppAllowlistType;
- private @ReasonCode int mTemporaryAppAllowlistReasonCode =
- PowerWhitelistManager.REASON_UNKNOWN;
+ private @ReasonCode int mTemporaryAppAllowlistReasonCode;
private @Nullable String mTemporaryAppAllowlistReason;
private int mMinManifestReceiverApiLevel = 0;
private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
@@ -47,59 +48,59 @@
* How long to temporarily put an app on the power allowlist when executing this broadcast
* to it.
*/
- static final String KEY_TEMPORARY_APP_ALLOWLIST_DURATION
+ private static final String KEY_TEMPORARY_APP_ALLOWLIST_DURATION
= "android:broadcast.temporaryAppAllowlistDuration";
- static final String KEY_TEMPORARY_APP_ALLOWLIST_TYPE
+ private static final String KEY_TEMPORARY_APP_ALLOWLIST_TYPE
= "android:broadcast.temporaryAppAllowlistType";
- static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE =
+ private static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE =
"android:broadcast.temporaryAppAllowlistReasonCode";
- static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON =
+ private static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON =
"android:broadcast.temporaryAppAllowlistReason";
/**
* Corresponds to {@link #setMinManifestReceiverApiLevel}.
*/
- static final String KEY_MIN_MANIFEST_RECEIVER_API_LEVEL
+ private static final String KEY_MIN_MANIFEST_RECEIVER_API_LEVEL
= "android:broadcast.minManifestReceiverApiLevel";
/**
* Corresponds to {@link #setMaxManifestReceiverApiLevel}.
*/
- static final String KEY_MAX_MANIFEST_RECEIVER_API_LEVEL
+ private static final String KEY_MAX_MANIFEST_RECEIVER_API_LEVEL
= "android:broadcast.maxManifestReceiverApiLevel";
/**
* Corresponds to {@link #setDontSendToRestrictedApps}.
*/
- static final String KEY_DONT_SEND_TO_RESTRICTED_APPS =
+ private static final String KEY_DONT_SEND_TO_RESTRICTED_APPS =
"android:broadcast.dontSendToRestrictedApps";
/**
* Corresponds to {@link #setBackgroundActivityStartsAllowed}.
*/
- static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS =
+ private static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS =
"android:broadcast.allowBackgroundActivityStarts";
/**
* @hide
- * @deprecated Use {@link android.os.PowerWhitelistManager#
- * TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED} instead.
+ * @deprecated Use {@link android.os.PowerExemptionManager#
+ * TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED} instead.
*/
@Deprecated
public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED =
- PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+ PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
/**
* @hide
- * @deprecated Use {@link android.os.PowerWhitelistManager#
- * TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} instead.
+ * @deprecated Use {@link android.os.PowerExemptionManager#
+ * TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} instead.
*/
@Deprecated
public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED =
- PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
+ PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
public static BroadcastOptions makeBasic() {
BroadcastOptions opts = new BroadcastOptions();
@@ -107,15 +108,22 @@
}
private BroadcastOptions() {
+ resetTemporaryAppAllowlist();
}
/** @hide */
- public BroadcastOptions(Bundle opts) {
- mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION);
- mTemporaryAppAllowlistType = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE);
- mTemporaryAppAllowlistReasonCode = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE,
- PowerWhitelistManager.REASON_UNKNOWN);
- mTemporaryAppAllowlistReason = opts.getString(KEY_TEMPORARY_APP_ALLOWLIST_REASON);
+ @TestApi
+ public BroadcastOptions(@NonNull Bundle opts) {
+ // Match the logic in toBundle().
+ if (opts.containsKey(KEY_TEMPORARY_APP_ALLOWLIST_DURATION)) {
+ mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION);
+ mTemporaryAppAllowlistType = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE);
+ mTemporaryAppAllowlistReasonCode = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE,
+ PowerExemptionManager.REASON_UNKNOWN);
+ mTemporaryAppAllowlistReason = opts.getString(KEY_TEMPORARY_APP_ALLOWLIST_REASON);
+ } else {
+ resetTemporaryAppAllowlist();
+ }
mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0);
mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL,
Build.VERSION_CODES.CUR_DEVELOPMENT);
@@ -136,18 +144,21 @@
android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
public void setTemporaryAppWhitelistDuration(long duration) {
setTemporaryAppAllowlist(duration,
- PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
- PowerWhitelistManager.REASON_UNKNOWN, null);
+ PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ PowerExemptionManager.REASON_UNKNOWN, null);
}
/**
* Set a duration for which the system should temporary place an application on the
* power allowlist when this broadcast is being delivered to it, specify the temp allowlist
* type.
- * @param duration the duration in milliseconds; 0 means to not place on allowlist.
- * @param type one of {@link TempAllowListType}
+ * @param duration the duration in milliseconds.
+ * 0 means to not place on allowlist, and clears previous call to this method.
+ * @param type one of {@link TempAllowListType}.
+ * {@link PowerExemptionManager#TEMPORARY_ALLOW_LIST_TYPE_NONE} means
+ * to not place on allowlist, and clears previous call to this method.
* @param reasonCode one of {@link ReasonCode}, use
- * {@link PowerWhitelistManager#REASON_UNKNOWN} if not sure.
+ * {@link PowerExemptionManager#REASON_UNKNOWN} if not sure.
* @param reason A human-readable reason explaining why the app is temp allowlisted. Only
* used for logging purposes. Could be null or empty string.
*/
@@ -160,12 +171,30 @@
mTemporaryAppAllowlistType = type;
mTemporaryAppAllowlistReasonCode = reasonCode;
mTemporaryAppAllowlistReason = reason;
+
+ if (!isTemporaryAppAllowlistSet()) {
+ resetTemporaryAppAllowlist();
+ }
+ }
+
+ private boolean isTemporaryAppAllowlistSet() {
+ return mTemporaryAppAllowlistDuration > 0
+ && mTemporaryAppAllowlistType
+ != PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
+ }
+
+ private void resetTemporaryAppAllowlist() {
+ mTemporaryAppAllowlistDuration = 0;
+ mTemporaryAppAllowlistType = PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
+ mTemporaryAppAllowlistReasonCode = PowerExemptionManager.REASON_UNKNOWN;
+ mTemporaryAppAllowlistReason = null;
}
/**
* Return {@link #setTemporaryAppAllowlist}.
* @hide
*/
+ @TestApi
public long getTemporaryAppAllowlistDuration() {
return mTemporaryAppAllowlistDuration;
}
@@ -174,6 +203,7 @@
* Return {@link #mTemporaryAppAllowlistType}.
* @hide
*/
+ @TestApi
public @TempAllowListType int getTemporaryAppAllowlistType() {
return mTemporaryAppAllowlistType;
}
@@ -182,6 +212,7 @@
* Return {@link #mTemporaryAppAllowlistReasonCode}.
* @hide
*/
+ @TestApi
public @ReasonCode int getTemporaryAppAllowlistReasonCode() {
return mTemporaryAppAllowlistReasonCode;
}
@@ -190,6 +221,7 @@
* Return {@link #mTemporaryAppAllowlistReason}.
* @hide
*/
+ @TestApi
public @Nullable String getTemporaryAppAllowlistReason() {
return mTemporaryAppAllowlistReason;
}
@@ -276,16 +308,10 @@
*/
public Bundle toBundle() {
Bundle b = new Bundle();
- if (mTemporaryAppAllowlistDuration > 0) {
+ if (isTemporaryAppAllowlistSet()) {
b.putLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION, mTemporaryAppAllowlistDuration);
- }
- if (mTemporaryAppAllowlistType != 0) {
b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE, mTemporaryAppAllowlistType);
- }
- if (mTemporaryAppAllowlistReasonCode != PowerWhitelistManager.REASON_UNKNOWN) {
b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE, mTemporaryAppAllowlistReasonCode);
- }
- if (mTemporaryAppAllowlistReason != null) {
b.putString(KEY_TEMPORARY_APP_ALLOWLIST_REASON, mTemporaryAppAllowlistReason);
}
if (mMinManifestReceiverApiLevel != 0) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 03e95fc..eb31b52 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -60,6 +60,7 @@
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.content.AttributionSource;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -224,8 +225,8 @@
private final String mBasePackageName;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final String mOpPackageName;
-
private final @NonNull ContextParams mParams;
+ private final @NonNull AttributionSource mAttributionSource;
private final @NonNull ResourcesManager mResourcesManager;
@UnsupportedAppUsage
@@ -467,13 +468,13 @@
/** @hide */
@Override
public String getOpPackageName() {
- return mOpPackageName != null ? mOpPackageName : getBasePackageName();
+ return mAttributionSource.getPackageName();
}
/** @hide */
@Override
public @Nullable String getAttributionTag() {
- return mParams.getAttributionTag();
+ return mAttributionSource.getAttributionTag();
}
@Override
@@ -482,6 +483,11 @@
}
@Override
+ public @NonNull AttributionSource getAttributionSource() {
+ return mAttributionSource;
+ }
+
+ @Override
public ApplicationInfo getApplicationInfo() {
if (mPackageInfo != null) {
return mPackageInfo.getApplicationInfo();
@@ -2074,13 +2080,7 @@
Log.v(TAG, "Treating renounced permission " + permission + " as denied");
return PERMISSION_DENIED;
}
-
- try {
- return ActivityManager.getService().checkPermissionWithToken(
- permission, pid, uid, callerToken);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return checkPermission(permission, pid, uid);
}
@Override
@@ -2415,8 +2415,10 @@
LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE);
if (pi != null) {
- ContextImpl c = new ContextImpl(this, mMainThread, pi, ContextParams.EMPTY, null,
- mToken, new UserHandle(UserHandle.getUserId(application.uid)),
+ ContextImpl c = new ContextImpl(this, mMainThread, pi, ContextParams.EMPTY,
+ mAttributionSource.getAttributionTag(),
+ mAttributionSource.getNext(),
+ null, mToken, new UserHandle(UserHandle.getUserId(application.uid)),
flags, null, null);
final int displayId = getDisplayId();
@@ -2446,15 +2448,19 @@
if (packageName.equals("system") || packageName.equals("android")) {
// The system resources are loaded in every application, so we can safely copy
// the context without reloading Resources.
- return new ContextImpl(this, mMainThread, mPackageInfo, mParams, null,
- mToken, user, flags, null, null);
+ return new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+ mAttributionSource.getAttributionTag(),
+ mAttributionSource.getNext(),
+ null, mToken, user, flags, null, null);
}
LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
if (pi != null) {
- ContextImpl c = new ContextImpl(this, mMainThread, pi, mParams, null,
- mToken, user, flags, null, null);
+ ContextImpl c = new ContextImpl(this, mMainThread, pi, mParams,
+ mAttributionSource.getAttributionTag(),
+ mAttributionSource.getNext(),
+ null, mToken, user, flags, null, null);
final int displayId = getDisplayId();
final Integer overrideDisplayId = mForceDisplayOverrideInResources
@@ -2491,8 +2497,10 @@
final ClassLoader classLoader = mPackageInfo.getSplitClassLoader(splitName);
final String[] paths = mPackageInfo.getSplitPaths(splitName);
- final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo,
- mParams, splitName, mToken, mUser, mFlags, classLoader, null);
+ final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+ mAttributionSource.getAttributionTag(),
+ mAttributionSource.getNext(),
+ splitName, mToken, mUser, mFlags, classLoader, null);
context.setResources(ResourcesManager.getInstance().getResources(
mToken,
@@ -2526,6 +2534,8 @@
}
ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+ mAttributionSource.getAttributionTag(),
+ mAttributionSource.getNext(),
mSplitName, mToken, mUser, mFlags, mClassLoader, null);
final int displayId = getDisplayId();
@@ -2544,6 +2554,8 @@
}
ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+ mAttributionSource.getAttributionTag(),
+ mAttributionSource.getNext(),
mSplitName, mToken, mUser, mFlags, mClassLoader, null);
final int displayId = display.getDisplayId();
@@ -2650,6 +2662,8 @@
@UiContext
ContextImpl createWindowContextBase(@NonNull IBinder token, @NonNull Display display) {
ContextImpl baseContext = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+ mAttributionSource.getAttributionTag(),
+ mAttributionSource.getNext(),
mSplitName, token, mUser, mFlags, mClassLoader, null);
// Window contexts receive configurations directly from the server and as such do not
// need to override their display in ResourcesManager.
@@ -2695,9 +2709,10 @@
@NonNull
@Override
- public Context createContext(@NonNull ContextParams params) {
- return new ContextImpl(this, mMainThread, mPackageInfo, params, mSplitName,
- mToken, mUser, mFlags, mClassLoader, null);
+ public Context createContext(@NonNull ContextParams contextParams) {
+ return new ContextImpl(this, mMainThread, mPackageInfo, contextParams,
+ contextParams.getAttributionTag(), contextParams.getNextAttributionSource(),
+ mSplitName, mToken, mUser, mFlags, mClassLoader, null);
}
@Override
@@ -2710,16 +2725,20 @@
public Context createDeviceProtectedStorageContext() {
final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
| Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
- return new ContextImpl(this, mMainThread, mPackageInfo, mParams, mSplitName,
- mToken, mUser, flags, mClassLoader, null);
+ return new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+ mAttributionSource.getAttributionTag(),
+ mAttributionSource.getNext(),
+ mSplitName, mToken, mUser, flags, mClassLoader, null);
}
@Override
public Context createCredentialProtectedStorageContext() {
final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
| Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
- return new ContextImpl(this, mMainThread, mPackageInfo, mParams, mSplitName,
- mToken, mUser, flags, mClassLoader, null);
+ return new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+ mAttributionSource.getAttributionTag(),
+ mAttributionSource.getNext(),
+ mSplitName, mToken, mUser, flags, mClassLoader, null);
}
@Override
@@ -2893,7 +2912,7 @@
static ContextImpl createSystemContext(ActivityThread mainThread) {
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread, packageInfo,
- ContextParams.EMPTY, null, null, null, 0, null, null);
+ ContextParams.EMPTY, null, null, null, null, null, 0, null, null);
context.setResources(packageInfo.getResources());
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetrics());
@@ -2911,7 +2930,7 @@
static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
final LoadedApk packageInfo = systemContext.mPackageInfo;
ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo,
- ContextParams.EMPTY, null, null, null, 0, null, null);
+ ContextParams.EMPTY, null, null, null, null, null, 0, null, null);
context.setResources(createResources(null, packageInfo, null, displayId, null,
packageInfo.getCompatibilityInfo(), null));
context.updateDisplay(displayId);
@@ -2936,7 +2955,7 @@
String opPackageName) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
ContextImpl context = new ContextImpl(null, mainThread, packageInfo,
- ContextParams.EMPTY, null, null, null, 0, null, opPackageName);
+ ContextParams.EMPTY, null, null, null, null, null, 0, null, opPackageName);
context.setResources(packageInfo.getResources());
context.mContextType = isSystemOrSystemUI(context) ? CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI
: CONTEXT_TYPE_NON_UI;
@@ -2966,7 +2985,7 @@
}
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, ContextParams.EMPTY,
- activityInfo.splitName, activityToken, null, 0, classLoader, null);
+ null, null, activityInfo.splitName, activityToken, null, 0, classLoader, null);
context.mContextType = CONTEXT_TYPE_ACTIVITY;
// Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY.
@@ -2999,6 +3018,7 @@
private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
@NonNull LoadedApk packageInfo, @NonNull ContextParams params,
+ @Nullable String attributionTag, @Nullable AttributionSource nextAttributionSource,
@Nullable String splitName, @Nullable IBinder token, @Nullable UserHandle user,
int flags, @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) {
mOuterContext = this;
@@ -3054,9 +3074,28 @@
mOpPackageName = overrideOpPackageName != null ? overrideOpPackageName : opPackageName;
mParams = Objects.requireNonNull(params);
+ mAttributionSource = createAttributionSource(attributionTag, nextAttributionSource);
mContentResolver = new ApplicationContentResolver(this, mainThread);
}
+ private @NonNull AttributionSource createAttributionSource(@Nullable String attributionTag,
+ @Nullable AttributionSource nextAttributionSource) {
+ AttributionSource attributionSource = new AttributionSource(Process.myUid(), mOpPackageName,
+ attributionTag, nextAttributionSource);
+ // If we want to access protected data on behalf of another app we need to
+ // tell the OS that we opt in to participate in the attribution chain.
+ if (nextAttributionSource != null) {
+ // If an app happened to stub the internal OS for testing the registration method
+ // can return null. In this case we keep the current untrusted attribution source.
+ final AttributionSource registeredAttributionSource = getSystemService(
+ PermissionManager.class).registerAttributionSource(attributionSource);
+ if (registeredAttributionSource != null) {
+ return registeredAttributionSource;
+ }
+ }
+ return attributionSource;
+ }
+
void setResources(Resources r) {
if (r instanceof CompatResources) {
((CompatResources) r).setContext(this);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 4c2433c..81e5e1d 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -475,8 +475,6 @@
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
boolean isTopOfTask(in IBinder token);
void bootAnimationComplete();
- int checkPermissionWithToken(in String permission, int pid, int uid,
- in IBinder callerToken);
@UnsupportedAppUsage
void registerTaskStackListener(in ITaskStackListener listener);
void unregisterTaskStackListener(in ITaskStackListener listener);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index bda2fa9..a5f8f10 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -104,7 +104,6 @@
void createConversationNotificationChannelForPackage(String pkg, int uid, in NotificationChannel parentChannel, String conversationId);
NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, String conversationId, boolean includeDeleted);
void deleteNotificationChannel(String pkg, String channelId);
- void deleteConversationNotificationChannels(String pkg, int uid, String conversationId);
ParceledListSlice getNotificationChannels(String callingPkg, String targetPkg, int userId);
ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index d47c3ca..2fbea28 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5360,6 +5360,11 @@
// Use different highlighted colors except when low-priority mode prevents that
if (!p.mReduceHighlights) {
pillColor = getAccentTertiaryColor(p);
+ // TODO(b/183710694): The accent tertiary is currently too bright in dark mode, so
+ // we need to pick a contrasting color.
+ textColor = ColorUtils.setAlphaComponent(
+ ContrastColorUtil.resolvePrimaryColor(mContext, pillColor, mInNightMode),
+ 0xFF);
}
contentView.setInt(R.id.expand_button, "setHighlightTextColor", textColor);
contentView.setInt(R.id.expand_button, "setHighlightPillColor", pillColor);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 26e6741..89d08cc 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1675,6 +1675,29 @@
})
public @interface PasswordComplexity {}
+ /** Indicates that nearby streaming is disabled. */
+ public static final int NEARBY_STREAMING_DISABLED = 0;
+
+ /** Indicates that nearby streaming is enabled. */
+ public static final int NEARBY_STREAMING_ENABLED = 1;
+
+ /**
+ * Indicates that nearby streaming is enabled only to devices offering a comparable level of
+ * security, with the same authenticated managed account.
+ */
+ public static final int NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY = 2;
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"NEARBY_STREAMING_"}, value = {
+ NEARBY_STREAMING_DISABLED,
+ NEARBY_STREAMING_ENABLED,
+ NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY,
+ })
+ public @interface NearbyStreamingPolicy {}
+
/**
* Activity action: have the user enter a new password for the parent profile.
* If the intent is launched from within a managed profile, this will trigger
@@ -7163,6 +7186,77 @@
}
/**
+ * Called by a device/profile owner to set nearby notification streaming policy. Notification
+ * streaming is sending notification data from pre-installed apps to nearby devices.
+ *
+ * @param policy One of the {@code NearbyStreamingPolicy} constants.
+ * @throws SecurityException if caller is not a device or profile owner
+ */
+ public void setNearbyNotificationStreamingPolicy(@NearbyStreamingPolicy int policy) {
+ throwIfParentInstance("setNearbyNotificationStreamingPolicy");
+ if (mService == null) {
+ return;
+ }
+ try {
+ mService.setNearbyNotificationStreamingPolicy(policy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the current runtime nearby notification streaming policy set by the device or profile
+ * owner. The default is {@link #NEARBY_STREAMING_DISABLED}.
+ */
+ public @NearbyStreamingPolicy int getNearbyNotificationStreamingPolicy() {
+ throwIfParentInstance("getNearbyNotificationStreamingPolicy");
+ if (mService == null) {
+ return NEARBY_STREAMING_DISABLED;
+ }
+ try {
+ return mService.getNearbyNotificationStreamingPolicy();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Called by a device/profile owner to set nearby app streaming policy. App streaming is when
+ * the device starts an app on a virtual display and sends a video stream of the app to nearby
+ * devices.
+ *
+ * @param policy One of the {@code NearbyStreamingPolicy} constants.
+ * @throws SecurityException if caller is not a device or profile owner.
+ */
+ public void setNearbyAppStreamingPolicy(@NearbyStreamingPolicy int policy) {
+ throwIfParentInstance("setNearbyAppStreamingPolicy");
+ if (mService == null) {
+ return;
+ }
+ try {
+ mService.setNearbyAppStreamingPolicy(policy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the current runtime nearby app streaming policy set by the device or profile owner.
+ * The default is {@link #NEARBY_STREAMING_DISABLED}.
+ */
+ public @NearbyStreamingPolicy int getNearbyAppStreamingPolicy() {
+ throwIfParentInstance("getNearbyAppStreamingPolicy");
+ if (mService == null) {
+ return NEARBY_STREAMING_DISABLED;
+ }
+ try {
+ return mService.getNearbyAppStreamingPolicy();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Called by a device owner, or alternatively a profile owner from Android 8.0 (API level 26) or
* higher, to set whether auto time is required. If auto time is required, no user will be able
* set the date and time and network date and time will be used.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 5e49a98..8a8c69c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -132,6 +132,12 @@
void setScreenCaptureDisabled(in ComponentName who, boolean disabled, boolean parent);
boolean getScreenCaptureDisabled(in ComponentName who, int userHandle, boolean parent);
+ void setNearbyNotificationStreamingPolicy(int policy);
+ int getNearbyNotificationStreamingPolicy();
+
+ void setNearbyAppStreamingPolicy(int policy);
+ int getNearbyAppStreamingPolicy();
+
void setKeyguardDisabledFeatures(in ComponentName who, int which, boolean parent);
int getKeyguardDisabledFeatures(in ComponentName who, int userHandle, boolean parent);
diff --git a/core/java/android/app/time/ExternalTimeSuggestion.java b/core/java/android/app/time/ExternalTimeSuggestion.java
index 61defb5..8e281c0 100644
--- a/core/java/android/app/time/ExternalTimeSuggestion.java
+++ b/core/java/android/app/time/ExternalTimeSuggestion.java
@@ -20,6 +20,7 @@
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.TimestampedValue;
@@ -67,6 +68,7 @@
*
* @hide
*/
+@SystemApi
public final class ExternalTimeSuggestion implements Parcelable {
public static final @NonNull Creator<ExternalTimeSuggestion> CREATOR =
@@ -129,7 +131,6 @@
/**
* Returns information that can be useful for debugging / logging. See {@link #addDebugInfo}.
- * {@hide}
*/
@NonNull
public List<String> getDebugInfo() {
diff --git a/core/java/android/app/time/TimeManager.java b/core/java/android/app/time/TimeManager.java
index c71badb0..d6acb8c 100644
--- a/core/java/android/app/time/TimeManager.java
+++ b/core/java/android/app/time/TimeManager.java
@@ -262,7 +262,6 @@
* HAL. This time <em>may</em> be used to set the device system clock, depending on the device
* configuration and user settings. This method call is processed asynchronously.
* See {@link ExternalTimeSuggestion} for more details.
- * {@hide}
*/
@RequiresPermission(android.Manifest.permission.SUGGEST_EXTERNAL_TIME)
public void suggestExternalTime(@NonNull ExternalTimeSuggestion timeSuggestion) {
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 30ea5c4..2a50e0d 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -67,4 +67,5 @@
void reportUsageStop(in IBinder activity, String token, String callingPackage);
int getUsageSource();
void forceUsageSourceSettingRead();
+ long getLastTimeAnyComponentUsed(String packageName);
}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 1db7e9d..067c212 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -1250,4 +1250,33 @@
} catch (RemoteException re) {
}
}
+
+ /**
+ * Get the last time a package is used by any users including explicit user interaction and
+ * component usage, measured in milliseconds since the epoch and truncated to the boundary of
+ * last day before the exact time. For packages that are never used, the time will be the epoch.
+ * <p> Note that this usage stats is user-agnostic. </p>
+ * <p>
+ * Also note that component usage is only reported for component bindings (e.g. broadcast
+ * receiver, service, content provider) and only when such a binding would cause an app to leave
+ * the stopped state.
+ * See {@link UsageEvents.Event.USER_INTERACTION}, {@link UsageEvents.Event.APP_COMPONENT_USED}.
+ * </p>
+ *
+ * @param packageName The name of the package to be queried.
+ * @return last time the queried package is used since the epoch.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.PACKAGE_USAGE_STATS})
+ public long getLastTimeAnyComponentUsed(@NonNull String packageName) {
+ // TODO(b/183462940): This usage data is not persisted to disk yet.
+ try {
+ return mService.getLastTimeAnyComponentUsed(packageName);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index a3d19ca..0be7b73 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -745,7 +745,6 @@
* Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
*/
BluetoothAdapter(IBluetoothManager managerService) {
-
if (managerService == null) {
throw new IllegalArgumentException("bluetooth manager service is null");
}
diff --git a/core/java/android/content/AttributionSource.aidl b/core/java/android/content/AttributionSource.aidl
new file mode 100644
index 0000000..10d5c27
--- /dev/null
+++ b/core/java/android/content/AttributionSource.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+parcelable AttributionSource;
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
new file mode 100644
index 0000000..053bfc1
--- /dev/null
+++ b/core/java/android/content/AttributionSource.java
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.app.AppGlobals;
+import android.os.Binder;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.permission.PermissionManager;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.Immutable;
+import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * This class represents a source to which access to permission protected data should be
+ * attributed. Attribution sources can be chained to represent cases where the protected
+ * data would flow through several applications. For example, app A may ask app B for
+ * contacts and in turn app B may ask app C for contacts. In this case, the attribution
+ * chain would be A -> B -> C and the data flow would be C -> B -> A. There are two
+ * main benefits of using the attribution source mechanism: avoid doing explicit permission
+ * checks on behalf of the calling app if you are accessing private data on their behalf
+ * to send back; avoid double data access blaming which happens as you check the calling
+ * app's permissions and when you access the data behind these permissions (for runtime
+ * permissions). Also if not explicitly blaming the caller the data access would be
+ * counted towards your app vs to the previous app where yours was just a proxy.
+ * <p>
+ * Every {@link Context} has an attribution source and you can get it via {@link
+ * Context#getAttributionSource()} representing itself, which is a chain of one. You
+ * can attribute work to another app, or more precisely to a chain of apps, through
+ * which the data you would be accessing would flow, via {@link Context#createContext(
+ * ContextParams)} plus specifying an attribution source for the next app to receive
+ * the protected data you are accessing via {@link AttributionSource.Builder#setNext(
+ * AttributionSource)}. Creating this attribution chain ensures that the datasource would
+ * check whether every app in the attribution chain has permission to access the data
+ * before releasing it. The datasource will also record appropriately that this data was
+ * accessed by the apps in the sequence if the data is behind a sensitive permission
+ * (e.g. dangerous). Again, this is useful if you are accessing the data on behalf of another
+ * app, for example a speech recognizer using the mic so it can provide recognition to
+ * a calling app.
+ * <p>
+ * You can create an attribution chain of you and any other app without any verification
+ * as this is something already available via the {@link android.app.AppOpsManager} APIs.
+ * This is supported to handle cases where you don't have access to the caller's attribution
+ * source and you can directly use the {@link AttributionSource.Builder} APIs. However,
+ * if the data flows through more than two apps (more than you access the data for the
+ * caller - which you cannot know ahead of time) you need to have a handle to the {@link
+ * AttributionSource} for the calling app's context in order to create an attribution context.
+ * This means you either need to have an API for the other app to send you its attribution
+ * source or use a platform API that pipes the callers attribution source.
+ * <p>
+ * You cannot forge an attribution chain without the participation of every app in the
+ * attribution chain (aside of the special case mentioned above). To create an attribution
+ * source that is trusted you need to create an attribution context that points to an
+ * attribution source that was explicitly created by the app that it refers to, recursively.
+ * <p>
+ * Since creating an attribution context leads to all permissions for apps in the attribution
+ * chain being checked, you need to expect getting a security exception when accessing
+ * permission protected APIs since some app in the chain may not have the permission.
+ */
+@Immutable
+// TODO: Codegen doesn't properly verify the class if the parcelling is inner class
+// TODO: Codegen doesn't allow overriding the constructor to change its visibility
+// TODO: Codegen applies method level annotations to argument vs the generated member (@SystemApi)
+// TODO: Codegen doesn't properly read/write IBinder members
+// TODO: Codegen doesn't properly handle Set arguments
+// @DataClass(genEqualsHashCode = true, genConstructor = false, genBuilder = true)
+public final class AttributionSource implements Parcelable {
+ /**
+ * @hide
+ */
+ static class RenouncedPermissionsParcelling implements Parcelling<Set<String>> {
+
+ @Override
+ public void parcel(Set<String> item, Parcel dest, int parcelFlags) {
+ if (item == null) {
+ dest.writeInt(-1);
+ } else {
+ dest.writeInt(item.size());
+ for (String permission : item) {
+ dest.writeString8(permission);
+ }
+ }
+ }
+
+ @Override
+ public Set<String> unparcel(Parcel source) {
+ final int size = source.readInt();
+ if (size < 0) {
+ return null;
+ }
+ final ArraySet<String> result = new ArraySet<>(size);
+ for (int i = 0; i < size; i++) {
+ result.add(source.readString8());
+ }
+ return result;
+ }
+ }
+
+ /**
+ * The UID that is accessing the permission protected data.
+ */
+ private final int mUid;
+
+ /**
+ * The package that is accessing the permission protected data.
+ */
+ private @Nullable String mPackageName = null;
+
+ /**
+ * The attribution tag of the app accessing the permission protected data.
+ */
+ private @Nullable String mAttributionTag = null;
+
+ /**
+ * Unique token for that source.
+ *
+ * @hide
+ */
+ private @Nullable IBinder mToken = null;
+
+ /**
+ * Permissions that should be considered revoked regardless if granted.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
+ @DataClass.ParcelWith(RenouncedPermissionsParcelling.class)
+ private @Nullable Set<String> mRenouncedPermissions = null;
+
+ /**
+ * The next app to receive the permission protected data.
+ */
+ private @Nullable AttributionSource mNext = null;
+
+ /** @hide */
+ @TestApi
+ public AttributionSource(int uid, @Nullable String packageName,
+ @Nullable String attributionTag) {
+ this(uid, packageName, attributionTag, /*next*/ null);
+ }
+
+ /** @hide */
+ @TestApi
+ public AttributionSource(int uid, @Nullable String packageName,
+ @Nullable String attributionTag, @Nullable AttributionSource next) {
+ this(uid, packageName, attributionTag, /*token*/ null,
+ /*renouncedPermissions*/ null, next);
+ }
+
+ /** @hide */
+ public AttributionSource(@NonNull AttributionSource current,
+ @Nullable AttributionSource next) {
+ this(current.getUid(), current.getPackageName(), current.getAttributionTag(),
+ /*token*/ null, /*renouncedPermissions*/ null, next);
+ }
+
+ /** @hide */
+ public AttributionSource withNextAttributionSource(@Nullable AttributionSource next) {
+ return new AttributionSource(mUid, mPackageName, mAttributionTag, mToken,
+ mRenouncedPermissions, next);
+ }
+
+ /** @hide */
+ public AttributionSource withToken(@Nullable IBinder token) {
+ return new AttributionSource(mUid, mPackageName, mAttributionTag, token,
+ mRenouncedPermissions, mNext);
+ }
+
+ /**
+ * If you are handling an IPC and you don't trust the caller you need to validate
+ * whether the attribution source is one for the calling app to prevent the caller
+ * to pass you a source from another app without including themselves in the
+ * attribution chain.
+ *
+ * @throws SecurityException if the attribution source cannot be trusted to be
+ * from the caller.
+ */
+ public void enforceCallingUid() {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.SYSTEM_UID && callingUid != mUid) {
+ throw new SecurityException("Calling uid: " + callingUid
+ + " doesn't match source uid: " + mUid);
+ }
+ // No need to check package as app ops manager does it already.
+ }
+
+ /**
+ * If you are handling an IPC and you don't trust the caller you need to validate
+ * whether the attribution source is one for the calling app to prevent the caller
+ * to pass you a source from another app without including themselves in the
+ * attribution chain.
+ *f
+ * @return if the attribution source cannot be trusted to be from the caller.
+ */
+ public boolean checkCallingUid() {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.SYSTEM_UID && callingUid != mUid) {
+ return false;
+ }
+ // No need to check package as app ops manager does it already.
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ if (Build.IS_DEBUGGABLE) {
+ return "AttributionSource { " +
+ "uid = " + mUid + ", " +
+ "packageName = " + mPackageName + ", " +
+ "attributionTag = " + mAttributionTag + ", " +
+ "token = " + mToken + ", " +
+ "next = " + mNext +
+ " }";
+ }
+ return super.toString();
+ }
+
+ /**
+ * @return The next UID that would receive the permission protected data.
+ *
+ * @hide
+ */
+ public int getNextUid() {
+ if (mNext != null) {
+ return mNext.getUid();
+ }
+ return Process.INVALID_UID;
+ }
+
+ /**
+ * @return The next package that would receive the permission protected data.
+ *
+ * @hide
+ */
+ public @Nullable String getNextPackageName() {
+ if (mNext != null) {
+ return mNext.getPackageName();
+ }
+ return null;
+ }
+
+ /**
+ * @return The nexxt package's attribution tag that would receive
+ * the permission protected data.
+ *
+ * @hide
+ */
+ public @Nullable String getNextAttributionTag() {
+ if (mNext != null) {
+ return mNext.getAttributionTag();
+ }
+ return null;
+ }
+
+ /**
+ * Checks whether this attribution source can be trusted. That is whether
+ * the app it refers to created it and provided to the attribution chain.
+ *
+ * @param context Context handle.
+ * @return Whether this is a trusted source.
+ */
+ public boolean isTrusted(@NonNull Context context) {
+ return mToken != null && context.getSystemService(PermissionManager.class)
+ .isRegisteredAttributionSource(this);
+ }
+
+ /**
+ * Permissions that should be considered revoked regardless if granted.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
+ @NonNull
+ public Set<String> getRenouncedPermissions() {
+ return CollectionUtils.emptyIfNull(mRenouncedPermissions);
+ }
+
+ @DataClass.Suppress({"setUid", "setToken"})
+ static class BaseBuilder {}
+
+
+
+
+
+
+ // Code below generated by codegen v1.0.22.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/AttributionSource.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /* package-private */ AttributionSource(
+ int uid,
+ @Nullable String packageName,
+ @Nullable String attributionTag,
+ @Nullable IBinder token,
+ @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) @Nullable Set<String> renouncedPermissions,
+ @Nullable AttributionSource next) {
+ this.mUid = uid;
+ this.mPackageName = packageName;
+ this.mAttributionTag = attributionTag;
+ this.mToken = token;
+ this.mRenouncedPermissions = renouncedPermissions;
+ com.android.internal.util.AnnotationValidations.validate(
+ SystemApi.class, null, mRenouncedPermissions);
+ com.android.internal.util.AnnotationValidations.validate(
+ RequiresPermission.class, null, mRenouncedPermissions,
+ "value", android.Manifest.permission.RENOUNCE_PERMISSIONS);
+ this.mNext = next;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The UID that is accessing the permission protected data.
+ */
+ public int getUid() {
+ return mUid;
+ }
+
+ /**
+ * The package that is accessing the permission protected data.
+ */
+ public @Nullable String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * The attribution tag of the app accessing the permission protected data.
+ */
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
+ }
+
+ /**
+ * Unique token for that source.
+ *
+ * @hide
+ */
+ public @Nullable IBinder getToken() {
+ return mToken;
+ }
+
+ /**
+ * The next app to receive the permission protected data.
+ */
+ public @Nullable AttributionSource getNext() {
+ return mNext;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(AttributionSource other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ AttributionSource that = (AttributionSource) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mUid == that.mUid
+ && Objects.equals(mPackageName, that.mPackageName)
+ && Objects.equals(mAttributionTag, that.mAttributionTag)
+ && Objects.equals(mToken, that.mToken)
+ && Objects.equals(mRenouncedPermissions, that.mRenouncedPermissions)
+ && Objects.equals(mNext, that.mNext);
+ }
+
+ @Override
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mUid;
+ _hash = 31 * _hash + Objects.hashCode(mPackageName);
+ _hash = 31 * _hash + Objects.hashCode(mAttributionTag);
+ _hash = 31 * _hash + Objects.hashCode(mToken);
+ _hash = 31 * _hash + Objects.hashCode(mRenouncedPermissions);
+ _hash = 31 * _hash + Objects.hashCode(mNext);
+ return _hash;
+ }
+
+ static Parcelling<Set<String>> sParcellingForRenouncedPermissions =
+ Parcelling.Cache.get(
+ RenouncedPermissionsParcelling.class);
+ static {
+ if (sParcellingForRenouncedPermissions == null) {
+ sParcellingForRenouncedPermissions = Parcelling.Cache.put(
+ new RenouncedPermissionsParcelling());
+ }
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mPackageName != null) flg |= 0x2;
+ if (mAttributionTag != null) flg |= 0x4;
+ if (mToken != null) flg |= 0x8;
+ if (mRenouncedPermissions != null) flg |= 0x10;
+ if (mNext != null) flg |= 0x20;
+ dest.writeByte(flg);
+ dest.writeInt(mUid);
+ if (mPackageName != null) dest.writeString(mPackageName);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
+ if (mToken != null) dest.writeStrongBinder(mToken);
+ sParcellingForRenouncedPermissions.parcel(mRenouncedPermissions, dest, flags);
+ if (mNext != null) dest.writeTypedObject(mNext, flags);
+ }
+
+ @Override
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ /* package-private */ AttributionSource(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int uid = in.readInt();
+ String packageName = (flg & 0x2) == 0 ? null : in.readString();
+ String attributionTag = (flg & 0x4) == 0 ? null : in.readString();
+ IBinder token = (flg & 0x8) == 0 ? null : in.readStrongBinder();
+ Set<String> renouncedPermissions = sParcellingForRenouncedPermissions.unparcel(in);
+ AttributionSource next = (flg & 0x20) == 0 ? null : (AttributionSource) in.readTypedObject(AttributionSource.CREATOR);
+
+ this.mUid = uid;
+ this.mPackageName = packageName;
+ this.mAttributionTag = attributionTag;
+ this.mToken = token;
+ this.mRenouncedPermissions = renouncedPermissions;
+ com.android.internal.util.AnnotationValidations.validate(
+ SystemApi.class, null, mRenouncedPermissions);
+ com.android.internal.util.AnnotationValidations.validate(
+ RequiresPermission.class, null, mRenouncedPermissions,
+ "value", android.Manifest.permission.RENOUNCE_PERMISSIONS);
+ this.mNext = next;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ public static final @NonNull Parcelable.Creator<AttributionSource> CREATOR
+ = new Parcelable.Creator<AttributionSource>() {
+ @Override
+ public AttributionSource[] newArray(int size) {
+ return new AttributionSource[size];
+ }
+
+ @Override
+ public AttributionSource createFromParcel(@NonNull Parcel in) {
+ return new AttributionSource(in);
+ }
+ };
+
+ /**
+ * A builder for {@link AttributionSource}
+ */
+ @SuppressWarnings("WeakerAccess")
+ public static final class Builder extends BaseBuilder {
+
+ private int mUid;
+ private @Nullable String mPackageName;
+ private @Nullable String mAttributionTag;
+ private @Nullable IBinder mToken;
+ private @SystemApi @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) @Nullable Set<String> mRenouncedPermissions;
+ private @Nullable AttributionSource mNext;
+
+ private long mBuilderFieldsSet = 0L;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @param uid
+ * The UID that is accessing the permission protected data.
+ */
+ public Builder(
+ int uid) {
+ mUid = uid;
+ }
+
+ /**
+ * The package that is accessing the permission protected data.
+ */
+ public @NonNull Builder setPackageName(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mPackageName = value;
+ return this;
+ }
+
+ /**
+ * The attribution tag of the app accessing the permission protected data.
+ */
+ public @NonNull Builder setAttributionTag(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mAttributionTag = value;
+ return this;
+ }
+
+ /**
+ * Permissions that should be considered revoked regardless if granted.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
+ public @NonNull Builder setRenouncedPermissions(@NonNull Set<String> value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mRenouncedPermissions = value;
+ return this;
+ }
+
+ /**
+ * The next app to receive the permission protected data.
+ */
+ public @NonNull Builder setNext(@NonNull AttributionSource value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mNext = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull AttributionSource build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mPackageName = null;
+ }
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mAttributionTag = null;
+ }
+ if ((mBuilderFieldsSet & 0x8) == 0) {
+ mToken = null;
+ }
+ if ((mBuilderFieldsSet & 0x10) == 0) {
+ mRenouncedPermissions = null;
+ }
+ if ((mBuilderFieldsSet & 0x20) == 0) {
+ mNext = null;
+ }
+ AttributionSource o = new AttributionSource(
+ mUid,
+ mPackageName,
+ mAttributionTag,
+ mToken,
+ mRenouncedPermissions,
+ mNext);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x40) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 73b4f62..8284203 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -18,11 +18,6 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.app.AppOpsManager.MODE_ALLOWED;
-import static android.app.AppOpsManager.MODE_DEFAULT;
-import static android.app.AppOpsManager.MODE_ERRORED;
-import static android.app.AppOpsManager.MODE_IGNORED;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Trace.TRACE_TAG_DATABASE;
import android.annotation.NonNull;
@@ -45,7 +40,6 @@
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
-import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
@@ -57,7 +51,6 @@
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;
-import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
@@ -141,7 +134,7 @@
private boolean mNoPerms;
private boolean mSingleUser;
- private ThreadLocal<Pair<String, String>> mCallingPackage;
+ private ThreadLocal<AttributionSource> mCallingAttributionSource;
private Transport mTransport = new Transport();
@@ -231,13 +224,13 @@
}
@Override
- public Cursor query(String callingPkg, @Nullable String attributionTag, Uri uri,
+ public Cursor query(@NonNull AttributionSource attributionSource, Uri uri,
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable ICancellationSignal cancellationSignal) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, attributionTag, uri, null)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(attributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
// The caller has no access to the data, so return an empty cursor with
// the columns in the requested order. The caller may ask for an invalid
// column and we would not catch that but this is not a problem in practice.
@@ -253,8 +246,8 @@
// we have to execute the query as if allowed to get a cursor with the
// columns. We then use the column names to return an empty cursor.
Cursor cursor;
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
cursor = mInterface.query(
uri, projection, queryArgs,
@@ -262,7 +255,7 @@
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
}
if (cursor == null) {
return null;
@@ -272,8 +265,8 @@
return new MatrixCursor(cursor.getColumnNames(), 0);
}
Trace.traceBegin(TRACE_TAG_DATABASE, "query");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return mInterface.query(
uri, projection, queryArgs,
@@ -281,7 +274,7 @@
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -314,60 +307,59 @@
}
@Override
- public Uri insert(String callingPkg, @Nullable String attributionTag, Uri uri,
+ public Uri insert(@NonNull AttributionSource attributionSource, Uri uri,
ContentValues initialValues, Bundle extras) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, attributionTag, uri, null)
- != AppOpsManager.MODE_ALLOWED) {
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ if (enforceWritePermission(attributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return rejectInsert(uri, initialValues);
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
}
}
Trace.traceBegin(TRACE_TAG_DATABASE, "insert");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return maybeAddUserId(mInterface.insert(uri, initialValues, extras), userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@Override
- public int bulkInsert(String callingPkg, @Nullable String attributionTag, Uri uri,
+ public int bulkInsert(@NonNull AttributionSource attributionSource, Uri uri,
ContentValues[] initialValues) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, attributionTag, uri, null)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(attributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "bulkInsert");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return mInterface.bulkInsert(uri, initialValues);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@Override
- public ContentProviderResult[] applyBatch(String callingPkg,
- @Nullable String attributionTag, String authority,
- ArrayList<ContentProviderOperation> operations)
+ public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
+ String authority, ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
validateIncomingAuthority(authority);
int numOperations = operations.size();
@@ -383,22 +375,24 @@
operation = new ContentProviderOperation(operation, uri);
operations.set(i, operation);
}
+ final AttributionSource accessAttributionSource =
+ attributionSource;
if (operation.isReadOperation()) {
- if (enforceReadPermission(callingPkg, attributionTag, uri, null)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(accessAttributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
throw new OperationApplicationException("App op not allowed", 0);
}
}
if (operation.isWriteOperation()) {
- if (enforceWritePermission(callingPkg, attributionTag, uri, null)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(accessAttributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
throw new OperationApplicationException("App op not allowed", 0);
}
}
}
Trace.traceBegin(TRACE_TAG_DATABASE, "applyBatch");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
ContentProviderResult[] results = mInterface.applyBatch(authority,
operations);
@@ -414,111 +408,111 @@
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@Override
- public int delete(String callingPkg, @Nullable String attributionTag, Uri uri,
+ public int delete(@NonNull AttributionSource attributionSource, Uri uri,
Bundle extras) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, attributionTag, uri, null)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(attributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "delete");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return mInterface.delete(uri, extras);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@Override
- public int update(String callingPkg, @Nullable String attributionTag, Uri uri,
+ public int update(@NonNull AttributionSource attributionSource, Uri uri,
ContentValues values, Bundle extras) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, attributionTag, uri, null)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(attributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "update");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return mInterface.update(uri, values, extras);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@Override
- public ParcelFileDescriptor openFile(String callingPkg, @Nullable String attributionTag,
- Uri uri, String mode, ICancellationSignal cancellationSignal, IBinder callerToken)
+ public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource,
+ Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, attributionTag, uri, mode, callerToken);
+ enforceFilePermission(attributionSource, uri, mode);
Trace.traceBegin(TRACE_TAG_DATABASE, "openFile");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return mInterface.openFile(
uri, mode, CancellationSignal.fromTransport(cancellationSignal));
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@Override
- public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String attributionTag,
+ public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, attributionTag, uri, mode, null);
+ enforceFilePermission(attributionSource, uri, mode);
Trace.traceBegin(TRACE_TAG_DATABASE, "openAssetFile");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return mInterface.openAssetFile(
uri, mode, CancellationSignal.fromTransport(cancellationSignal));
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@Override
- public Bundle call(String callingPkg, @Nullable String attributionTag, String authority,
+ public Bundle call(@NonNull AttributionSource attributionSource, String authority,
String method, @Nullable String arg, @Nullable Bundle extras) {
validateIncomingAuthority(authority);
Bundle.setDefusable(extras, true);
Trace.traceBegin(TRACE_TAG_DATABASE, "call");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return mInterface.call(authority, method, arg, extras);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -539,23 +533,23 @@
}
@Override
- public AssetFileDescriptor openTypedAssetFile(String callingPkg,
- @Nullable String attributionTag, Uri uri, String mimeType, Bundle opts,
- ICancellationSignal cancellationSignal) throws FileNotFoundException {
+ public AssetFileDescriptor openTypedAssetFile(
+ @NonNull AttributionSource attributionSource, Uri uri, String mimeType,
+ Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
Bundle.setDefusable(opts, true);
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, attributionTag, uri, "r", null);
+ enforceFilePermission(attributionSource, uri, "r");
Trace.traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return mInterface.openTypedAssetFile(
uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal));
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -566,34 +560,34 @@
}
@Override
- public Uri canonicalize(String callingPkg, @Nullable String attributionTag, Uri uri) {
+ public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri uri) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, attributionTag, uri, null)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(attributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
return null;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "canonicalize");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return maybeAddUserId(mInterface.canonicalize(uri), userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@Override
- public void canonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
+ public void canonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
RemoteCallback callback) {
final Bundle result = new Bundle();
try {
result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
- canonicalize(callingPkg, attributionTag, uri));
+ canonicalize(attributionSource, uri));
} catch (Exception e) {
result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR,
new ParcelableException(e));
@@ -602,34 +596,34 @@
}
@Override
- public Uri uncanonicalize(String callingPkg, String attributionTag, Uri uri) {
+ public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri uri) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, attributionTag, uri, null)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(attributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
return null;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "uncanonicalize");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return maybeAddUserId(mInterface.uncanonicalize(uri), userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@Override
- public void uncanonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
+ public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
RemoteCallback callback) {
final Bundle result = new Bundle();
try {
result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
- uncanonicalize(callingPkg, attributionTag, uri));
+ uncanonicalize(attributionSource, uri));
} catch (Exception e) {
result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR,
new ParcelableException(e));
@@ -638,92 +632,95 @@
}
@Override
- public boolean refresh(String callingPkg, String attributionTag, Uri uri, Bundle extras,
- ICancellationSignal cancellationSignal) throws RemoteException {
+ public boolean refresh(@NonNull AttributionSource attributionSource, Uri uri,
+ Bundle extras, ICancellationSignal cancellationSignal) throws RemoteException {
uri = validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, attributionTag, uri, null)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(attributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
return false;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "refresh");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return mInterface.refresh(uri, extras,
CancellationSignal.fromTransport(cancellationSignal));
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@Override
- public int checkUriPermission(String callingPkg, @Nullable String attributionTag, Uri uri,
+ public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri,
int uid, int modeFlags) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
Trace.traceBegin(TRACE_TAG_DATABASE, "checkUriPermission");
- final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, attributionTag));
+ final AttributionSource original = setCallingAttributionSource(
+ attributionSource);
try {
return mInterface.checkUriPermission(uri, uid, modeFlags);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- setCallingPackage(original);
+ setCallingAttributionSource(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
- private void enforceFilePermission(String callingPkg, @Nullable String attributionTag,
- Uri uri, String mode, IBinder callerToken)
+ @PermissionChecker.PermissionResult
+ private void enforceFilePermission(@NonNull AttributionSource attributionSource,
+ Uri uri, String mode)
throws FileNotFoundException, SecurityException {
if (mode != null && mode.indexOf('w') != -1) {
- if (enforceWritePermission(callingPkg, attributionTag, uri, callerToken)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(attributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
throw new FileNotFoundException("App op not allowed");
}
} else {
- if (enforceReadPermission(callingPkg, attributionTag, uri, callerToken)
- != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(attributionSource, uri)
+ != PermissionChecker.PERMISSION_GRANTED) {
throw new FileNotFoundException("App op not allowed");
}
}
}
- private int enforceReadPermission(String callingPkg, @Nullable String attributionTag,
- Uri uri, IBinder callerToken)
+ @PermissionChecker.PermissionResult
+ private int enforceReadPermission(@NonNull AttributionSource attributionSource, Uri uri)
throws SecurityException {
- final int mode = enforceReadPermissionInner(uri, callingPkg, attributionTag,
- callerToken);
- if (mode != MODE_ALLOWED) {
- return mode;
+ final int result = enforceReadPermissionInner(uri, attributionSource);
+ if (result != PermissionChecker.PERMISSION_GRANTED) {
+ return result;
}
-
- return noteProxyOp(callingPkg, attributionTag, mReadOp);
+ // Only check the read op if it differs from the one for the permission
+ // we already checked above to avoid double attribution for every access.
+ if (mTransport.mReadOp != AppOpsManager.OP_NONE
+ && mTransport.mReadOp != AppOpsManager.permissionToOpCode(mReadPermission)) {
+ return PermissionChecker.checkOpForDataDelivery(getContext(),
+ AppOpsManager.opToPublicName(mTransport.mReadOp),
+ attributionSource, /*message*/ null);
+ }
+ return PermissionChecker.PERMISSION_GRANTED;
}
- private int enforceWritePermission(String callingPkg, String attributionTag, Uri uri,
- IBinder callerToken)
+ @PermissionChecker.PermissionResult
+ private int enforceWritePermission(@NonNull AttributionSource attributionSource, Uri uri)
throws SecurityException {
- final int mode = enforceWritePermissionInner(uri, callingPkg, attributionTag,
- callerToken);
- if (mode != MODE_ALLOWED) {
- return mode;
+ final int result = enforceWritePermissionInner(uri, attributionSource);
+ if (result != PermissionChecker.PERMISSION_GRANTED) {
+ return result;
}
-
- return noteProxyOp(callingPkg, attributionTag, mWriteOp);
- }
-
- private int noteProxyOp(String callingPkg, String attributionTag, int op) {
- if (op != AppOpsManager.OP_NONE) {
- int mode = mAppOpsManager.noteProxyOp(op, callingPkg, Binder.getCallingUid(),
- attributionTag, null);
- return mode == MODE_DEFAULT ? MODE_IGNORED : mode;
+ // Only check the write op if it differs from the one for the permission
+ // we already checked above to avoid double attribution for every access.
+ if (mTransport.mWriteOp != AppOpsManager.OP_NONE
+ && mTransport.mWriteOp != AppOpsManager.permissionToOpCode(mWritePermission)) {
+ return PermissionChecker.checkOpForDataDelivery(getContext(),
+ AppOpsManager.opToPublicName(mTransport.mWriteOp),
+ attributionSource, /*message*/ null);
}
-
- return AppOpsManager.MODE_ALLOWED;
+ return PermissionChecker.PERMISSION_GRANTED;
}
}
@@ -731,49 +728,53 @@
if (UserHandle.getUserId(uid) == context.getUserId() || mSingleUser) {
return true;
}
- return context.checkPermission(INTERACT_ACROSS_USERS, pid, uid) == PERMISSION_GRANTED
+ return context.checkPermission(INTERACT_ACROSS_USERS, pid, uid)
+ == PackageManager.PERMISSION_GRANTED
|| context.checkPermission(INTERACT_ACROSS_USERS_FULL, pid, uid)
- == PERMISSION_GRANTED;
+ == PackageManager.PERMISSION_GRANTED;
}
/**
* Verify that calling app holds both the given permission and any app-op
* associated with that permission.
*/
- private int checkPermissionAndAppOp(String permission, String callingPkg,
- @Nullable String attributionTag, IBinder callerToken) {
- if (getContext().checkPermission(permission, Binder.getCallingPid(), Binder.getCallingUid(),
- callerToken) != PERMISSION_GRANTED) {
- return MODE_ERRORED;
+ @PermissionChecker.PermissionResult
+ private int checkPermission(String permission,
+ @NonNull AttributionSource attributionSource) {
+ if (Binder.getCallingPid() == Process.myPid()) {
+ return PermissionChecker.PERMISSION_GRANTED;
}
-
- return mTransport.noteProxyOp(callingPkg, attributionTag,
- AppOpsManager.permissionToOpCode(permission));
+ if (!attributionSource.checkCallingUid()) {
+ return PermissionChecker.PERMISSION_HARD_DENIED;
+ }
+ return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(getContext(),
+ permission, -1, new AttributionSource(getContext().getAttributionSource(),
+ attributionSource), /*message*/ null);
}
/** {@hide} */
- protected int enforceReadPermissionInner(Uri uri, String callingPkg,
- @Nullable String attributionTag, IBinder callerToken) throws SecurityException {
+ @PermissionChecker.PermissionResult
+ protected int enforceReadPermissionInner(Uri uri,
+ @NonNull AttributionSource attributionSource) throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
String missingPerm = null;
- int strongestMode = MODE_ALLOWED;
+ int strongestResult = PermissionChecker.PERMISSION_GRANTED;
if (UserHandle.isSameApp(uid, mMyUid)) {
- return MODE_ALLOWED;
+ return PermissionChecker.PERMISSION_GRANTED;
}
if (mExported && checkUser(pid, uid, context)) {
final String componentPerm = getReadPermission();
if (componentPerm != null) {
- final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, attributionTag,
- callerToken);
- if (mode == MODE_ALLOWED) {
- return MODE_ALLOWED;
+ final int result = checkPermission(componentPerm, attributionSource);
+ if (result == PermissionChecker.PERMISSION_GRANTED) {
+ return PermissionChecker.PERMISSION_GRANTED;
} else {
missingPerm = componentPerm;
- strongestMode = Math.max(strongestMode, mode);
+ strongestResult = Math.max(strongestResult, result);
}
}
@@ -787,16 +788,15 @@
for (PathPermission pp : pps) {
final String pathPerm = pp.getReadPermission();
if (pathPerm != null && pp.match(path)) {
- final int mode = checkPermissionAndAppOp(pathPerm, callingPkg,
- attributionTag, callerToken);
- if (mode == MODE_ALLOWED) {
- return MODE_ALLOWED;
+ final int result = checkPermission(pathPerm, attributionSource);
+ if (result == PermissionChecker.PERMISSION_GRANTED) {
+ return PermissionChecker.PERMISSION_GRANTED;
} else {
// any denied <path-permission> means we lose
// default <provider> access.
allowDefaultRead = false;
missingPerm = pathPerm;
- strongestMode = Math.max(strongestMode, mode);
+ strongestResult = Math.max(strongestResult, result);
}
}
}
@@ -804,22 +804,22 @@
// if we passed <path-permission> checks above, and no default
// <provider> permission, then allow access.
- if (allowDefaultRead) return MODE_ALLOWED;
+ if (allowDefaultRead) return PermissionChecker.PERMISSION_GRANTED;
}
// last chance, check against any uri grants
final int callingUserId = UserHandle.getUserId(uid);
final Uri userUri = (mSingleUser && !UserHandle.isSameUser(mMyUid, uid))
? maybeAddUserId(uri, callingUserId) : uri;
- if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION,
- callerToken) == PERMISSION_GRANTED) {
- return MODE_ALLOWED;
+ if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ == PackageManager.PERMISSION_GRANTED) {
+ return PermissionChecker.PERMISSION_GRANTED;
}
// If the worst denial we found above was ignored, then pass that
// ignored through; otherwise we assume it should be a real error below.
- if (strongestMode == MODE_IGNORED) {
- return MODE_IGNORED;
+ if (strongestResult == PermissionChecker.PERMISSION_SOFT_DENIED) {
+ return PermissionChecker.PERMISSION_SOFT_DENIED;
}
final String suffix;
@@ -836,28 +836,28 @@
}
/** {@hide} */
- protected int enforceWritePermissionInner(Uri uri, String callingPkg,
- @Nullable String attributionTag, IBinder callerToken) throws SecurityException {
+ @PermissionChecker.PermissionResult
+ protected int enforceWritePermissionInner(Uri uri,
+ @NonNull AttributionSource attributionSource) throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
String missingPerm = null;
- int strongestMode = MODE_ALLOWED;
+ int strongestResult = PermissionChecker.PERMISSION_GRANTED;
if (UserHandle.isSameApp(uid, mMyUid)) {
- return MODE_ALLOWED;
+ return PermissionChecker.PERMISSION_GRANTED;
}
if (mExported && checkUser(pid, uid, context)) {
final String componentPerm = getWritePermission();
if (componentPerm != null) {
- final int mode = checkPermissionAndAppOp(componentPerm, callingPkg,
- attributionTag, callerToken);
- if (mode == MODE_ALLOWED) {
- return MODE_ALLOWED;
+ final int mode = checkPermission(componentPerm, attributionSource);
+ if (mode == PermissionChecker.PERMISSION_GRANTED) {
+ return PermissionChecker.PERMISSION_GRANTED;
} else {
missingPerm = componentPerm;
- strongestMode = Math.max(strongestMode, mode);
+ strongestResult = Math.max(strongestResult, mode);
}
}
@@ -871,16 +871,15 @@
for (PathPermission pp : pps) {
final String pathPerm = pp.getWritePermission();
if (pathPerm != null && pp.match(path)) {
- final int mode = checkPermissionAndAppOp(pathPerm, callingPkg,
- attributionTag, callerToken);
- if (mode == MODE_ALLOWED) {
- return MODE_ALLOWED;
+ final int mode = checkPermission(pathPerm, attributionSource);
+ if (mode == PermissionChecker.PERMISSION_GRANTED) {
+ return PermissionChecker.PERMISSION_GRANTED;
} else {
// any denied <path-permission> means we lose
// default <provider> access.
allowDefaultWrite = false;
missingPerm = pathPerm;
- strongestMode = Math.max(strongestMode, mode);
+ strongestResult = Math.max(strongestResult, mode);
}
}
}
@@ -888,19 +887,19 @@
// if we passed <path-permission> checks above, and no default
// <provider> permission, then allow access.
- if (allowDefaultWrite) return MODE_ALLOWED;
+ if (allowDefaultWrite) return PermissionChecker.PERMISSION_GRANTED;
}
// last chance, check against any uri grants
- if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
- callerToken) == PERMISSION_GRANTED) {
- return MODE_ALLOWED;
+ if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+ == PackageManager.PERMISSION_GRANTED) {
+ return PermissionChecker.PERMISSION_GRANTED;
}
// If the worst denial we found above was ignored, then pass that
// ignored through; otherwise we assume it should be a real error below.
- if (strongestMode == MODE_IGNORED) {
- return MODE_IGNORED;
+ if (strongestResult == PermissionChecker.PERMISSION_SOFT_DENIED) {
+ return PermissionChecker.PERMISSION_SOFT_DENIED;
}
final String failReason = mExported
@@ -941,9 +940,10 @@
* Set the calling package/feature, returning the current value (or {@code null})
* which can be used later to restore the previous state.
*/
- private Pair<String, String> setCallingPackage(Pair<String, String> callingPackage) {
- final Pair<String, String> original = mCallingPackage.get();
- mCallingPackage.set(callingPackage);
+ private @Nullable AttributionSource setCallingAttributionSource(
+ @Nullable AttributionSource attributionSource) {
+ final AttributionSource original = mCallingAttributionSource.get();
+ mCallingAttributionSource.set(attributionSource);
onCallingPackageChanged();
return original;
}
@@ -963,13 +963,30 @@
* calling UID.
*/
public final @Nullable String getCallingPackage() {
- final Pair<String, String> pkg = mCallingPackage.get();
- if (pkg != null) {
- mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg.first);
- return pkg.first;
- }
+ final AttributionSource callingAttributionSource = getCallingAttributionSource();
+ return (callingAttributionSource != null)
+ ? callingAttributionSource.getPackageName() : null;
+ }
- return null;
+ /**
+ * Gets the attribution source of the calling app. If you want to attribute
+ * the data access to the calling app you can create an attribution context
+ * via {@link android.content.Context#createContext(ContextParams)} and passing
+ * this identity to {@link ContextParams.Builder#setNextAttributionSource(
+ * AttributionSource)}.
+ *
+ * @return The identity of the caller for permission purposes.
+ *
+ * @see ContextParams.Builder#setNextAttributionSource(AttributionSource)
+ * @see AttributionSource
+ */
+ public final @Nullable AttributionSource getCallingAttributionSource() {
+ final AttributionSource attributionSource = mCallingAttributionSource.get();
+ if (attributionSource != null) {
+ mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(),
+ attributionSource.getPackageName());
+ }
+ return attributionSource;
}
/**
@@ -983,11 +1000,10 @@
* @see #getCallingPackage
*/
public final @Nullable String getCallingAttributionTag() {
- final Pair<String, String> pkg = mCallingPackage.get();
- if (pkg != null) {
- return pkg.second;
+ final AttributionSource attributionSource = mCallingAttributionSource.get();
+ if (attributionSource != null) {
+ return attributionSource.getAttributionTag();
}
-
return null;
}
@@ -1012,11 +1028,10 @@
* @see Context#grantUriPermission(String, Uri, int)
*/
public final @Nullable String getCallingPackageUnchecked() {
- final Pair<String, String> pkg = mCallingPackage.get();
- if (pkg != null) {
- return pkg.first;
+ final AttributionSource attributionSource = mCallingAttributionSource.get();
+ if (attributionSource != null) {
+ return attributionSource.getPackageName();
}
-
return null;
}
@@ -1038,12 +1053,12 @@
/** {@hide} */
public final long binderToken;
/** {@hide} */
- public final Pair<String, String> callingPackage;
+ public final @Nullable AttributionSource callingAttributionSource;
/** {@hide} */
- public CallingIdentity(long binderToken, Pair<String, String> callingPackage) {
+ public CallingIdentity(long binderToken, @Nullable AttributionSource attributionSource) {
this.binderToken = binderToken;
- this.callingPackage = callingPackage;
+ this.callingAttributionSource = attributionSource;
}
}
@@ -1059,7 +1074,8 @@
*/
@SuppressWarnings("AndroidFrameworkBinderIdentity")
public final @NonNull CallingIdentity clearCallingIdentity() {
- return new CallingIdentity(Binder.clearCallingIdentity(), setCallingPackage(null));
+ return new CallingIdentity(Binder.clearCallingIdentity(),
+ setCallingAttributionSource(null));
}
/**
@@ -1071,7 +1087,7 @@
*/
public final void restoreCallingIdentity(@NonNull CallingIdentity identity) {
Binder.restoreCallingIdentity(identity.binderToken);
- mCallingPackage.set(identity.callingPackage);
+ mCallingAttributionSource.set(identity.callingAttributionSource);
}
/**
@@ -2374,7 +2390,7 @@
private void attachInfo(Context context, ProviderInfo info, boolean testing) {
mNoPerms = testing;
- mCallingPackage = new ThreadLocal<>();
+ mCallingAttributionSource = new ThreadLocal<>();
/*
* Only allow it to be set once, so after the content service gives
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 5af7861..518e753 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -79,7 +79,8 @@
private final IContentProvider mContentProvider;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final String mPackageName;
- private final @Nullable String mAttributionTag;
+ private final @NonNull AttributionSource mAttributionSource;
+
private final String mAuthority;
private final boolean mStable;
@@ -103,7 +104,7 @@
mContentResolver = contentResolver;
mContentProvider = contentProvider;
mPackageName = contentResolver.mPackageName;
- mAttributionTag = contentResolver.mAttributionTag;
+ mAttributionSource = contentResolver.getAttributionSource();
mAuthority = authority;
mStable = stable;
@@ -193,7 +194,7 @@
cancellationSignal.setRemote(remoteCancellationSignal);
}
final Cursor cursor = mContentProvider.query(
- mPackageName, mAttributionTag, uri, projection, queryArgs,
+ mAttributionSource, uri, projection, queryArgs,
remoteCancellationSignal);
if (cursor == null) {
return null;
@@ -254,7 +255,7 @@
beforeRemote();
try {
- return mContentProvider.canonicalize(mPackageName, mAttributionTag, url);
+ return mContentProvider.canonicalize(mAttributionSource, url);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -272,7 +273,7 @@
beforeRemote();
try {
- return mContentProvider.uncanonicalize(mPackageName, mAttributionTag, url);
+ return mContentProvider.uncanonicalize(mAttributionSource, url);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -297,7 +298,7 @@
remoteCancellationSignal = mContentProvider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return mContentProvider.refresh(mPackageName, mAttributionTag, url, extras,
+ return mContentProvider.refresh(mAttributionSource, url, extras,
remoteCancellationSignal);
} catch (DeadObjectException e) {
if (!mStable) {
@@ -317,7 +318,7 @@
beforeRemote();
try {
- return mContentProvider.checkUriPermission(mPackageName, mAttributionTag, uri, uid,
+ return mContentProvider.checkUriPermission(mAttributionSource, uri, uid,
modeFlags);
} catch (DeadObjectException e) {
if (!mStable) {
@@ -343,7 +344,7 @@
beforeRemote();
try {
- return mContentProvider.insert(mPackageName, mAttributionTag, url, initialValues,
+ return mContentProvider.insert(mAttributionSource, url, initialValues,
extras);
} catch (DeadObjectException e) {
if (!mStable) {
@@ -364,7 +365,7 @@
beforeRemote();
try {
- return mContentProvider.bulkInsert(mPackageName, mAttributionTag, url, initialValues);
+ return mContentProvider.bulkInsert(mAttributionSource, url, initialValues);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -388,7 +389,7 @@
beforeRemote();
try {
- return mContentProvider.delete(mPackageName, mAttributionTag, url, extras);
+ return mContentProvider.delete(mAttributionSource, url, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -413,7 +414,7 @@
beforeRemote();
try {
- return mContentProvider.update(mPackageName, mAttributionTag, url, values, extras);
+ return mContentProvider.update(mAttributionSource, url, values, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -457,8 +458,7 @@
remoteSignal = mContentProvider.createCancellationSignal();
signal.setRemote(remoteSignal);
}
- return mContentProvider.openFile(mPackageName, mAttributionTag, url, mode,
- remoteSignal, null);
+ return mContentProvider.openFile(mAttributionSource, url, mode, remoteSignal);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -502,7 +502,7 @@
remoteSignal = mContentProvider.createCancellationSignal();
signal.setRemote(remoteSignal);
}
- return mContentProvider.openAssetFile(mPackageName, mAttributionTag, url, mode,
+ return mContentProvider.openAssetFile(mAttributionSource, url, mode,
remoteSignal);
} catch (DeadObjectException e) {
if (!mStable) {
@@ -544,7 +544,7 @@
signal.setRemote(remoteSignal);
}
return mContentProvider.openTypedAssetFile(
- mPackageName, mAttributionTag, uri, mimeTypeFilter, opts, remoteSignal);
+ mAttributionSource, uri, mimeTypeFilter, opts, remoteSignal);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -571,7 +571,7 @@
beforeRemote();
try {
- return mContentProvider.applyBatch(mPackageName, mAttributionTag, authority,
+ return mContentProvider.applyBatch(mAttributionSource, authority,
operations);
} catch (DeadObjectException e) {
if (!mStable) {
@@ -598,7 +598,7 @@
beforeRemote();
try {
- return mContentProvider.call(mPackageName, mAttributionTag, authority, method, arg,
+ return mContentProvider.call(mAttributionSource, authority, method, arg,
extras);
} catch (DeadObjectException e) {
if (!mStable) {
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 7d121d5..47c96699 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -16,6 +16,7 @@
package android.content;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
@@ -83,8 +84,8 @@
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String callingFeatureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
// String[] projection
@@ -103,7 +104,7 @@
ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
- Cursor cursor = query(callingPkg, callingFeatureId, url, projection, queryArgs,
+ Cursor cursor = query(attributionSource, url, projection, queryArgs,
cancellationSignal);
if (cursor != null) {
CursorToBulkCursorAdaptor adaptor = null;
@@ -158,13 +159,13 @@
case INSERT_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
ContentValues values = ContentValues.CREATOR.createFromParcel(data);
Bundle extras = data.readBundle();
- Uri out = insert(callingPkg, featureId, url, values, extras);
+ Uri out = insert(attributionSource, url, values, extras);
reply.writeNoException();
Uri.writeToParcel(reply, out);
return true;
@@ -173,12 +174,12 @@
case BULK_INSERT_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
ContentValues[] values = data.createTypedArray(ContentValues.CREATOR);
- int count = bulkInsert(callingPkg, featureId, url, values);
+ int count = bulkInsert(attributionSource, url, values);
reply.writeNoException();
reply.writeInt(count);
return true;
@@ -187,8 +188,8 @@
case APPLY_BATCH_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
String authority = data.readString();
final int numOperations = data.readInt();
final ArrayList<ContentProviderOperation> operations =
@@ -196,7 +197,7 @@
for (int i = 0; i < numOperations; i++) {
operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
}
- final ContentProviderResult[] results = applyBatch(callingPkg, featureId,
+ final ContentProviderResult[] results = applyBatch(attributionSource,
authority, operations);
reply.writeNoException();
reply.writeTypedArray(results, 0);
@@ -206,12 +207,12 @@
case DELETE_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
Bundle extras = data.readBundle();
- int count = delete(callingPkg, featureId, url, extras);
+ int count = delete(attributionSource, url, extras);
reply.writeNoException();
reply.writeInt(count);
@@ -221,13 +222,13 @@
case UPDATE_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
ContentValues values = ContentValues.CREATOR.createFromParcel(data);
Bundle extras = data.readBundle();
- int count = update(callingPkg, featureId, url, values, extras);
+ int count = update(attributionSource, url, values, extras);
reply.writeNoException();
reply.writeInt(count);
@@ -237,16 +238,15 @@
case OPEN_FILE_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
String mode = data.readString();
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
- IBinder callerToken = data.readStrongBinder();
ParcelFileDescriptor fd;
- fd = openFile(callingPkg, featureId, url, mode, signal, callerToken);
+ fd = openFile(attributionSource, url, mode, signal);
reply.writeNoException();
if (fd != null) {
reply.writeInt(1);
@@ -261,15 +261,15 @@
case OPEN_ASSET_FILE_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
String mode = data.readString();
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
AssetFileDescriptor fd;
- fd = openAssetFile(callingPkg, featureId, url, mode, signal);
+ fd = openAssetFile(attributionSource, url, mode, signal);
reply.writeNoException();
if (fd != null) {
reply.writeInt(1);
@@ -285,14 +285,14 @@
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
String authority = data.readString();
String method = data.readString();
String stringArg = data.readString();
Bundle extras = data.readBundle();
- Bundle responseBundle = call(callingPkg, featureId, authority, method,
+ Bundle responseBundle = call(attributionSource, authority, method,
stringArg, extras);
reply.writeNoException();
@@ -315,8 +315,8 @@
case OPEN_TYPED_ASSET_FILE_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
String mimeType = data.readString();
Bundle opts = data.readBundle();
@@ -324,7 +324,7 @@
data.readStrongBinder());
AssetFileDescriptor fd;
- fd = openTypedAssetFile(callingPkg, featureId, url, mimeType, opts, signal);
+ fd = openTypedAssetFile(attributionSource, url, mimeType, opts, signal);
reply.writeNoException();
if (fd != null) {
reply.writeInt(1);
@@ -349,11 +349,11 @@
case CANONICALIZE_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
- Uri out = canonicalize(callingPkg, featureId, url);
+ Uri out = canonicalize(attributionSource, url);
reply.writeNoException();
Uri.writeToParcel(reply, out);
return true;
@@ -361,22 +361,22 @@
case CANONICALIZE_ASYNC_TRANSACTION: {
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri uri = Uri.CREATOR.createFromParcel(data);
RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
- canonicalizeAsync(callingPkg, featureId, uri, callback);
+ canonicalizeAsync(attributionSource, uri, callback);
return true;
}
case UNCANONICALIZE_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
- Uri out = uncanonicalize(callingPkg, featureId, url);
+ Uri out = uncanonicalize(attributionSource, url);
reply.writeNoException();
Uri.writeToParcel(reply, out);
return true;
@@ -384,24 +384,24 @@
case UNCANONICALIZE_ASYNC_TRANSACTION: {
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri uri = Uri.CREATOR.createFromParcel(data);
RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
- uncanonicalizeAsync(callingPkg, featureId, uri, callback);
+ uncanonicalizeAsync(attributionSource, uri, callback);
return true;
}
case REFRESH_TRANSACTION: {
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
Bundle extras = data.readBundle();
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
- boolean out = refresh(callingPkg, featureId, url, extras, signal);
+ boolean out = refresh(attributionSource, url, extras, signal);
reply.writeNoException();
reply.writeInt(out ? 0 : -1);
return true;
@@ -409,13 +409,13 @@
case CHECK_URI_PERMISSION_TRANSACTION: {
data.enforceInterface(IContentProvider.descriptor);
- String callingPkg = data.readString();
- String featureId = data.readString();
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri uri = Uri.CREATOR.createFromParcel(data);
int uid = data.readInt();
int modeFlags = data.readInt();
- int out = checkUriPermission(callingPkg, featureId, uri, uid, modeFlags);
+ int out = checkUriPermission(attributionSource, uri, uid, modeFlags);
reply.writeNoException();
reply.writeInt(out);
return true;
@@ -451,7 +451,7 @@
}
@Override
- public Cursor query(String callingPkg, @Nullable String featureId, Uri url,
+ public Cursor query(@NonNull AttributionSource attributionSource, Uri url,
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable ICancellationSignal cancellationSignal)
throws RemoteException {
@@ -461,8 +461,7 @@
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
int length = 0;
if (projection != null) {
@@ -540,7 +539,7 @@
}
@Override
- public Uri insert(String callingPkg, @Nullable String featureId, Uri url,
+ public Uri insert(@NonNull AttributionSource attributionSource, Uri url,
ContentValues values, Bundle extras) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -548,8 +547,7 @@
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
values.writeToParcel(data, 0);
data.writeBundle(extras);
@@ -566,15 +564,14 @@
}
@Override
- public int bulkInsert(String callingPkg, @Nullable String featureId, Uri url,
+ public int bulkInsert(@NonNull AttributionSource attributionSource, Uri url,
ContentValues[] values) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
data.writeTypedArray(values, 0);
@@ -590,15 +587,14 @@
}
@Override
- public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String featureId,
+ public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
String authority, ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
data.writeString(authority);
data.writeInt(operations.size());
for (ContentProviderOperation operation : operations) {
@@ -617,15 +613,14 @@
}
@Override
- public int delete(String callingPkg, @Nullable String featureId, Uri url, Bundle extras)
+ public int delete(@NonNull AttributionSource attributionSource, Uri url, Bundle extras)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
data.writeBundle(extras);
@@ -641,15 +636,14 @@
}
@Override
- public int update(String callingPkg, @Nullable String featureId, Uri url,
+ public int update(@NonNull AttributionSource attributionSource, Uri url,
ContentValues values, Bundle extras) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
values.writeToParcel(data, 0);
data.writeBundle(extras);
@@ -666,20 +660,18 @@
}
@Override
- public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, Uri url,
- String mode, ICancellationSignal signal, IBinder token)
+ public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource, Uri url,
+ String mode, ICancellationSignal signal)
throws RemoteException, FileNotFoundException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
data.writeString(mode);
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
- data.writeStrongBinder(token);
mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0);
@@ -695,7 +687,7 @@
}
@Override
- public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String featureId,
+ public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
Uri url, String mode, ICancellationSignal signal)
throws RemoteException, FileNotFoundException {
Parcel data = Parcel.obtain();
@@ -703,8 +695,7 @@
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
data.writeString(mode);
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
@@ -723,15 +714,14 @@
}
@Override
- public Bundle call(String callingPkg, @Nullable String featureId, String authority,
+ public Bundle call(@NonNull AttributionSource attributionSource, String authority,
String method, String request, Bundle extras) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
data.writeString(authority);
data.writeString(method);
data.writeString(request);
@@ -771,7 +761,7 @@
}
@Override
- public AssetFileDescriptor openTypedAssetFile(String callingPkg, @Nullable String featureId,
+ public AssetFileDescriptor openTypedAssetFile(@NonNull AttributionSource attributionSource,
Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
throws RemoteException, FileNotFoundException {
Parcel data = Parcel.obtain();
@@ -779,8 +769,7 @@
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
data.writeString(mimeType);
data.writeBundle(opts);
@@ -820,15 +809,14 @@
}
@Override
- public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri url)
+ public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri url)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
mRemote.transact(IContentProvider.CANONICALIZE_TRANSACTION, data, reply, 0);
@@ -843,14 +831,13 @@
}
@Override
- /* oneway */ public void canonicalizeAsync(String callingPkg, @Nullable String featureId,
+ /* oneway */ public void canonicalizeAsync(@NonNull AttributionSource attributionSource,
Uri uri, RemoteCallback callback) throws RemoteException {
Parcel data = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
uri.writeToParcel(data, 0);
callback.writeToParcel(data, 0);
@@ -862,15 +849,14 @@
}
@Override
- public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri url)
+ public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri url)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
mRemote.transact(IContentProvider.UNCANONICALIZE_TRANSACTION, data, reply, 0);
@@ -885,14 +871,13 @@
}
@Override
- /* oneway */ public void uncanonicalizeAsync(String callingPkg, @Nullable String featureId,
+ /* oneway */ public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource,
Uri uri, RemoteCallback callback) throws RemoteException {
Parcel data = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
uri.writeToParcel(data, 0);
callback.writeToParcel(data, 0);
@@ -904,15 +889,14 @@
}
@Override
- public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle extras,
+ public boolean refresh(@NonNull AttributionSource attributionSource, Uri url, Bundle extras,
ICancellationSignal signal) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
data.writeBundle(extras);
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
@@ -929,15 +913,14 @@
}
@Override
- public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri url, int uid,
+ public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri url, int uid,
int modeFlags) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(callingPkg);
- data.writeString(featureId);
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
data.writeInt(uid);
data.writeInt(modeFlags);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 8ea417f..aec39da 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -816,7 +816,6 @@
public ContentResolver(@Nullable Context context, @Nullable ContentInterface wrapped) {
mContext = context != null ? context : ActivityThread.currentApplication();
mPackageName = mContext.getOpPackageName();
- mAttributionTag = mContext.getAttributionTag();
mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
mWrapped = wrapped;
}
@@ -1217,7 +1216,7 @@
cancellationSignal.setRemote(remoteCancellationSignal);
}
try {
- qCursor = unstableProvider.query(mPackageName, mAttributionTag, uri, projection,
+ qCursor = unstableProvider.query(mContext.getAttributionSource(), uri, projection,
queryArgs, remoteCancellationSignal);
} catch (DeadObjectException e) {
// The remote process has died... but we only hold an unstable
@@ -1228,7 +1227,7 @@
if (stableProvider == null) {
return null;
}
- qCursor = stableProvider.query(mPackageName, mAttributionTag, uri, projection,
+ qCursor = stableProvider.query(mContext.getAttributionSource(), uri, projection,
queryArgs, remoteCancellationSignal);
}
if (qCursor == null) {
@@ -1320,7 +1319,7 @@
try {
final UriResultListener resultListener = new UriResultListener();
- provider.canonicalizeAsync(mPackageName, mAttributionTag, url,
+ provider.canonicalizeAsync(mContext.getAttributionSource(), url,
new RemoteCallback(resultListener));
resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
if (resultListener.exception != null) {
@@ -1371,7 +1370,7 @@
try {
final UriResultListener resultListener = new UriResultListener();
- provider.uncanonicalizeAsync(mPackageName, mAttributionTag, url,
+ provider.uncanonicalizeAsync(mContext.getAttributionSource(), url,
new RemoteCallback(resultListener));
resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
if (resultListener.exception != null) {
@@ -1429,7 +1428,7 @@
remoteCancellationSignal = provider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return provider.refresh(mPackageName, mAttributionTag, url, extras,
+ return provider.refresh(mContext.getAttributionSource(), url, extras,
remoteCancellationSignal);
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
@@ -1858,7 +1857,7 @@
try {
fd = unstableProvider.openAssetFile(
- mPackageName, mAttributionTag, uri, mode,
+ mContext.getAttributionSource(), uri, mode,
remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
@@ -1873,8 +1872,8 @@
if (stableProvider == null) {
throw new FileNotFoundException("No content provider: " + uri);
}
- fd = stableProvider.openAssetFile(
- mPackageName, mAttributionTag, uri, mode, remoteCancellationSignal);
+ fd = stableProvider.openAssetFile(mContext.getAttributionSource(),
+ uri, mode, remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
@@ -2025,7 +2024,7 @@
try {
fd = unstableProvider.openTypedAssetFile(
- mPackageName, mAttributionTag, uri, mimeType, opts,
+ mContext.getAttributionSource(), uri, mimeType, opts,
remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
@@ -2041,7 +2040,7 @@
throw new FileNotFoundException("No content provider: " + uri);
}
fd = stableProvider.openTypedAssetFile(
- mPackageName, mAttributionTag, uri, mimeType, opts,
+ mContext.getAttributionSource(), uri, mimeType, opts,
remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
@@ -2190,7 +2189,7 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- Uri createdRow = provider.insert(mPackageName, mAttributionTag, url, values, extras);
+ Uri createdRow = provider.insert(mContext.getAttributionSource(), url, values, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
return createdRow;
@@ -2271,7 +2270,7 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsCreated = provider.bulkInsert(mPackageName, mAttributionTag, url, values);
+ int rowsCreated = provider.bulkInsert(mContext.getAttributionSource(), url, values);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
return rowsCreated;
@@ -2330,7 +2329,7 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsDeleted = provider.delete(mPackageName, mAttributionTag, url, extras);
+ int rowsDeleted = provider.delete(mContext.getAttributionSource(), url, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "delete", null);
return rowsDeleted;
@@ -2397,7 +2396,8 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsUpdated = provider.update(mPackageName, mAttributionTag, uri, values, extras);
+ int rowsUpdated = provider.update(mContext.getAttributionSource(),
+ uri, values, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, uri, "update", null);
return rowsUpdated;
@@ -2446,8 +2446,8 @@
throw new IllegalArgumentException("Unknown authority " + authority);
}
try {
- final Bundle res = provider.call(mPackageName, mAttributionTag, authority, method, arg,
- extras);
+ final Bundle res = provider.call(mContext.getAttributionSource(),
+ authority, method, arg, extras);
Bundle.setDefusable(res, true);
return res;
} catch (RemoteException e) {
@@ -3866,12 +3866,17 @@
/** @hide */
@UnsupportedAppUsage
public String getPackageName() {
- return mPackageName;
+ return mContext.getOpPackageName();
}
/** @hide */
public @Nullable String getAttributionTag() {
- return mAttributionTag;
+ return mContext.getAttributionTag();
+ }
+
+ /** @hide */
+ public @NonNull AttributionSource getAttributionSource() {
+ return mContext.getAttributionSource();
}
@UnsupportedAppUsage
@@ -3879,9 +3884,9 @@
@UnsupportedAppUsage
private final Context mContext;
+ @Deprecated
@UnsupportedAppUsage
final String mPackageName;
- final @Nullable String mAttributionTag;
final int mTargetSdkVersion;
final ContentInterface mWrapped;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 6ff296c..232daa8 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -889,6 +889,15 @@
return null;
}
+ /**
+ * @return The identity of this context for permission purposes.
+ *
+ * @see AttributionSource
+ */
+ public @NonNull AttributionSource getAttributionSource() {
+ return null;
+ }
+
// TODO moltmann: Remove
/**
* @removed
@@ -6465,8 +6474,10 @@
* @removed
*/
@Deprecated
- public @NonNull Context createFeatureContext(@Nullable String featureId) {
- return createAttributionContext(featureId);
+ public @NonNull Context createFeatureContext(@Nullable String attributionTag) {
+ return createContext(new ContextParams.Builder(getParams())
+ .setAttributionTag(attributionTag)
+ .build());
}
/**
diff --git a/core/java/android/content/ContextParams.java b/core/java/android/content/ContextParams.java
index fad905b..bd3eaea 100644
--- a/core/java/android/content/ContextParams.java
+++ b/core/java/android/content/ContextParams.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import java.util.Collections;
@@ -38,36 +37,27 @@
* is an arbitrary string your app specifies for the purposes of tracking permission
* accesses from a given portion of your app; against another package and optionally
* its attribution tag if you are accessing the data on behalf of another app and
- * you will be passing that data to this app. Both attributions are not mutually
- * exclusive.
- *
- * <p>For example if you have a feature "foo" in your app which accesses
- * permissions on behalf of app "foo.bar.baz" with feature "bar" you need to
- * create a context like this:
- *
- * <pre class="prettyprint">
- * context.createContext(new ContextParams.Builder()
- * .setAttributionTag("foo")
- * .setReceiverPackage("foo.bar.baz", "bar")
- * .build())
- * </pre>
+ * you will be passing that data to this app, recursively. Both attributions are
+ * not mutually exclusive.
*
* @see Context#createContext(ContextParams)
+ * @see AttributionSource
*/
public final class ContextParams {
- private final String mAttributionTag;
- private final String mReceiverPackage;
- private final String mReceiverAttributionTag;
- private final Set<String> mRenouncedPermissions;
+ private final @Nullable String mAttributionTag;
+ private final @Nullable AttributionSource mNext;
+ private final @NonNull Set<String> mRenouncedPermissions;
/** {@hide} */
public static final ContextParams EMPTY = new ContextParams.Builder().build();
- private ContextParams(@NonNull ContextParams.Builder builder) {
- mAttributionTag = builder.mAttributionTag;
- mReceiverPackage = builder.mReceiverPackage;
- mReceiverAttributionTag = builder.mReceiverAttributionTag;
- mRenouncedPermissions = builder.mRenouncedPermissions;
+ private ContextParams(@Nullable String attributionTag,
+ @Nullable AttributionSource next,
+ @Nullable Set<String> renouncedPermissions) {
+ mAttributionTag = attributionTag;
+ mNext = next;
+ mRenouncedPermissions = (renouncedPermissions != null)
+ ? renouncedPermissions : Collections.emptySet();
}
/**
@@ -79,45 +69,35 @@
}
/**
- * @return The receiving package.
- */
- @Nullable
- public String getReceiverPackage() {
- return mReceiverPackage;
- }
-
- /**
- * @return The receiving package's attribution tag.
- */
- @Nullable
- public String getReceiverAttributionTag() {
- return mReceiverAttributionTag;
- }
-
- /**
* @return The set of permissions to treat as renounced.
* @hide
*/
@SystemApi
- @SuppressLint("NullableCollection")
@RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
- public @Nullable Set<String> getRenouncedPermissions() {
+ public @NonNull Set<String> getRenouncedPermissions() {
return mRenouncedPermissions;
}
/** @hide */
public boolean isRenouncedPermission(@NonNull String permission) {
- return mRenouncedPermissions != null && mRenouncedPermissions.contains(permission);
+ return mRenouncedPermissions.contains(permission);
+ }
+
+ /**
+ * @return The receiving attribution source.
+ */
+ @Nullable
+ public AttributionSource getNextAttributionSource() {
+ return mNext;
}
/**
* Builder for creating a {@link ContextParams}.
*/
public static final class Builder {
- private String mAttributionTag;
- private String mReceiverPackage;
- private String mReceiverAttributionTag;
- private Set<String> mRenouncedPermissions;
+ private @Nullable String mAttributionTag;
+ private @NonNull Set<String> mRenouncedPermissions = Collections.emptySet();
+ private @Nullable AttributionSource mNext;
/**
* Create a new builder.
@@ -145,9 +125,8 @@
public Builder(@NonNull ContextParams params) {
Objects.requireNonNull(params);
mAttributionTag = params.mAttributionTag;
- mReceiverPackage = params.mReceiverPackage;
- mReceiverAttributionTag = params.mReceiverAttributionTag;
mRenouncedPermissions = params.mRenouncedPermissions;
+ mNext = params.mNext;
}
/**
@@ -163,18 +142,16 @@
}
/**
- * Sets the package and its optional attribution tag that would be receiving
- * the permission protected data.
+ * Sets the attribution source for the app on whose behalf you are doing the work.
*
- * @param packageName The package name receiving the permission protected data.
- * @param attributionTag An attribution tag of the receiving package.
+ * @param next The permission identity of the receiving app.
* @return This builder.
+ *
+ * @see AttributionSource
*/
@NonNull
- public Builder setReceiverPackage(@Nullable String packageName,
- @Nullable String attributionTag) {
- mReceiverPackage = packageName;
- mReceiverAttributionTag = attributionTag;
+ public Builder setNextAttributionSource(@Nullable AttributionSource next) {
+ mNext = next;
return this;
}
@@ -194,7 +171,7 @@
* permissions are supported by this mechanism.
*
* @param renouncedPermissions The set of permissions to treat as
- * renounced.
+ * renounced, which is as if not granted.
* @return This builder.
* @hide
*/
@@ -202,11 +179,7 @@
@RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
public @NonNull Builder setRenouncedPermissions(
@Nullable Set<String> renouncedPermissions) {
- if (renouncedPermissions != null) {
- mRenouncedPermissions = Collections.unmodifiableSet(renouncedPermissions);
- } else {
- mRenouncedPermissions = null;
- }
+ mRenouncedPermissions = renouncedPermissions;
return this;
}
@@ -217,7 +190,8 @@
*/
@NonNull
public ContextParams build() {
- return new ContextParams(this);
+ return new ContextParams(mAttributionTag, mNext,
+ mRenouncedPermissions);
}
}
}
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 609f417..de0d65f 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1060,6 +1060,12 @@
return mBase.createAttributionContext(attributionTag);
}
+ @NonNull
+ @Override
+ public AttributionSource getAttributionSource() {
+ return mBase.getAttributionSource();
+ }
+
@Override
public boolean isRestricted() {
return mBase.isRestricted();
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 9210b13..e0315a3 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -16,11 +16,13 @@
package android.content;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
@@ -38,11 +40,11 @@
* @hide
*/
public interface IContentProvider extends IInterface {
- public Cursor query(String callingPkg, @Nullable String attributionTag, Uri url,
+ Cursor query(@NonNull AttributionSource attributionSource, Uri url,
@Nullable String[] projection,
@Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
throws RemoteException;
- public String getType(Uri url) throws RemoteException;
+ String getType(Uri url) throws RemoteException;
/**
* A oneway version of getType. The functionality is exactly the same, except that the
@@ -55,54 +57,56 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ "ContentProviderClient#insert(android.net.Uri, android.content.ContentValues)} "
+ "instead")
- public default Uri insert(String callingPkg, Uri url, ContentValues initialValues)
+ default Uri insert(String callingPkg, Uri url, ContentValues initialValues)
throws RemoteException {
- return insert(callingPkg, null, url, initialValues, null);
+ return insert(new AttributionSource(Binder.getCallingUid(), callingPkg, null),
+ url, initialValues, null);
}
- public Uri insert(String callingPkg, String attributionTag, Uri url,
+ Uri insert(@NonNull AttributionSource attributionSource, Uri url,
ContentValues initialValues, Bundle extras) throws RemoteException;
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ "ContentProviderClient#bulkInsert(android.net.Uri, android.content.ContentValues[])"
+ "} instead")
- public default int bulkInsert(String callingPkg, Uri url, ContentValues[] initialValues)
+ default int bulkInsert(String callingPkg, Uri url, ContentValues[] initialValues)
throws RemoteException {
- return bulkInsert(callingPkg, null, url, initialValues);
+ return bulkInsert(new AttributionSource(Binder.getCallingUid(), callingPkg, null),
+ url, initialValues);
}
- public int bulkInsert(String callingPkg, String attributionTag, Uri url,
+ int bulkInsert(@NonNull AttributionSource attributionSource, Uri url,
ContentValues[] initialValues) throws RemoteException;
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ "ContentProviderClient#delete(android.net.Uri, java.lang.String, java.lang"
+ ".String[])} instead")
- public default int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
+ default int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
throws RemoteException {
- return delete(callingPkg, null, url,
- ContentResolver.createSqlQueryBundle(selection, selectionArgs));
+ return delete(new AttributionSource(Binder.getCallingUid(), callingPkg, null),
+ url, ContentResolver.createSqlQueryBundle(selection, selectionArgs));
}
- public int delete(String callingPkg, String attributionTag, Uri url, Bundle extras)
+ int delete(@NonNull AttributionSource attributionSource, Uri url, Bundle extras)
throws RemoteException;
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ "ContentProviderClient#update(android.net.Uri, android.content.ContentValues, java"
+ ".lang.String, java.lang.String[])} instead")
- public default int update(String callingPkg, Uri url, ContentValues values, String selection,
+ default int update(String callingPkg, Uri url, ContentValues values, String selection,
String[] selectionArgs) throws RemoteException {
- return update(callingPkg, null, url, values,
- ContentResolver.createSqlQueryBundle(selection, selectionArgs));
+ return update(new AttributionSource(Binder.getCallingUid(), callingPkg, null),
+ url, values, ContentResolver.createSqlQueryBundle(selection, selectionArgs));
}
- public int update(String callingPkg, String attributionTag, Uri url, ContentValues values,
+ int update(@NonNull AttributionSource attributionSource, Uri url, ContentValues values,
Bundle extras) throws RemoteException;
- public ParcelFileDescriptor openFile(String callingPkg, @Nullable String attributionTag,
- Uri url, String mode, ICancellationSignal signal, IBinder callerToken)
- throws RemoteException, FileNotFoundException;
-
- public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String attributionTag,
+ ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource,
Uri url, String mode, ICancellationSignal signal)
throws RemoteException, FileNotFoundException;
- public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String attributionTag,
+ AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
+ Uri url, String mode, ICancellationSignal signal)
+ throws RemoteException, FileNotFoundException;
+
+ ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
String authority, ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException;
@@ -112,18 +116,19 @@
+ "instead")
public default Bundle call(String callingPkg, String method,
@Nullable String arg, @Nullable Bundle extras) throws RemoteException {
- return call(callingPkg, null, "unknown", method, arg, extras);
+ return call(new AttributionSource(Binder.getCallingUid(), callingPkg, null),
+ "unknown", method, arg, extras);
}
- public Bundle call(String callingPkg, @Nullable String attributionTag, String authority,
+ Bundle call(@NonNull AttributionSource attributionSource, String authority,
String method, @Nullable String arg, @Nullable Bundle extras) throws RemoteException;
- public int checkUriPermission(String callingPkg, @Nullable String attributionTag, Uri uri,
+ int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri,
int uid, int modeFlags) throws RemoteException;
- public ICancellationSignal createCancellationSignal() throws RemoteException;
+ ICancellationSignal createCancellationSignal() throws RemoteException;
- public Uri canonicalize(String callingPkg, @Nullable String attributionTag, Uri uri)
+ Uri canonicalize(@NonNull AttributionSource attributionSource, Uri uri)
throws RemoteException;
/**
@@ -131,10 +136,10 @@
* call returns immediately, and the resulting type is returned when available via
* a binder callback.
*/
- void canonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
+ void canonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
RemoteCallback callback) throws RemoteException;
- public Uri uncanonicalize(String callingPkg, @Nullable String attributionTag, Uri uri)
+ Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri uri)
throws RemoteException;
/**
@@ -142,18 +147,17 @@
* call returns immediately, and the resulting type is returned when available via
* a binder callback.
*/
- void uncanonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
+ void uncanonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
RemoteCallback callback) throws RemoteException;
- public boolean refresh(String callingPkg, @Nullable String attributionTag, Uri url,
+ public boolean refresh(@NonNull AttributionSource attributionSource, Uri url,
@Nullable Bundle extras, ICancellationSignal cancellationSignal) throws RemoteException;
// Data interchange.
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException;
- public AssetFileDescriptor openTypedAssetFile(String callingPkg,
- @Nullable String attributionTag, Uri url, String mimeType, Bundle opts,
- ICancellationSignal signal)
+ public AssetFileDescriptor openTypedAssetFile(@NonNull AttributionSource attributionSource,
+ Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
throws RemoteException, FileNotFoundException;
/* IPC constants */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 96b8fbe..2c77372 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1979,6 +1979,43 @@
"android.intent.action.VIEW_PERMISSION_USAGE";
/**
+ * Activity action: Launch UI to show information about the usage of a given permission group in
+ * a given period. This action would be handled by apps that want to show details about how and
+ * why given permission group is being used.
+ * <p>
+ * <strong>Important:</strong>You must protect the activity that handles this action with the
+ * {@link android.Manifest.permission#START_VIEW_PERMISSION_USAGE} permission to ensure that
+ * only the system can launch this activity. The system will not launch activities that are not
+ * properly protected.
+ *
+ * <p>
+ * Input: {@link #EXTRA_PERMISSION_GROUP_NAME} specifies the permission group for which the
+ * launched UI would be targeted.
+ * </p>
+ * <p>
+ * Input: {@link #EXTRA_ATTRIBUTION_TAGS} specifies the attribution tags for the usage entry.
+ * </p>
+ * <p>
+ * Input: {@link #EXTRA_START_TIME} specifies the start time of the period. Both start time and
+ * end time are needed and start time must be <= end time.
+ * </p>
+ * <p>
+ * Input: {@link #EXTRA_END_TIME} specifies the end time of the period. Both start time and end
+ * time are needed and start time must be <= end time.
+ * </p>
+ * <p>
+ * Output: Nothing.
+ * </p>
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ @RequiresPermission(android.Manifest.permission.START_VIEW_PERMISSION_USAGE)
+ @SystemApi
+ public static final String ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD =
+ "android.intent.action.VIEW_PERMISSION_USAGE_FOR_PERIOD";
+
+ /**
* Activity action: Launch UI to manage a default app.
* <p>
* Input: {@link #EXTRA_ROLE_NAME} specifies the role of the default app which will be managed
@@ -5336,6 +5373,33 @@
public static final String EXTRA_TASK_ID = "android.intent.extra.TASK_ID";
/**
+ * A String[] holding attribution tags when used with
+ * {@link #ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD}
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_ATTRIBUTION_TAGS = "android.intent.extra.ATTRIBUTION_TAGS";
+
+ /**
+ * A long representing the start timestamp (in millis) of the permission usage when used with
+ * {@link #ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD}
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_START_TIME = "android.intent.extra.START_TIME";
+
+ /**
+ * A long representing the end timestamp (in millis) of the permission usage when used with
+ * {@link #ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD}
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_END_TIME = "android.intent.extra.END_TIME";
+
+ /**
* An Intent[] describing additional, alternate choices you would like shown with
* {@link #ACTION_CHOOSER}.
*
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index 159db92..fc963fe 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -16,6 +16,7 @@
package android.content;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -24,9 +25,12 @@
import android.content.pm.PermissionInfo;
import android.os.Binder;
import android.os.Process;
+import android.util.Slog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
/**
* This class provides permission check APIs that verify both the
@@ -68,8 +72,16 @@
* @hide
*/
public final class PermissionChecker {
+ private static final String LOG_TAG = PermissionChecker.class.getName();
+
+ private static final String PLATFORM_PACKAGE_NAME = "android";
+
/** The permission is granted. */
- public static final int PERMISSION_GRANTED = PackageManager.PERMISSION_GRANTED;
+ public static final int PERMISSION_GRANTED = AppOpsManager.MODE_ALLOWED;
+
+ /** Only for runtime permissions, its returned when the runtime permission
+ * is granted, but the corresponding app op is denied. */
+ public static final int PERMISSION_SOFT_DENIED = AppOpsManager.MODE_IGNORED;
/** Returned when:
* <ul>
@@ -79,15 +91,15 @@
* </ul>
*
*/
- public static final int PERMISSION_HARD_DENIED = PackageManager.PERMISSION_DENIED;
-
- /** Only for runtime permissions, its returned when the runtime permission
- * is granted, but the corresponding app op is denied. */
- public static final int PERMISSION_SOFT_DENIED = PackageManager.PERMISSION_DENIED - 1;
+ public static final int PERMISSION_HARD_DENIED = AppOpsManager.MODE_ERRORED;
/** Constant when the PID for which we check permissions is unknown. */
public static final int PID_UNKNOWN = -1;
+ // Cache for platform defined runtime permissions to avoid multi lookup (name -> info)
+ private static final ConcurrentHashMap<String, PermissionInfo> sPlatformPermissions
+ = new ConcurrentHashMap<>();
+
/** @hide */
@IntDef({PERMISSION_GRANTED,
PERMISSION_SOFT_DENIED,
@@ -131,6 +143,50 @@
* @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
+ * @param startDataDelivery Whether this is the start of data delivery.
+ *
+ * @see #checkPermissionForPreflight(Context, String, int, int, String)
+ */
+ @PermissionResult
+ public static int checkPermissionForDataDelivery(@NonNull Context context,
+ @NonNull String permission, int pid, int uid, @Nullable String packageName,
+ @Nullable String attributionTag, @Nullable String message, boolean startDataDelivery) {
+ return checkPermissionForDataDelivery(context, permission, pid, new AttributionSource(uid,
+ packageName, attributionTag), message, startDataDelivery);
+ }
+
+ /**
+ * Checks whether a given package in a UID and PID has a given permission
+ * and whether the app op that corresponds to this permission is allowed.
+ *
+ * <strong>NOTE:</strong> Use this method only for permission checks at the
+ * point where you will deliver the permission protected data to clients.
+ *
+ * <p>For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)}
+ * to determine if the app has or may have location permission (if app has only foreground
+ * location the grant state depends on the app's fg/gb state) and this check will not
+ * leave a trace that permission protected data was delivered. When you are about to
+ * deliver the location data to a registered listener you should use this method which
+ * 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
+ * is not known.
+ * @param uid The uid for which to check.
+ * @param packageName The package name for which to check. If null the
+ * the first package for the calling UID will be used.
+ * @param attributionTag 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
*
* @see #checkPermissionForPreflight(Context, String, int, int, String)
*/
@@ -138,8 +194,303 @@
public static int checkPermissionForDataDelivery(@NonNull Context context,
@NonNull String permission, int pid, int uid, @Nullable String packageName,
@Nullable String attributionTag, @Nullable String message) {
- return checkPermissionCommon(context, permission, pid, uid, packageName, attributionTag,
- message, true /*forDataDelivery*/);
+ return checkPermissionForDataDelivery(context, permission, pid, uid,
+ packageName, attributionTag, message, false /*startDataDelivery*/);
+ }
+
+ /**
+ * Checks whether a given data access chain described by the given {@link AttributionSource}
+ * has a given permission and whether the app op that corresponds to this permission
+ * is allowed. Call this method if you are the datasource which would not blame you for
+ * access to the data since you are the data.
+ *
+ * <strong>NOTE:</strong> Use this method only for permission checks at the
+ * point where you will deliver the permission protected data to clients.
+ *
+ * <p>For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)}
+ * to determine if the app has or may have location permission (if app has only foreground
+ * location the grant state depends on the app's fg/gb state) and this check will not
+ * leave a trace that permission protected data was delivered. When you are about to
+ * deliver the location data to a registered listener you should use this method which
+ * will evaluate the permission access based on the current fg/bg state of the app and
+ * leave a record that the data was accessed.
+ *
+ * @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
+ * is not known.
+ * @param attributionSource the permission identity
+ * @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
+ *
+ * @see #checkPermissionForPreflight(Context, String, AttributionSource)
+ */
+ @PermissionResult
+ public static int checkPermissionForDataDeliveryFromDataSource(@NonNull Context context,
+ @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
+ @Nullable String message) {
+ return checkPermissionForDataDeliveryCommon(context, permission, pid, attributionSource,
+ message, false /*startDataDelivery*/, /*fromDatasource*/ true);
+ }
+
+ /**
+ * Checks whether a given data access chain described by the given {@link AttributionSource}
+ * has a given permission and whether the app op that corresponds to this permission
+ * is allowed.
+ *
+ * <strong>NOTE:</strong> Use this method only for permission checks at the
+ * point where you will deliver the permission protected data to clients.
+ *
+ * <p>For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkPermissionForPreflight(Context, String, AttributionSource)}
+ * to determine if the app has or may have location permission (if app has only foreground
+ * location the grant state depends on the app's fg/gb state) and this check will not
+ * leave a trace that permission protected data was delivered. When you are about to
+ * deliver the location data to a registered listener you should use this method which
+ * will evaluate the permission access based on the current fg/bg state of the app and
+ * leave a record that the data was accessed.
+ *
+ * @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
+ * is not known.
+ * @param attributionSource the permission identity
+ * @param message A message describing the reason the permission was checked
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+ *
+ * @see #checkPermissionForPreflight(Context, String, AttributionSource)
+ */
+ @PermissionResult
+ public static int checkPermissionForDataDelivery(@NonNull Context context,
+ @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
+ @Nullable String message) {
+ return checkPermissionForDataDelivery(context, permission, pid, attributionSource,
+ message, false /*startDataDelivery*/);
+ }
+
+ /**
+ * Checks whether a given data access chain described by the given {@link AttributionSource}
+ * has a given permission and whether the app op that corresponds to this permission
+ * is allowed.
+ *
+ * <strong>NOTE:</strong> Use this method only for permission checks at the
+ * point where you will deliver the permission protected data to clients.
+ *
+ * <p>For example, if an app registers a data listener it should have the required
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkPermissionForPreflight(Context, String,
+ * AttributionSource)}
+ * to determine if the app has or may have permission and this check will not
+ * leave a trace that permission protected data was delivered. When you are about to
+ * deliver the data to a registered listener you should use this method which
+ * will evaluate the permission access based on the current fg/bg state of the app and
+ * leave a record that the data was accessed.
+ *
+ * @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
+ * is not known.
+ * @param attributionSource The identity for which to check the permission.
+ * @param message A message describing the reason the permission was checked
+ * @param startDataDelivery Whether this is the start of data delivery.
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+ *
+ * @see #checkPermissionForPreflight(Context, String, AttributionSource)
+ */
+ @PermissionResult
+ public static int checkPermissionForDataDelivery(@NonNull Context context,
+ @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
+ @Nullable String message, boolean startDataDelivery) {
+ return checkPermissionForDataDeliveryCommon(context, permission, pid, attributionSource,
+ message, startDataDelivery, /*fromDatasource*/ false);
+ }
+
+ private static int checkPermissionForDataDeliveryCommon(@NonNull Context context,
+ @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
+ @Nullable String message, boolean startDataDelivery, boolean fromDatasource) {
+ // If the check failed in the middle of the chain, finish any started op.
+ final int result = checkPermissionCommon(context, permission, attributionSource,
+ message, true /*forDataDelivery*/, startDataDelivery, fromDatasource);
+ if (startDataDelivery && result != PERMISSION_GRANTED) {
+ finishDataDelivery(context, AppOpsManager.permissionToOp(permission),
+ attributionSource);
+ }
+ return result;
+ }
+
+ /**
+ * Checks whether a given data access chain described by the given {@link AttributionSource}
+ * has a given permission and whether the app op that corresponds to this permission
+ * is allowed. The app ops area also marked as started. This is useful for long running
+ * permissions like camera.
+ *
+ * <strong>NOTE:</strong> Use this method only for permission checks at the
+ * point where you will deliver the permission protected data to clients.
+ *
+ * <p>For example, if an app registers a data listener it should have the required
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkPermissionForPreflight(Context, String,
+ * AttributionSource)}
+ * to determine if the app has or may have permission and this check will not
+ * leave a trace that permission protected data was delivered. When you are about to
+ * deliver the data to a registered listener you should use this method which
+ * will evaluate the permission access based on the current fg/bg state of the app and
+ * leave a record that the data was accessed.
+ *
+ * @param context Context for accessing resources.
+ * @param permission The permission to check.
+ * @param attributionSource The identity for which to check the permission.
+ * @param message A message describing the reason the permission was checked
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+ *
+ * @see #checkPermissionForPreflight(Context, String, AttributionSource)
+ */
+ @PermissionResult
+ public static int checkPermissionAndStartDataDelivery(@NonNull Context context,
+ @NonNull String permission, @NonNull AttributionSource attributionSource,
+ @Nullable String message) {
+ return checkPermissionCommon(context, permission, attributionSource,
+ message, true /*forDataDelivery*/, /*startDataDelivery*/ true,
+ /*fromDatasource*/ false);
+ }
+
+ /**
+ * Checks whether a given data access chain described by the given {@link
+ * AttributionSource} has a given app op allowed and marks the op as started.
+ *
+ * <strong>NOTE:</strong> Use this method only for app op checks at the
+ * point where you will deliver the protected data to clients.
+ *
+ * <p>For example, if an app registers a data listener it should have the data
+ * op but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkOpForPreflight(Context, String, AttributionSource, String)}
+ * to determine if the app has or may have op access and this check will not
+ * leave a trace that op protected data was delivered. When you are about to
+ * deliver the data to a registered listener you should use this method which
+ * will evaluate the op access based on the current fg/bg state of the app and
+ * leave a record that the data was accessed.
+ *
+ * @param context Context for accessing resources.
+ * @param opName THe op to start.
+ * @param attributionSource The identity for which to check the permission.
+ * @param message A message describing the reason the permission was checked
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+ *
+ * @see #finishDataDelivery(Context, String, AttributionSource)
+ */
+ @PermissionResult
+ public static int startOpForDataDelivery(@NonNull Context context,
+ @NonNull String opName, @NonNull AttributionSource attributionSource,
+ @Nullable String message) {
+ final int result = checkOp(context, AppOpsManager.strOpToOp(opName), attributionSource,
+ message, true /*forDataDelivery*/, true /*startDataDelivery*/);
+ // It is important to finish any started op if some step in the attribution chain failed.
+ if (result != PERMISSION_GRANTED) {
+ finishDataDelivery(context, opName, attributionSource);
+ }
+ return result;
+ }
+
+ /**
+ * Finishes an ongoing op for data access chain described by the given {@link
+ * AttributionSource}.
+ *
+ * @param context Context for accessing resources.
+ * @param op The op to finish.
+ * @param attributionSource The identity for which finish op.
+ *
+ * @see #startOpForDataDelivery(Context, String, AttributionSource, String)
+ * @see #checkPermissionAndStartDataDelivery(Context, String, AttributionSource, String)
+ */
+ public static void finishDataDelivery(@NonNull Context context, @NonNull String op,
+ @NonNull AttributionSource attributionSource) {
+ if (op == null || attributionSource.getPackageName() == null) {
+ return;
+ }
+
+ final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+ appOpsManager.finishProxyOp(op, attributionSource);
+
+ if (attributionSource.getNext() != null) {
+ finishDataDelivery(context, op, attributionSource.getNext());
+ }
+ }
+
+ /**
+ * Checks whether a given data access chain described by the given {@link
+ * AttributionSource} has a given app op allowed.
+ *
+ * <strong>NOTE:</strong> Use this method only for op checks at the
+ * preflight point where you will not deliver the protected data
+ * to clients but schedule a data delivery, apps register listeners,
+ * etc.
+ *
+ * <p>For example, if an app registers a data listener it should have the op
+ * but no data is actually sent to the app at the moment of registration
+ * and you should use this method to determine if the app has or may have data
+ * access and this check will not leave a trace that protected data
+ * was delivered. When you are about to deliver the data to a registered
+ * listener you should use {@link #checkOpForDataDelivery(Context, String,
+ * AttributionSource, String)} which will evaluate the op access based
+ * on the current fg/bg state of the app and leave a record that the data was
+ * accessed.
+ *
+ * @param context Context for accessing resources.
+ * @param opName The op to check.
+ * @param attributionSource The identity for which to check the permission.
+ * @param message A message describing the reason the permission was checked
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+ *
+ * @see #checkOpForDataDelivery(Context, String, AttributionSource, String)
+ */
+ @PermissionResult
+ public static int checkOpForPreflight(@NonNull Context context,
+ @NonNull String opName, @NonNull AttributionSource attributionSource,
+ @Nullable String message) {
+ return checkOp(context, AppOpsManager.strOpToOp(opName), attributionSource,
+ message, false /*forDataDelivery*/, false /*startDataDelivery*/);
+ }
+
+ /**
+ * Checks whether a given data access chain described by the given {@link AttributionSource}
+ * has an allowed app op.
+ *
+ * <strong>NOTE:</strong> Use this method only for op checks at the
+ * point where you will deliver the permission protected data to clients.
+ *
+ * <p>For example, if an app registers a data listener it should have the data
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkOpForPreflight(Context, String, AttributionSource, String)}
+ * to determine if the app has or may have data access and this check will not
+ * leave a trace that op protected data was delivered. When you are about to
+ * deliver the data to a registered listener you should use this method which
+ * will evaluate the op access based on the current fg/bg state of the app and
+ * leave a record that the data was accessed.
+ *
+ * @param context Context for accessing resources.
+ * @param opName The op to check.
+ * @param attributionSource The identity for which to check the op.
+ * @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
+ *
+ * @see #checkOpForPreflight(Context, String, AttributionSource, String)
+ */
+ @PermissionResult
+ public static int checkOpForDataDelivery(@NonNull Context context,
+ @NonNull String opName, @NonNull AttributionSource attributionSource,
+ @Nullable String message) {
+ return checkOp(context, AppOpsManager.strOpToOp(opName), attributionSource,
+ message, true /*forDataDelivery*/, false /*startDataDelivery*/);
}
/**
@@ -158,8 +509,8 @@
* fg/gb state) and this check will not leave a trace that permission protected data
* was delivered. When you are about to deliver the location data to a registered
* listener you should use {@link #checkPermissionForDataDelivery(Context, String,
- * int, int, String, String)} which will evaluate the permission access based on the current
- * fg/bg state of the app and leave a record that the data was accessed.
+ * int, int, String, String, String)} which will evaluate the permission access based
+ * on the currentfg/bg state of the app and leave a record that the data was accessed.
*
* @param context Context for accessing resources.
* @param permission The permission to check.
@@ -170,13 +521,49 @@
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
*
- * @see #checkPermissionForDataDelivery(Context, String, int, int, String, String)
+ * @see #checkPermissionForDataDelivery(Context, String, int, int, String, String, String)
*/
@PermissionResult
public static int checkPermissionForPreflight(@NonNull Context context,
@NonNull String permission, int pid, int uid, @Nullable String packageName) {
- return checkPermissionCommon(context, permission, pid, uid, packageName,
- null /*attributionTag*/, null /*message*/, false /*forDataDelivery*/);
+ return checkPermissionForPreflight(context, permission, new AttributionSource(
+ uid, packageName, null /*attributionTag*/));
+ }
+
+ /**
+ * Checks whether a given data access chain described by the given {@link AttributionSource}
+ * has a given permission and whether the app op that corresponds to this permission
+ * is allowed.
+ *
+ * <strong>NOTE:</strong> Use this method only for permission checks at the
+ * preflight point where you will not deliver the permission protected data
+ * to clients but schedule permission data delivery, apps register listeners,
+ * etc.
+ *
+ * <p>For example, if an app registers a data listener it should have the required
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use this method to determine if the app has or may have the
+ * permission and this check will not leave a trace that permission protected data
+ * was delivered. When you are about to deliver the protected data to a registered
+ * listener you should use {@link #checkPermissionForDataDelivery(Context, String,
+ * int, AttributionSource, String, boolean)} which will evaluate the permission access based
+ * on the current fg/bg state of the app and leave a record that the data was accessed.
+ *
+ * @param context Context for accessing resources.
+ * @param permission The permission to check.
+ * @param attributionSource The identity for which to check the permission.
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
+ *
+ * @see #checkPermissionForDataDelivery(Context, String, int, AttributionSource,
+ * String, boolean)
+ */
+ @PermissionResult
+ public static int checkPermissionForPreflight(@NonNull Context context,
+ @NonNull String permission, @NonNull AttributionSource attributionSource) {
+ return checkPermissionCommon(context, permission, attributionSource,
+ null /*message*/, false /*forDataDelivery*/, /*startDataDelivery*/ false,
+ /*fromDatasource*/ false);
}
/**
@@ -211,7 +598,8 @@
public static int checkSelfPermissionForDataDelivery(@NonNull Context context,
@NonNull String permission, @Nullable String message) {
return checkPermissionForDataDelivery(context, permission, Process.myPid(),
- Process.myUid(), context.getPackageName(), context.getAttributionTag(), message);
+ Process.myUid(), context.getPackageName(), context.getAttributionTag(), message,
+ /*startDataDelivery*/ false);
}
/**
@@ -289,7 +677,8 @@
return PERMISSION_HARD_DENIED;
}
return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
- Binder.getCallingUid(), callingPackageName, callingAttributionTag, message);
+ Binder.getCallingUid(), callingPackageName, callingAttributionTag, message,
+ /*startDataDelivery*/ false);
}
/**
@@ -308,8 +697,8 @@
* fg/gb state) and this check will not leave a trace that permission protected data
* was delivered. When you are about to deliver the location data to a registered
* listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
- * String, String)} which will evaluate the permission access based on the current fg/bg state
- * of the app and leave a record that the data was accessed.
+ * String, String, String, String)} which will evaluate the permission access based on the
+ * current fg/bg stateof the app and leave a record that the data was accessed.
*
* @param context Context for accessing resources.
* @param permission The permission to check.
@@ -318,7 +707,7 @@
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
*
- * @see #checkCallingPermissionForDataDelivery(Context, String, String, String)
+ * @see #checkCallingPermissionForDataDelivery(Context, String, String, String, String)
*/
@PermissionResult
public static int checkCallingPermissionForPreflight(@NonNull Context context,
@@ -370,7 +759,8 @@
callingAttributionTag = (Binder.getCallingPid() == Process.myPid())
? context.getAttributionTag() : callingAttributionTag;
return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
- Binder.getCallingUid(), callingPackageName, callingAttributionTag, message);
+ Binder.getCallingUid(), callingPackageName, callingAttributionTag, message,
+ /*startDataDelivery*/ false);
}
/**
@@ -408,88 +798,326 @@
Binder.getCallingUid(), packageName);
}
- static int checkPermissionCommon(@NonNull Context context, @NonNull String permission,
- int pid, int uid, @Nullable String packageName, @Nullable String attributionTag,
- @Nullable String message, boolean forDataDelivery) {
- final PermissionInfo permissionInfo;
- try {
- // TODO(b/147869157): Cache platform defined app op and runtime permissions to avoid
- // calling into the package manager every time.
- permissionInfo = context.getPackageManager().getPermissionInfo(permission, 0);
- } catch (PackageManager.NameNotFoundException ignored) {
- return PERMISSION_HARD_DENIED;
- }
+ @PermissionResult
+ private static int checkPermissionCommon(@NonNull Context context, @NonNull String permission,
+ @NonNull AttributionSource attributionSource,
+ @Nullable String message, boolean forDataDelivery, boolean startDataDelivery,
+ boolean fromDatasource) {
+ PermissionInfo permissionInfo = sPlatformPermissions.get(permission);
- if (packageName == null) {
- String[] packageNames = context.getPackageManager().getPackagesForUid(uid);
- if (packageNames != null && packageNames.length > 0) {
- packageName = packageNames[0];
+ if (permissionInfo == null) {
+ try {
+ permissionInfo = context.getPackageManager().getPermissionInfo(permission, 0);
+ if (PLATFORM_PACKAGE_NAME.equals(permissionInfo.packageName)) {
+ // Double addition due to concurrency is fine - the backing store is concurrent.
+ sPlatformPermissions.put(permission, permissionInfo);
+ }
+ } catch (PackageManager.NameNotFoundException ignored) {
+ return PERMISSION_HARD_DENIED;
}
}
if (permissionInfo.isAppOp()) {
- return checkAppOpPermission(context, permission, pid, uid, packageName, attributionTag,
- message, forDataDelivery);
+ return checkAppOpPermission(context, permission, attributionSource, message,
+ forDataDelivery, fromDatasource);
}
if (permissionInfo.isRuntime()) {
- return checkRuntimePermission(context, permission, pid, uid, packageName,
- attributionTag, message, forDataDelivery);
+ return checkRuntimePermission(context, permission, attributionSource, message,
+ forDataDelivery, startDataDelivery, fromDatasource);
}
- return context.checkPermission(permission, pid, uid);
- }
- private static int checkAppOpPermission(@NonNull Context context, @NonNull String permission,
- int pid, int uid, @Nullable String packageName, @Nullable String attributionTag,
- @Nullable String message, boolean forDataDelivery) {
- final String op = AppOpsManager.permissionToOp(permission);
- if (op == null || packageName == null) {
+ if (!fromDatasource && !checkPermission(context, permission, attributionSource.getUid(),
+ attributionSource.getRenouncedPermissions())) {
return PERMISSION_HARD_DENIED;
}
- final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
- final int opMode = (forDataDelivery)
- ? appOpsManager.noteProxyOpNoThrow(op, packageName, uid, attributionTag, message)
- : appOpsManager.unsafeCheckOpRawNoThrow(op, uid, packageName);
+ if (attributionSource.getNext() != null) {
+ return checkPermissionCommon(context, permission,
+ attributionSource.getNext(), message, forDataDelivery,
+ startDataDelivery, /*fromDatasource*/ false);
+ }
- switch (opMode) {
- case AppOpsManager.MODE_ALLOWED:
- case AppOpsManager.MODE_FOREGROUND: {
- return PERMISSION_GRANTED;
- }
- case AppOpsManager.MODE_DEFAULT: {
- return context.checkPermission(permission, pid, uid)
- == PackageManager.PERMISSION_GRANTED
- ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED;
- }
- default: {
+ return PERMISSION_GRANTED;
+ }
+
+ @PermissionResult
+ private static int checkAppOpPermission(@NonNull Context context, @NonNull String permission,
+ @NonNull AttributionSource attributionSource, @Nullable String message,
+ boolean forDataDelivery, boolean fromDatasource) {
+ final int op = AppOpsManager.permissionToOpCode(permission);
+ if (op < 0) {
+ Slog.wtf(LOG_TAG, "Appop permission " + permission + " with no app op defined!");
+ return PERMISSION_HARD_DENIED;
+ }
+
+ AttributionSource current = attributionSource;
+ AttributionSource next = null;
+
+ while (true) {
+ final boolean skipCurrentChecks = (fromDatasource || next != null);
+
+ next = current.getNext();
+
+ // If the call is from a datasource we need to vet only the chain before it. This
+ // way we can avoid the datasource creating an attribution context for every call.
+ if (!(fromDatasource && current == attributionSource)
+ && next != null && !current.isTrusted(context)) {
return PERMISSION_HARD_DENIED;
}
+
+ // The access is for oneself if this is the single receiver of data
+ // after the data source or if this is the single attribution source
+ // in the chain if not from a datasource.
+ final boolean singleReceiverFromDatasource = (fromDatasource
+ && current == attributionSource && next != null && next.getNext() == null);
+ final boolean selfAccess = singleReceiverFromDatasource || next == null;
+
+ final int opMode = performOpTransaction(context, op, current, message,
+ forDataDelivery, /*startDataDelivery*/ false, skipCurrentChecks,
+ selfAccess, singleReceiverFromDatasource);
+
+ switch (opMode) {
+ case AppOpsManager.MODE_IGNORED:
+ case AppOpsManager.MODE_ERRORED: {
+ return PERMISSION_HARD_DENIED;
+ }
+ case AppOpsManager.MODE_DEFAULT: {
+ if (!skipCurrentChecks && !checkPermission(context, permission,
+ attributionSource.getUid(), attributionSource
+ .getRenouncedPermissions())) {
+ return PERMISSION_HARD_DENIED;
+ }
+ if (next != null && !checkPermission(context, permission,
+ next.getUid(), next.getRenouncedPermissions())) {
+ return PERMISSION_HARD_DENIED;
+ }
+ }
+ }
+
+ if (next == null || next.getNext() == null) {
+ return PERMISSION_GRANTED;
+ }
+
+ current = next;
}
}
private static int checkRuntimePermission(@NonNull Context context, @NonNull String permission,
- int pid, int uid, @Nullable String packageName, @Nullable String attributionTag,
- @Nullable String message, boolean forDataDelivery) {
- if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) {
+ @NonNull AttributionSource attributionSource, @Nullable String message,
+ boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource) {
+ // Now let's check the identity chain...
+ final int op = AppOpsManager.permissionToOpCode(permission);
+
+ AttributionSource current = attributionSource;
+ AttributionSource next = null;
+
+ while (true) {
+ final boolean skipCurrentChecks = (fromDatasource || next != null);
+ next = current.getNext();
+
+ // If the call is from a datasource we need to vet only the chain before it. This
+ // way we can avoid the datasource creating an attribution context for every call.
+ if (!(fromDatasource && current == attributionSource)
+ && next != null && !current.isTrusted(context)) {
+ return PERMISSION_HARD_DENIED;
+ }
+
+ // If we already checked the permission for this one, skip the work
+ if (!skipCurrentChecks && !checkPermission(context, permission,
+ current.getUid(), current.getRenouncedPermissions())) {
+ return PERMISSION_HARD_DENIED;
+ }
+
+ if (next != null && !checkPermission(context, permission,
+ next.getUid(), next.getRenouncedPermissions())) {
+ return PERMISSION_HARD_DENIED;
+ }
+
+ if (op < 0) {
+ // Bg location is one-off runtime modifier permission and has no app op
+ if (sPlatformPermissions.contains(permission)
+ && !Manifest.permission.ACCESS_BACKGROUND_LOCATION.equals(permission)) {
+ Slog.wtf(LOG_TAG, "Platform runtime permission " + permission
+ + " with no app op defined!");
+ }
+ if (next == null) {
+ return PERMISSION_GRANTED;
+ }
+ current = next;
+ continue;
+ }
+
+ // The access is for oneself if this is the single receiver of data
+ // after the data source or if this is the single attribution source
+ // in the chain if not from a datasource.
+ final boolean singleReceiverFromDatasource = (fromDatasource
+ && current == attributionSource && next != null && next.getNext() == null);
+ final boolean selfAccess = singleReceiverFromDatasource || next == null;
+
+ final int opMode = performOpTransaction(context, op, current, message,
+ forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
+ singleReceiverFromDatasource);
+
+ switch (opMode) {
+ case AppOpsManager.MODE_ERRORED: {
+ return PERMISSION_HARD_DENIED;
+ }
+ case AppOpsManager.MODE_IGNORED: {
+ return PERMISSION_SOFT_DENIED;
+ }
+ }
+
+ if (next == null || next.getNext() == null) {
+ return PERMISSION_GRANTED;
+ }
+
+ current = next;
+ }
+ }
+
+ private static boolean checkPermission(@NonNull Context context, @NonNull String permission,
+ int uid, @NonNull Set<String> renouncedPermissions) {
+ final boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1,
+ uid) == PackageManager.PERMISSION_GRANTED;
+ if (permissionGranted && renouncedPermissions.contains(permission)) {
+ return false;
+ }
+ return permissionGranted;
+ }
+
+ private static int checkOp(@NonNull Context context, @NonNull int op,
+ @NonNull AttributionSource attributionSource, @Nullable String message,
+ boolean forDataDelivery, boolean startDataDelivery) {
+ if (op < 0 || attributionSource.getPackageName() == null) {
return PERMISSION_HARD_DENIED;
}
- final String op = AppOpsManager.permissionToOp(permission);
- if (op == null || packageName == null) {
- return PERMISSION_GRANTED;
- }
+ AttributionSource current = attributionSource;
+ AttributionSource next = null;
- final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
- final int opMode = (forDataDelivery)
- ? appOpsManager.noteProxyOpNoThrow(op, packageName, uid, attributionTag, message)
- : appOpsManager.unsafeCheckOpRawNoThrow(op, uid, packageName);
+ while (true) {
+ final boolean skipCurrentChecks = (next != null);
+ next = current.getNext();
- switch (opMode) {
- case AppOpsManager.MODE_ALLOWED:
- case AppOpsManager.MODE_FOREGROUND:
+ // If the call is from a datasource we need to vet only the chain before it. This
+ // way we can avoid the datasource creating an attribution context for every call.
+ if (next != null && !current.isTrusted(context)) {
+ return PERMISSION_HARD_DENIED;
+ }
+
+ // The access is for oneself if this is the single attribution source in the chain.
+ final boolean selfAccess = (next == null);
+
+ final int opMode = performOpTransaction(context, op, current, message,
+ forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
+ /*fromDatasource*/ false);
+
+ switch (opMode) {
+ case AppOpsManager.MODE_ERRORED: {
+ return PERMISSION_HARD_DENIED;
+ }
+ case AppOpsManager.MODE_IGNORED: {
+ return PERMISSION_SOFT_DENIED;
+ }
+ }
+
+ if (next == null || next.getNext() == null) {
return PERMISSION_GRANTED;
- default:
- return PERMISSION_SOFT_DENIED;
+ }
+
+ current = next;
}
}
+
+ private static int performOpTransaction(@NonNull Context context, int op,
+ @NonNull AttributionSource attributionSource, @Nullable String message,
+ boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation,
+ boolean selfAccess, boolean singleReceiverFromDatasource) {
+ // We cannot perform app ops transactions without a package name. In all relevant
+ // places we pass the package name but just in case there is a bug somewhere we
+ // do a best effort to resolve the package from the UID (pick first without a loss
+ // of generality - they are in the same security sandbox).
+ final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+ final AttributionSource accessorSource = (!singleReceiverFromDatasource)
+ ? attributionSource : attributionSource.getNext();
+ if (!forDataDelivery) {
+ final String resolvedAccessorPackageName = resolvePackageName(context, accessorSource);
+ if (resolvedAccessorPackageName == null) {
+ return AppOpsManager.MODE_ERRORED;
+ }
+ final int opMode = appOpsManager.unsafeCheckOpRawNoThrow(op,
+ accessorSource.getUid(), resolvedAccessorPackageName);
+ final AttributionSource next = accessorSource.getNext();
+ if (!selfAccess && opMode == AppOpsManager.MODE_ALLOWED && next != null) {
+ final String resolvedNextPackageName = resolvePackageName(context, next);
+ if (resolvedNextPackageName == null) {
+ return AppOpsManager.MODE_ERRORED;
+ }
+ return appOpsManager.unsafeCheckOpRawNoThrow(op, next.getUid(),
+ resolvedNextPackageName);
+ }
+ return opMode;
+ } else if (startDataDelivery) {
+ final AttributionSource resolvedAttributionSource = resolveAttributionSource(
+ context, accessorSource);
+ if (resolvedAttributionSource.getPackageName() == null) {
+ return AppOpsManager.MODE_ERRORED;
+ }
+ if (selfAccess) {
+ return appOpsManager.startOpNoThrow(op, resolvedAttributionSource.getUid(),
+ resolvedAttributionSource.getPackageName(),
+ /*startIfModeDefault*/ false,
+ resolvedAttributionSource.getAttributionTag(),
+ message);
+ } else {
+ return appOpsManager.startProxyOpNoThrow(op, resolvedAttributionSource, message,
+ skipProxyOperation);
+ }
+ } else {
+ final AttributionSource resolvedAttributionSource = resolveAttributionSource(
+ context, accessorSource);
+ if (resolvedAttributionSource.getPackageName() == null) {
+ return AppOpsManager.MODE_ERRORED;
+ }
+ if (selfAccess) {
+ return appOpsManager.noteOpNoThrow(op, resolvedAttributionSource.getUid(),
+ resolvedAttributionSource.getPackageName(),
+ resolvedAttributionSource.getAttributionTag(),
+ message);
+ } else {
+ return appOpsManager.noteProxyOpNoThrow(op, resolvedAttributionSource, message,
+ skipProxyOperation);
+ }
+ }
+ }
+
+ private static @Nullable String resolvePackageName(@NonNull Context context,
+ @NonNull AttributionSource attributionSource) {
+ if (attributionSource.getPackageName() != null) {
+ return attributionSource.getPackageName();
+ }
+ final String[] packageNames = context.getPackageManager().getPackagesForUid(
+ attributionSource.getUid());
+ if (packageNames != null) {
+ // This is best effort if the caller doesn't pass a package. The security
+ // sandbox is UID, therefore we pick an arbitrary package.
+ return packageNames[0];
+ }
+ // Last resort to handle special UIDs like root, etc.
+ return AppOpsManager.resolvePackageName(attributionSource.getUid(),
+ attributionSource.getPackageName());
+ }
+
+ private static @NonNull AttributionSource resolveAttributionSource(
+ @NonNull Context context, @NonNull AttributionSource attributionSource) {
+ if (attributionSource.getPackageName() != null) {
+ return attributionSource;
+ }
+ return new AttributionSource(attributionSource.getUid(),
+ resolvePackageName(context, attributionSource),
+ attributionSource.getAttributionTag(),
+ attributionSource.getToken(),
+ attributionSource.getRenouncedPermissions(),
+ attributionSource.getNext());
+ }
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 5f3ec36..6badf0e0 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -2268,7 +2268,10 @@
return (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0;
}
- /** @hide */
+ /**
+ * True if the application is pre-installed on the OEM partition of the system image.
+ * @hide
+ */
@SystemApi
public boolean isOem() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
@@ -2316,13 +2319,19 @@
return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
}
- /** @hide */
+ /**
+ * True if the application is pre-installed on the vendor partition of the system image.
+ * @hide
+ */
@SystemApi
public boolean isVendor() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
- /** @hide */
+ /**
+ * True if the application is pre-installed on the product partition of the system image.
+ * @hide
+ */
@SystemApi
public boolean isProduct() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 0d218c2..3be7f74 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1567,7 +1567,7 @@
/** {@hide} */
public boolean forceQueryableOverride;
/** {@hide} */
- public Boolean requireUserAction;
+ public int requireUserAction = SessionInfo.USER_ACTION_UNSPECIFIED;
/**
* Construct parameters for a new package install session.
@@ -1610,12 +1610,7 @@
dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel);
}
rollbackDataPolicy = source.readInt();
- int requireUserActionInt = source.readInt();
- requireUserAction = requireUserActionInt == 0
- ? Boolean.FALSE
- : requireUserActionInt == 1
- ? Boolean.TRUE : null;
-
+ requireUserAction = source.readInt();
}
/** {@hide} */
@@ -2048,31 +2043,34 @@
* {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES android.permission
* #REQUEST_INSTALL_PACKAGES} permission, and {@code false} otherwise. When {@code true},
* installers will receive a {@link #STATUS_PENDING_USER_ACTION} callback once the
- * session is committed, indicating that the user is required for the install to proceed.
+ * session is committed, indicating that user action is required for the install to proceed.
* <p>
- * For installers using the {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES
- * android.permission.REQUEST_INSTALL_PACKAGES} permission, user action will not be
- * required when the following conditions are met:
+ * For installers that have been granted the
+ * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES android.permission
+ * .REQUEST_INSTALL_PACKAGES} permission, user action will not be required when all of
+ * the following conditions are met:
*
* <ul>
* <li>{@code requireUserAction} is set to {@code false}.</li>
- * <li>The being installed targets {@link android.os.Build.VERSION_CODES#Q API 29} or
- * higher.</li>
+ * <li>The app being installed targets {@link android.os.Build.VERSION_CODES#Q API 29}
+ * or higher.</li>
* <li>The installer is the {@link InstallSourceInfo#getInstallingPackageName()
* installer of record} of an existing version of the app (i.e.: this install session
- * is an app update or the installer is updating itself).</li>
+ * is an app update) or the installer is updating itself.</li>
* <li>The installer declares the
* {@link android.Manifest.permission#UPDATE_PACKAGES_WITHOUT_USER_ACTION android
* .permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION} permission.</li>
* </ul>
* <p>
* Note: The target API level requirement will advance in future Android versions.
- * Session owners should always be prepared to handle {@link #STATUS_PENDING_USER_ACTION}
+ * Session owners should always be prepared to handle {@link #STATUS_PENDING_USER_ACTION}.
*
* @param requireUserAction whether user action should be required.
*/
public void setRequireUserAction(boolean requireUserAction) {
- this.requireUserAction = requireUserAction;
+ this.requireUserAction = requireUserAction
+ ? SessionInfo.USER_ACTION_REQUIRED
+ : SessionInfo.USER_ACTION_NOT_REQUIRED;
}
/**
@@ -2105,7 +2103,7 @@
pw.printPair("isMultiPackage", isMultiPackage);
pw.printPair("isStaged", isStaged);
pw.printPair("forceQueryable", forceQueryableOverride);
- pw.printPair("requireUserAction", requireUserAction);
+ pw.printPair("requireUserAction", SessionInfo.userActionToString(requireUserAction));
pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
pw.printPair("dataLoaderParams", dataLoaderParams);
pw.printPair("rollbackDataPolicy", rollbackDataPolicy);
@@ -2147,10 +2145,7 @@
dest.writeParcelable(null, flags);
}
dest.writeInt(rollbackDataPolicy);
- dest.writeInt(requireUserAction == Boolean.TRUE
- ? 1
- : requireUserAction == Boolean.FALSE
- ? 0 : 2);
+ dest.writeInt(requireUserAction);
}
public static final Parcelable.Creator<SessionParams>
@@ -2227,7 +2222,7 @@
public @interface UserActionRequirement {}
/**
- * The installer did not calling {@link SessionParams#setRequireUserAction(boolean)} to
+ * The installer did not call {@link SessionParams#setRequireUserAction(boolean)} to
* specify whether user action should be required for the install.
*/
public static final int USER_ACTION_UNSPECIFIED = 0;
@@ -2242,6 +2237,17 @@
*/
public static final int USER_ACTION_NOT_REQUIRED = 2;
+ private static String userActionToString(int requireUserAction) {
+ switch(requireUserAction) {
+ case SessionInfo.USER_ACTION_REQUIRED:
+ return "REQUIRED";
+ case SessionInfo.USER_ACTION_NOT_REQUIRED:
+ return "NOT_REQUIRED";
+ default:
+ return "UNSPECIFIED";
+ }
+ }
+
/** {@hide} */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public int sessionId;
@@ -2334,7 +2340,7 @@
public int rollbackDataPolicy;
/** {@hide} */
- public Boolean requireUserAction;
+ public int requireUserAction;
/** {@hide} */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -2385,11 +2391,7 @@
isCommitted = source.readBoolean();
rollbackDataPolicy = source.readInt();
createdMillis = source.readLong();
- int requireUserActionInt = source.readInt();
- requireUserAction = requireUserActionInt == 0
- ? Boolean.FALSE
- : requireUserActionInt == 1
- ? Boolean.TRUE : null;
+ requireUserAction = source.readInt();
}
/**
@@ -2901,11 +2903,7 @@
*/
@UserActionRequirement
public int getRequireUserAction() {
- return requireUserAction == null
- ? USER_ACTION_UNSPECIFIED
- : requireUserAction == Boolean.TRUE
- ? USER_ACTION_REQUIRED
- : USER_ACTION_NOT_REQUIRED;
+ return requireUserAction;
}
@Override
@@ -2953,10 +2951,7 @@
dest.writeBoolean(isCommitted);
dest.writeInt(rollbackDataPolicy);
dest.writeLong(createdMillis);
- dest.writeInt(requireUserAction == Boolean.TRUE
- ? 1
- : requireUserAction == Boolean.FALSE
- ? 0 : 2);
+ dest.writeInt(requireUserAction);
}
public static final Parcelable.Creator<SessionInfo>
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 921c630..cdd8265 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -34,6 +34,7 @@
import android.util.Xml;
import com.android.internal.R;
+import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
@@ -112,6 +113,18 @@
* android:color="?android:attr/colorAccent"
* android:alpha="0.5" />
* </pre>
+ * <p>
+ * Starting with API 31, items may optionally define an {@link android.R.attr#lStar android:lStar}
+ * attribute to modify the base color's perceptual luminance. This attribute takes a either
+ * floating-point value between 0 and 100 or a theme attribute that resolves as such. The item's
+ * overall color is calculated by converting the base color to an accessibility friendly color space
+ * and setting its L* to the value specified on the {@code lStar} attribute. For
+ * example, the following item represents the theme's accent color at 50% perpectual luminosity:
+ * <pre>
+ * <item android:state_enabled="false"
+ * android:color="?android:attr/colorAccent"
+ * android:lStar="50" />
+ * </pre>
*
* <a name="DeveloperGuide"></a>
* <h3>Developer guide</h3>
@@ -122,6 +135,7 @@
*
* @attr ref android.R.styleable#ColorStateListItem_alpha
* @attr ref android.R.styleable#ColorStateListItem_color
+ * @attr ref android.R.styleable#ColorStateListItem_lStar
*/
public class ColorStateList extends ComplexColor implements Parcelable {
private static final String TAG = "ColorStateList";
@@ -301,6 +315,24 @@
}
/**
+ * Creates a new ColorStateList that has the same states and colors as this
+ * one but where each color has the specified perceived luminosity value (0-100).
+ *
+ * @param lStar Target perceptual luminance (0-100).
+ * @return A new color state list.
+ */
+ @NonNull
+ public ColorStateList withLStar(float lStar) {
+ final int[] colors = new int[mColors.length];
+ final int len = colors.length;
+ for (int i = 0; i < len; i++) {
+ colors[i] = modulateColor(mColors[i], 1.0f /* alphaMod */, lStar);
+ }
+
+ return new ColorStateList(mStateSpecs, colors);
+ }
+
+ /**
* Fill in this object based on the contents of an XML "selector" element.
*/
private void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
@@ -332,6 +364,7 @@
final int[] themeAttrs = a.extractThemeAttrs();
final int baseColor = a.getColor(R.styleable.ColorStateListItem_color, Color.MAGENTA);
final float alphaMod = a.getFloat(R.styleable.ColorStateListItem_alpha, 1.0f);
+ final float lStar = a.getFloat(R.styleable.ColorStateListItem_lStar, -1.0f);
changingConfigurations |= a.getChangingConfigurations();
@@ -346,6 +379,7 @@
switch (stateResId) {
case R.attr.color:
case R.attr.alpha:
+ case R.attr.lStar:
// Recognized attribute, ignore.
break;
default:
@@ -355,10 +389,11 @@
}
stateSpec = StateSet.trimStateSet(stateSpec, j);
- // Apply alpha modulation. If we couldn't resolve the color or
+ // Apply alpha and luma modulation. If we couldn't resolve the color or
// alpha yet, the default values leave us enough information to
// modulate again during applyTheme().
- final int color = modulateColorAlpha(baseColor, alphaMod);
+ final int color = modulateColor(baseColor, alphaMod, lStar);
+
if (listSize == 0 || stateSpec.length == 0) {
defaultColor = color;
}
@@ -455,7 +490,9 @@
R.styleable.ColorStateListItem_color, mColors[i]);
final float alphaMod = a.getFloat(
R.styleable.ColorStateListItem_alpha, defaultAlphaMod);
- mColors[i] = modulateColorAlpha(baseColor, alphaMod);
+ final float lStar = a.getFloat(
+ R.styleable.ColorStateListItem_lStar, -1.0f);
+ mColors[i] = modulateColor(baseColor, alphaMod, lStar);
// Account for any configuration changes.
mChangingConfigurations |= a.getChangingConfigurations();
@@ -505,13 +542,21 @@
return super.getChangingConfigurations() | mChangingConfigurations;
}
- private int modulateColorAlpha(int baseColor, float alphaMod) {
- if (alphaMod == 1.0f) {
+ private int modulateColor(int baseColor, float alphaMod, float lStar) {
+ final boolean validLStar = lStar >= 0.0f && lStar <= 100.0f;
+ if (alphaMod == 1.0f && !validLStar) {
return baseColor;
}
final int baseAlpha = Color.alpha(baseColor);
final int alpha = MathUtils.constrain((int) (baseAlpha * alphaMod + 0.5f), 0, 255);
+
+ if (validLStar) {
+ final double[] labColor = new double[3];
+ ColorUtils.colorToLAB(baseColor, labColor);
+ baseColor = ColorUtils.LABToColor(lStar, labColor[1], labColor[2]);
+ }
+
return (baseColor & 0xFFFFFF) | (alpha << 24);
}
diff --git a/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java b/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
index 8c7695a..fbc951e 100644
--- a/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
+++ b/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
@@ -16,6 +16,7 @@
package android.graphics.fonts;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
@@ -213,6 +214,16 @@
public List<FontVariationAxis> getAxes() {
return mAxes;
}
+
+ /**
+ * Returns the index of collection
+ *
+ * TODO(183752879): Make font index configurable and make this SystemApi.
+ * @hide
+ */
+ public @IntRange(from = 0) int getIndex() {
+ return 0;
+ }
}
/**
diff --git a/core/java/android/graphics/fonts/FontUpdateRequest.java b/core/java/android/graphics/fonts/FontUpdateRequest.java
index b79c8f62..4dd5a72 100644
--- a/core/java/android/graphics/fonts/FontUpdateRequest.java
+++ b/core/java/android/graphics/fonts/FontUpdateRequest.java
@@ -17,19 +17,24 @@
package android.graphics.fonts;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.LocaleList;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.text.FontConfig;
+import android.util.TypedXmlSerializer;
-import java.io.File;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Represents a font update request. Currently only font install request is supported.
@@ -47,6 +52,273 @@
@Retention(RetentionPolicy.SOURCE)
public @interface Type {}
+ /**
+ * Font object used for update.
+ *
+ * Here is an example of Family/Font XML.
+ * <family name="my-sans">
+ * <font name="MySans" weight="400" slant="0" axis="'wght' 400 'ital' 0" index="0" />
+ * <font name="MySans" weight="400" slant="0" axis="'wght' 400 'ital' 1" index="0" />
+ * <font name="MySans" weight="400" slant="0" axis="'wght' 700 'ital' 0" index="0" />
+ * <font name="MySans" weight="400" slant="0" axis="'wght' 700 'ital' 1" index="0" />
+ * </family>
+ *
+ * @see Font#readFromXml(XmlPullParser)
+ * @see Font#writeToXml(TypedXmlSerializer, Font)
+ * @see Family#readFromXml(XmlPullParser)
+ * @see Family#writeFamilyToXml(TypedXmlSerializer, Family)
+ */
+ public static final class Font implements Parcelable {
+ private static final String ATTR_INDEX = "index";
+ private static final String ATTR_WEIGHT = "weight";
+ private static final String ATTR_SLANT = "slant";
+ private static final String ATTR_AXIS = "axis";
+ private static final String ATTR_POSTSCRIPT_NAME = "name";
+
+ private final @NonNull String mPostScriptName;
+ private final @NonNull FontStyle mFontStyle;
+ private final @IntRange(from = 0) int mIndex;
+ private final @NonNull String mFontVariationSettings;
+
+ public Font(@NonNull String postScriptName, @NonNull FontStyle fontStyle,
+ @IntRange(from = 0) int index, @NonNull String fontVariationSettings) {
+ mPostScriptName = postScriptName;
+ mFontStyle = fontStyle;
+ mIndex = index;
+ mFontVariationSettings = fontVariationSettings;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString8(mPostScriptName);
+ dest.writeInt(mFontStyle.getWeight());
+ dest.writeInt(mFontStyle.getSlant());
+ dest.writeInt(mIndex);
+ dest.writeString8(mFontVariationSettings);
+ }
+
+ public static final @NonNull Creator<Font> CREATOR = new Creator<Font>() {
+ @Override
+ public Font createFromParcel(Parcel source) {
+ String fontName = source.readString8();
+ int weight = source.readInt();
+ int slant = source.readInt();
+ int index = source.readInt();
+ String varSettings = source.readString8();
+ return new Font(fontName, new FontStyle(weight, slant), index, varSettings);
+ }
+
+ @Override
+ public Font[] newArray(int size) {
+ return new Font[size];
+ }
+ };
+
+ /**
+ * Write {@link Font} instance to XML file.
+ *
+ * For the XML format, see {@link Font} class comment.
+ *
+ * @param out output XML serializer
+ * @param font a Font instance to be written.
+ */
+ public static void writeToXml(TypedXmlSerializer out, Font font) throws IOException {
+ out.attribute(null, ATTR_POSTSCRIPT_NAME, font.getPostScriptName());
+ out.attributeInt(null, ATTR_INDEX, font.getIndex());
+ out.attributeInt(null, ATTR_WEIGHT, font.getFontStyle().getWeight());
+ out.attributeInt(null, ATTR_SLANT, font.getFontStyle().getSlant());
+ out.attribute(null, ATTR_AXIS, font.getFontVariationSettings());
+ }
+
+ /**
+ * Read {@link Font} instance from <font> element in XML
+ *
+ * For the XML format, see {@link Font} class comment.
+ *
+ * @param parser a parser that point <font> element.
+ * @return a font instance
+ * @throws IOException if font element is invalid.
+ */
+ public static Font readFromXml(XmlPullParser parser) throws IOException {
+ String psName = parser.getAttributeValue(null, ATTR_POSTSCRIPT_NAME);
+ if (psName == null) {
+ throw new IOException("name attribute is missing font tag.");
+ }
+ int index = getAttributeValueInt(parser, ATTR_INDEX, 0);
+ int weight = getAttributeValueInt(parser, ATTR_WEIGHT, FontStyle.FONT_WEIGHT_NORMAL);
+ int slant = getAttributeValueInt(parser, ATTR_SLANT, FontStyle.FONT_SLANT_UPRIGHT);
+ String varSettings = parser.getAttributeValue(null, ATTR_AXIS);
+ if (varSettings == null) {
+ varSettings = "";
+ }
+ return new Font(psName, new FontStyle(weight, slant), index, varSettings);
+ }
+
+ public @NonNull String getPostScriptName() {
+ return mPostScriptName;
+ }
+
+ public @NonNull FontStyle getFontStyle() {
+ return mFontStyle;
+ }
+
+ public @IntRange(from = 0) int getIndex() {
+ return mIndex;
+ }
+
+ public @NonNull String getFontVariationSettings() {
+ return mFontVariationSettings;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Font font = (Font) o;
+ return mIndex == font.mIndex
+ && mPostScriptName.equals(font.mPostScriptName)
+ && mFontStyle.equals(font.mFontStyle)
+ && mFontVariationSettings.equals(font.mFontVariationSettings);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPostScriptName, mFontStyle, mIndex, mFontVariationSettings);
+ }
+
+ @Override
+ public String toString() {
+ return "Font{"
+ + "mPostScriptName='" + mPostScriptName + '\''
+ + ", mFontStyle=" + mFontStyle
+ + ", mIndex=" + mIndex
+ + ", mFontVariationSettings='" + mFontVariationSettings + '\''
+ + '}';
+ }
+ }
+
+ /**
+ * Font Family object used for update request.
+ */
+ public static final class Family implements Parcelable {
+ private static final String TAG_FAMILY = "family";
+ private static final String ATTR_NAME = "name";
+ private static final String TAG_FONT = "font";
+
+ private final @Nullable String mName;
+ private final @NonNull List<Font> mFonts;
+
+ public Family(String name, List<Font> fonts) {
+ mName = name;
+ mFonts = fonts;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString8(mName);
+ dest.writeParcelableList(mFonts, flags);
+ }
+
+ public static final @NonNull Creator<Family> CREATOR = new Creator<Family>() {
+
+ @Override
+ public Family createFromParcel(Parcel source) {
+ String familyName = source.readString8();
+ List<Font> fonts = source.readParcelableList(
+ new ArrayList<>(), Font.class.getClassLoader());
+ return new Family(familyName, fonts);
+ }
+
+ @Override
+ public Family[] newArray(int size) {
+ return new Family[size];
+ }
+ };
+
+ /**
+ * Write {@link Family} instance to XML.
+ *
+ * For the XML format, see {@link Font} class comment.
+ *
+ * @param out an output XML serializer
+ * @param family a {@link Family} instance to be written
+ */
+ public static void writeFamilyToXml(@NonNull TypedXmlSerializer out, @NonNull Family family)
+ throws IOException {
+ out.attribute(null, ATTR_NAME, family.getName());
+ List<Font> fonts = family.getFonts();
+ for (int i = 0; i < fonts.size(); ++i) {
+ Font font = fonts.get(i);
+ out.startTag(null, TAG_FONT);
+ Font.writeToXml(out, font);
+ out.endTag(null, TAG_FONT);
+ }
+ }
+
+ /**
+ * Read a {@link Family} instance from <family> element in XML
+ *
+ * For the XML format, see {@link Font} class comment.
+ *
+ * @param parser an XML parser that points <family> element.
+ * @return an {@link Family} instance
+ */
+ public static @NonNull Family readFromXml(@NonNull XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ List<Font> fonts = new ArrayList<>();
+ if (parser.getEventType() != XmlPullParser.START_TAG
+ || !parser.getName().equals(TAG_FAMILY)) {
+ throw new IOException("Unexpected parser state: must be START_TAG with family");
+ }
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ int type = 0;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_FONT)) {
+ fonts.add(Font.readFromXml(parser));
+ } else if (type == XmlPullParser.END_TAG && parser.getName().equals(TAG_FAMILY)) {
+ break;
+ }
+ }
+ return new Family(name, fonts);
+ }
+
+ public @NonNull String getName() {
+ return mName;
+ }
+
+ public @NonNull List<Font> getFonts() {
+ return mFonts;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Family family = (Family) o;
+ return mName.equals(family.mName) && mFonts.equals(family.mFonts);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mName, mFonts);
+ }
+
+ @Override
+ public String toString() {
+ return "Family{mName='" + mName + '\'' + ", mFonts=" + mFonts + '}';
+ }
+ }
+
public static final Creator<FontUpdateRequest> CREATOR = new Creator<FontUpdateRequest>() {
@Override
public FontUpdateRequest createFromParcel(Parcel in) {
@@ -68,7 +340,7 @@
private final byte[] mSignature;
// NonNull if mType == TYPE_UPDATE_FONT_FAMILY.
@Nullable
- private final FontConfig.FontFamily mFontFamily;
+ private final Family mFontFamily;
public FontUpdateRequest(@NonNull ParcelFileDescriptor fd, @NonNull byte[] signature) {
mType = TYPE_UPDATE_FONT_FILE;
@@ -77,31 +349,29 @@
mFontFamily = null;
}
- public FontUpdateRequest(@NonNull FontConfig.FontFamily fontFamily) {
+ public FontUpdateRequest(@NonNull Family fontFamily) {
mType = TYPE_UPDATE_FONT_FAMILY;
mFd = null;
mSignature = null;
mFontFamily = fontFamily;
}
- public FontUpdateRequest(@NonNull String postScriptName,
+ public FontUpdateRequest(@NonNull String familyName,
@NonNull List<FontFamilyUpdateRequest.Font> variations) {
- // TODO: Serialize the request directly instead of reusing FontConfig.FontFamily.
- this(createFontFamily(postScriptName, variations));
+ this(createFontFamily(familyName, variations));
}
- private static FontConfig.FontFamily createFontFamily(@NonNull String postScriptName,
+ private static Family createFontFamily(@NonNull String familyName,
@NonNull List<FontFamilyUpdateRequest.Font> fonts) {
- List<FontConfig.Font> configFonts = new ArrayList<>(fonts.size());
+ List<Font> updateFonts = new ArrayList<>(fonts.size());
for (FontFamilyUpdateRequest.Font font : fonts) {
- // TODO: Support .otf.
- configFonts.add(new FontConfig.Font(new File(font.getPostScriptName() + ".ttf"), null,
- font.getStyle(), 0 /* index */,
- FontVariationAxis.toFontVariationSettings(font.getAxes()),
- null /* fontFamilyName */));
+ updateFonts.add(new Font(
+ font.getPostScriptName(),
+ font.getStyle(),
+ font.getIndex(),
+ FontVariationAxis.toFontVariationSettings(font.getAxes())));
}
- return new FontConfig.FontFamily(configFonts, postScriptName,
- LocaleList.getEmptyLocaleList(), FontConfig.FontFamily.VARIANT_DEFAULT);
+ return new Family(familyName, updateFonts);
}
protected FontUpdateRequest(Parcel in) {
@@ -126,7 +396,7 @@
}
@Nullable
- public FontConfig.FontFamily getFontFamily() {
+ public Family getFontFamily() {
return mFontFamily;
}
@@ -142,4 +412,17 @@
dest.writeBlob(mSignature);
dest.writeParcelable(mFontFamily, flags);
}
+
+ // Utility functions
+ private static int getAttributeValueInt(XmlPullParser parser, String name, int defaultValue) {
+ try {
+ String value = parser.getAttributeValue(null, name);
+ if (value == null) {
+ return defaultValue;
+ }
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
}
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index e03c1f4..d30848f 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -22,6 +22,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.annotation.UserIdInt;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -229,7 +230,25 @@
@RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public void addSensorPrivacyListener(@Sensors.Sensor int sensor,
@NonNull OnSensorPrivacyChangedListener listener) {
- addSensorPrivacyListener(sensor, mContext.getMainExecutor(), listener);
+ addSensorPrivacyListener(sensor, mContext.getUserId(), mContext.getMainExecutor(),
+ listener);
+ }
+
+ /**
+ * Registers a new listener to receive notification when the state of sensor privacy
+ * changes.
+ *
+ * @param sensor the sensor to listen to changes to
+ * @param userId the user's id
+ * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
+ * privacy changes.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+ public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @UserIdInt int userId,
+ @NonNull OnSensorPrivacyChangedListener listener) {
+ addSensorPrivacyListener(sensor, userId, mContext.getMainExecutor(), listener);
}
/**
@@ -248,6 +267,24 @@
@RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor,
@NonNull OnSensorPrivacyChangedListener listener) {
+ addSensorPrivacyListener(sensor, mContext.getUserId(), executor, listener);
+ }
+
+ /**
+ * Registers a new listener to receive notification when the state of sensor privacy
+ * changes.
+ *
+ * @param sensor the sensor to listen to changes to
+ * @param executor the executor to dispatch the callback on
+ * @param userId the user's id
+ * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
+ * privacy changes.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+ public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @UserIdInt int userId,
+ @NonNull Executor executor, @NonNull OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) {
ISensorPrivacyListener iListener = mListeners.get(listener);
if (iListener == null) {
@@ -261,7 +298,7 @@
}
try {
- mService.addIndividualSensorPrivacyListener(mContext.getUserId(), sensor,
+ mService.addIndividualSensorPrivacyListener(userId, sensor,
iListener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -322,8 +359,20 @@
@TestApi
@RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) {
+ return isSensorPrivacyEnabled(sensor, mContext.getUserId());
+ }
+
+ /**
+ * Returns whether sensor privacy is currently enabled for a specific sensor.
+ *
+ * @return true if sensor privacy is currently enabled, false otherwise.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+ public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor, @UserIdInt int userId) {
try {
- return mService.isIndividualSensorPrivacyEnabled(mContext.getUserId(), sensor);
+ return mService.isIndividualSensorPrivacyEnabled(userId, sensor);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -340,8 +389,23 @@
@TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setSensorPrivacy(@Sensors.Sensor int sensor, boolean enable) {
+ setSensorPrivacy(sensor, enable, mContext.getUserId());
+ }
+
+ /**
+ * Sets sensor privacy to the specified state for an individual sensor.
+ *
+ * @param sensor the sensor which to change the state for
+ * @param enable the state to which sensor privacy should be set.
+ * @param userId the user's id
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
+ public void setSensorPrivacy(@Sensors.Sensor int sensor, boolean enable,
+ @UserIdInt int userId) {
try {
- mService.setIndividualSensorPrivacy(mContext.getUserId(), sensor, enable);
+ mService.setIndividualSensorPrivacy(userId, sensor, enable);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -360,8 +424,24 @@
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setSensorPrivacyForProfileGroup(@Sensors.Sensor int sensor,
boolean enable) {
+ setSensorPrivacyForProfileGroup(sensor, enable, mContext.getUserId());
+ }
+
+ /**
+ * Sets sensor privacy to the specified state for an individual sensor for the profile group of
+ * context's user.
+ *
+ * @param sensor the sensor which to change the state for
+ * @param enable the state to which sensor privacy should be set.
+ * @param userId the user's id
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
+ public void setSensorPrivacyForProfileGroup(@Sensors.Sensor int sensor,
+ boolean enable, @UserIdInt int userId) {
try {
- mService.setIndividualSensorPrivacyForProfileGroup(mContext.getUserId(), sensor,
+ mService.setIndividualSensorPrivacyForProfileGroup(userId, sensor,
enable);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -379,8 +459,23 @@
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void suppressSensorPrivacyReminders(@NonNull String packageName,
boolean suppress) {
+ suppressSensorPrivacyReminders(packageName, suppress, mContext.getUserId());
+ }
+
+ /**
+ * Don't show dialogs to turn off sensor privacy for this package.
+ *
+ * @param packageName Package name not to show dialogs for
+ * @param suppress Whether to suppress or re-enable.
+ * @param userId the user's id
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
+ public void suppressSensorPrivacyReminders(@NonNull String packageName,
+ boolean suppress, @UserIdInt int userId) {
try {
- mService.suppressIndividualSensorPrivacyReminders(mContext.getUserId(), packageName,
+ mService.suppressIndividualSensorPrivacyReminders(userId, packageName,
token, suppress);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 0dc612f..6c2d140 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -38,6 +38,7 @@
import android.os.Build;
import android.os.Handler;
import android.util.Pair;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.Surface;
@@ -348,6 +349,37 @@
/** @hide */
+ @IntDef(prefix = {"MATCH_CONTENT_FRAMERATE_"}, value = {
+ MATCH_CONTENT_FRAMERATE_UNKNOWN,
+ MATCH_CONTENT_FRAMERATE_NEVER,
+ MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY,
+ MATCH_CONTENT_FRAMERATE_ALWAYS,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MatchContentFrameRateType {}
+
+ /**
+ * Match content frame rate user preference is unknown.
+ */
+ public static final int MATCH_CONTENT_FRAMERATE_UNKNOWN = -1;
+
+ /**
+ * No mode switching is allowed.
+ */
+ public static final int MATCH_CONTENT_FRAMERATE_NEVER = 0;
+
+ /**
+ * Only refresh rate switches without visual interruptions are allowed.
+ */
+ public static final int MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY = 1;
+
+ /**
+ * Refresh rate switches between all refresh rates are allowed even if they have visual
+ * interruptions for the user.
+ */
+ public static final int MATCH_CONTENT_FRAMERATE_ALWAYS = 2;
+
+ /** @hide */
@IntDef(prefix = {"SWITCHING_TYPE_"}, value = {
SWITCHING_TYPE_NONE,
SWITCHING_TYPE_WITHIN_GROUPS,
@@ -749,6 +781,17 @@
}
/**
+ * Returns the HDR formats disabled by the user.
+ *
+ * @hide
+ */
+ @TestApi
+ public @NonNull int[] getUserDisabledHdrTypes() {
+ return mGlobal.getUserDisabledHdrTypes();
+ }
+
+
+ /**
* Creates a virtual display.
*
* @see #createVirtualDisplay(String, int, int, int, Surface, int,
@@ -1065,14 +1108,36 @@
}
/**
- * Returns the refresh rate switching type.
- *
- * @hide
+ * Returns the user preference for "Match content frame rate".
+ * <p>
+ * Never: Even if the app requests it, the device will never try to match its output to the
+ * original frame rate of the content.
+ * </p><p>
+ * Seamless: If the app requests it, the device will match its output to the original frame
+ * rate of the content, ONLY if the display can transition seamlessly.
+ * </p><p>
+ * Always: If the app requests it, the device will match its output to the original
+ * frame rate of the content. This may cause the screen to go blank for a
+ * second when exiting or entering a video playback.
+ * </p>
*/
- @TestApi
- @RequiresPermission(Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE)
- @SwitchingType public int getRefreshRateSwitchingType() {
- return mGlobal.getRefreshRateSwitchingType();
+ @MatchContentFrameRateType public int getMatchContentFrameRateUserPreference() {
+ return toMatchContentFrameRateSetting(mGlobal.getRefreshRateSwitchingType());
+ }
+
+ @MatchContentFrameRateType
+ private int toMatchContentFrameRateSetting(@SwitchingType int switchingType) {
+ switch (switchingType) {
+ case SWITCHING_TYPE_NONE:
+ return MATCH_CONTENT_FRAMERATE_NEVER;
+ case SWITCHING_TYPE_WITHIN_GROUPS:
+ return MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY;
+ case SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS:
+ return MATCH_CONTENT_FRAMERATE_ALWAYS;
+ default:
+ Slog.e(TAG, switchingType + " is not a valid value of switching type.");
+ return MATCH_CONTENT_FRAMERATE_UNKNOWN;
+ }
}
/**
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index da3a76f..cdc219a 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -551,6 +551,18 @@
}
}
+ /**
+ * Returns the HDR formats disabled by the user.
+ *
+ */
+ public int[] getUserDisabledHdrTypes() {
+ try {
+ return mDm.getUserDisabledHdrTypes();
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
public void requestColorMode(int displayId, int colorMode) {
try {
mDm.requestColorMode(displayId, colorMode);
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 519b86e..5ca4e0c 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -77,6 +77,9 @@
// No permissions required.
boolean areUserDisabledHdrTypesAllowed();
+ // No permissions required.
+ int[] getUserDisabledHdrTypes();
+
// Requires CONFIGURE_DISPLAY_COLOR_MODE
void requestColorMode(int displayId, int colorMode);
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 8dc8d5b..13e2700 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -1059,7 +1059,7 @@
*
* @param face The face template that was removed.
*/
- public void onRemovalSucceeded(Face face, int remaining) {
+ public void onRemovalSucceeded(@Nullable Face face, int remaining) {
}
}
@@ -1258,10 +1258,6 @@
if (mRemovalCallback == null) {
return;
}
- if (face == null) {
- Slog.e(TAG, "Received MSG_REMOVED, but face is null");
- return;
- }
mRemovalCallback.onRemovalSucceeded(face, remaining);
}
diff --git a/core/java/android/hardware/face/FaceServiceReceiver.java b/core/java/android/hardware/face/FaceServiceReceiver.java
new file mode 100644
index 0000000..f0f975d
--- /dev/null
+++ b/core/java/android/hardware/face/FaceServiceReceiver.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.face;
+
+import android.os.RemoteException;
+
+/**
+ * Provides default methods for callers who only need a subset of the functionality.
+ * @hide
+ */
+public class FaceServiceReceiver extends IFaceServiceReceiver.Stub {
+ @Override
+ public void onEnrollResult(Face face, int remaining) throws RemoteException {
+
+ }
+
+ @Override
+ public void onAcquired(int acquiredInfo, int vendorCode) throws RemoteException {
+
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(Face face, int userId, boolean isStrongBiometric)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onFaceDetected(int sensorId, int userId, boolean isStrongBiometric)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onAuthenticationFailed() throws RemoteException {
+
+ }
+
+ @Override
+ public void onError(int error, int vendorCode) throws RemoteException {
+
+ }
+
+ @Override
+ public void onRemoved(Face face, int remaining) throws RemoteException {
+
+ }
+
+ @Override
+ public void onFeatureSet(boolean success, int feature) throws RemoteException {
+
+ }
+
+ @Override
+ public void onFeatureGet(boolean success, int feature, boolean value) throws RemoteException {
+
+ }
+
+ @Override
+ public void onChallengeGenerated(int sensorId, long challenge) throws RemoteException {
+
+ }
+
+ @Override
+ public void onChallengeInterrupted(int sensorId) throws RemoteException {
+
+ }
+
+ @Override
+ public void onChallengeInterruptFinished(int sensorId) throws RemoteException {
+
+ }
+
+ @Override
+ public void onAuthenticationFrame(FaceAuthenticationFrame frame) throws RemoteException {
+
+ }
+
+ @Override
+ public void onEnrollmentFrame(FaceEnrollFrame frame) throws RemoteException {
+
+ }
+}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 1c33b26..7b6e129 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -452,7 +452,7 @@
* {@link #remove} is called on a group, this should be the number of remaining
* fingerprints in the group, and 0 after the last fingerprint is removed.
*/
- public void onRemovalSucceeded(Fingerprint fp, int remaining) { }
+ public void onRemovalSucceeded(@Nullable Fingerprint fp, int remaining) { }
}
/**
diff --git a/core/java/android/hardware/fingerprint/FingerprintServiceReceiver.java b/core/java/android/hardware/fingerprint/FingerprintServiceReceiver.java
new file mode 100644
index 0000000..798e87b
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/FingerprintServiceReceiver.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fingerprint;
+
+import android.os.RemoteException;
+
+/**
+ * Provides default methods for callers who only need a subset of the functionality.
+ * @hide
+ */
+public class FingerprintServiceReceiver extends IFingerprintServiceReceiver.Stub {
+ @Override
+ public void onEnrollResult(Fingerprint fp, int remaining) throws RemoteException {
+
+ }
+
+ @Override
+ public void onAcquired(int acquiredInfo, int vendorCode) throws RemoteException {
+
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(Fingerprint fp, int userId, boolean isStrongBiometric)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onAuthenticationFailed() throws RemoteException {
+
+ }
+
+ @Override
+ public void onError(int error, int vendorCode) throws RemoteException {
+
+ }
+
+ @Override
+ public void onRemoved(Fingerprint fp, int remaining) throws RemoteException {
+
+ }
+
+ @Override
+ public void onChallengeGenerated(int sensorId, long challenge) throws RemoteException {
+
+ }
+
+ @Override
+ public void onUdfpsPointerDown(int sensorId) throws RemoteException {
+
+ }
+
+ @Override
+ public void onUdfpsPointerUp(int sensorId) throws RemoteException {
+
+ }
+}
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 5cfcd66..9198eb7 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -171,7 +171,7 @@
SomeArgs args = (SomeArgs) msg.obj;
try {
inputMethod.initializeInternal((IBinder) args.arg1, msg.arg1,
- (IInputMethodPrivilegedOperations) args.arg2);
+ (IInputMethodPrivilegedOperations) args.arg2, (int) args.arg3);
} finally {
args.recycle();
}
@@ -280,9 +280,10 @@
@BinderThread
@Override
public void initializeInternal(IBinder token, int displayId,
- IInputMethodPrivilegedOperations privOps) {
+ IInputMethodPrivilegedOperations privOps, int configChanges) {
mCaller.executeOrSendMessage(
- mCaller.obtainMessageIOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps));
+ mCaller.obtainMessageIOOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps,
+ configChanges));
}
@BinderThread
diff --git a/core/java/android/inputmethodservice/ImsConfigurationTracker.java b/core/java/android/inputmethodservice/ImsConfigurationTracker.java
new file mode 100644
index 0000000..3c78888
--- /dev/null
+++ b/core/java/android/inputmethodservice/ImsConfigurationTracker.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.inputmethodservice;
+
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+/**
+ * Helper class that takes care of Configuration change behavior of {@link InputMethodService}.
+ * Note: this class is public for testing only. Never call any of it's methods for development
+ * of IMEs.
+ * @hide
+ */
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public final class ImsConfigurationTracker {
+
+ /**
+ * A constant value that represents {@link Configuration} has changed from the last time
+ * {@link InputMethodService#onConfigurationChanged(Configuration)} was called.
+ */
+ private static final int CONFIG_CHANGED = -1;
+
+ @Nullable
+ private Configuration mLastKnownConfig = null;
+ private int mHandledConfigChanges = 0;
+ private boolean mInitialized = false;
+
+ /**
+ * Called from {@link InputMethodService.InputMethodImpl
+ * #initializeInternal(IBinder, int, IInputMethodPrivilegedOperations, int)} ()}
+ * @param handledConfigChanges Configuration changes declared handled by IME
+ * {@link android.R.styleable#InputMethod_configChanges}.
+ */
+ @MainThread
+ public void onInitialize(int handledConfigChanges) {
+ Preconditions.checkState(!mInitialized, "onInitialize can be called only once.");
+ mInitialized = true;
+ mHandledConfigChanges = handledConfigChanges;
+ }
+
+ /**
+ * Called from {@link InputMethodService.InputMethodImpl#onBindInput()}
+ */
+ @MainThread
+ public void onBindInput(@Nullable Resources resources) {
+ Preconditions.checkState(mInitialized,
+ "onBindInput can be called only after onInitialize().");
+ if (mLastKnownConfig == null && resources != null) {
+ mLastKnownConfig = new Configuration(resources.getConfiguration());
+ }
+ }
+
+ /**
+ * Dynamically set handled configChanges.
+ * Note: this method is public for testing only.
+ */
+ public void setHandledConfigChanges(int configChanges) {
+ mHandledConfigChanges = configChanges;
+ }
+
+ /**
+ * Called from {@link InputMethodService.InputMethodImpl#onConfigurationChanged(Configuration)}}
+ */
+ @MainThread
+ public void onConfigurationChanged(@NonNull Configuration newConfig,
+ @NonNull Runnable resetStateForNewConfigurationRunner) {
+ if (!mInitialized) {
+ return;
+ }
+ final int diff = mLastKnownConfig != null
+ ? mLastKnownConfig.diffPublicOnly(newConfig) : CONFIG_CHANGED;
+ // If the new config is the same as the config this Service is already running with,
+ // then don't bother calling resetStateForNewConfiguration.
+ final int unhandledDiff = (diff & ~mHandledConfigChanges);
+ if (unhandledDiff != 0) {
+ resetStateForNewConfigurationRunner.run();
+ }
+ if (diff != 0) {
+ mLastKnownConfig = new Configuration(newConfig);
+ }
+ }
+}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 7e2be01..4ee5383 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -513,6 +513,7 @@
private boolean mIsAutomotive;
private Handler mHandler;
private boolean mImeSurfaceScheduledForRemoval;
+ private ImsConfigurationTracker mConfigTracker = new ImsConfigurationTracker();
/**
* An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput}
@@ -588,12 +589,13 @@
@MainThread
@Override
public final void initializeInternal(@NonNull IBinder token, int displayId,
- IInputMethodPrivilegedOperations privilegedOperations) {
+ IInputMethodPrivilegedOperations privilegedOperations, int configChanges) {
if (InputMethodPrivilegedOperationsRegistry.isRegistered(token)) {
Log.w(TAG, "The token has already registered, ignore this initialization.");
return;
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initializeInternal");
+ mConfigTracker.onInitialize(configChanges);
mPrivOps.set(privilegedOperations);
InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps);
updateInputMethodDisplay(displayId);
@@ -663,6 +665,7 @@
reportFullscreenMode();
initialize();
onBindInput();
+ mConfigTracker.onBindInput(getResources());
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -938,7 +941,7 @@
}
private void setImeWindowStatus(int visibilityFlags, int backDisposition) {
- mPrivOps.setImeWindowStatus(visibilityFlags, backDisposition);
+ mPrivOps.setImeWindowStatusAsync(visibilityFlags, backDisposition);
}
/** Set region of the keyboard to be avoided from back gesture */
@@ -1428,10 +1431,13 @@
* state: {@link #onStartInput} if input is active, and
* {@link #onCreateInputView} and {@link #onStartInputView} and related
* appropriate functions if the UI is displayed.
+ * <p>Starting with {@link Build.VERSION_CODES#S}, IMEs can opt into handling configuration
+ * changes themselves instead of being restarted with
+ * {@link android.R.styleable#InputMethod_configChanges}.
*/
@Override public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- resetStateForNewConfiguration();
+ mConfigTracker.onConfigurationChanged(newConfig, this::resetStateForNewConfiguration);
}
private void resetStateForNewConfiguration() {
@@ -3181,7 +3187,7 @@
requestHideSelf(InputMethodManager.HIDE_NOT_ALWAYS);
}
}
-
+
void startExtractingText(boolean inputChanged) {
final ExtractEditText eet = mExtractEditText;
if (eet != null && getCurrentInputStarted()
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index b202420..68606ec 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -18,8 +18,6 @@
import static android.app.ActivityManager.procStateToString;
import static android.content.pm.PackageManager.GET_SIGNATURES;
-import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
-import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -174,7 +172,7 @@
/** @hide */
public static final int FOREGROUND_THRESHOLD_STATE =
- ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+ ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
/**
* {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
@@ -787,36 +785,6 @@
}
/**
- * Returns whether network access of an UID is blocked or not based on {@code blockedReasons}
- * corresponding to it.
- *
- * {@code blockedReasons} would be a bitwise {@code OR} combination of the
- * {@code BLOCKED_REASON_*} and/or {@code BLOCKED_METERED_REASON_*} constants.
- *
- * @param blockedReasons Value indicating the reasons for why the network access of an UID is
- * blocked. If the value is equal to
- * {@link ConnectivityManager#BLOCKED_REASON_NONE}, then
- * it indicates that an app's network access is not blocked.
- * @param meteredNetwork Value indicating whether the network is metered or not.
- * @return Whether network access is blocked or not.
- * @hide
- */
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public static boolean isUidBlocked(int blockedReasons, boolean meteredNetwork) {
- if (blockedReasons == BLOCKED_REASON_NONE) {
- return false;
- }
- final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK);
- if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) {
- return true;
- }
- if (meteredNetwork) {
- return blockedReasons != BLOCKED_REASON_NONE;
- }
- return false;
- }
-
- /**
* Returns the {@code string} representation of {@code blockedReasons} argument.
*
* @param blockedReasons Value indicating the reasons for why the network access of an UID is
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index bc3d5c4..11445e9 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -72,7 +72,7 @@
boolean deviceSupportsNfcSecure();
boolean setNfcSecure(boolean enable);
- boolean setAlwaysOn(boolean value);
- boolean isAlwaysOnEnabled();
- boolean isAlwaysOnSupported();
+ boolean setControllerAlwaysOn(boolean value);
+ boolean isControllerAlwaysOn();
+ boolean isControllerAlwaysOnSupported();
}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index e85eb93..eed2c77 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -2254,13 +2254,13 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
- public boolean setAlwaysOn(boolean value) {
+ @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
+ public boolean setControllerAlwaysOn(boolean value) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
try {
- return sService.setAlwaysOn(value);
+ return sService.setControllerAlwaysOn(value);
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
// Try one more time
@@ -2269,7 +2269,7 @@
return false;
}
try {
- return sService.setAlwaysOn(value);
+ return sService.setControllerAlwaysOn(value);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to recover NFC Service.");
}
@@ -2286,10 +2286,10 @@
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
- public boolean isAlwaysOnEnabled() {
+ @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
+ public boolean isControllerAlwaysOn() {
try {
- return sService.isAlwaysOnEnabled();
+ return sService.isControllerAlwaysOn();
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
// Try one more time
@@ -2298,7 +2298,7 @@
return false;
}
try {
- return sService.isAlwaysOnEnabled();
+ return sService.isControllerAlwaysOn();
} catch (RemoteException ee) {
Log.e(TAG, "Failed to recover NFC Service.");
}
@@ -2315,13 +2315,13 @@
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
- public boolean isAlwaysOnSupported() {
+ @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
+ public boolean isControllerAlwaysOnSupported() {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
try {
- return sService.isAlwaysOnSupported();
+ return sService.isControllerAlwaysOnSupported();
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
// Try one more time
@@ -2330,7 +2330,7 @@
return false;
}
try {
- return sService.isAlwaysOnSupported();
+ return sService.isControllerAlwaysOnSupported();
} catch (RemoteException ee) {
Log.e(TAG, "Failed to recover NFC Service.");
}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index ae7d94c..425e797 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -27,9 +27,9 @@
interface IPowerManager
{
void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws,
- String historyTag);
+ String historyTag, int displayId);
void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName,
- int uidtoblame);
+ int uidtoblame, int displayId);
@UnsupportedAppUsage
void releaseWakeLock(IBinder lock, int flags);
void updateWakeLockUids(IBinder lock, in int[] uids);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 2c4d130..9d1fd50 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -36,6 +36,7 @@
import android.util.ArrayMap;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
+import android.view.Display;
import com.android.internal.util.Preconditions;
@@ -1143,8 +1144,7 @@
* wake lock, and {@link WakeLock#release release()} when you are done.
* </p><p>
* {@samplecode
- * PowerManager pm = (PowerManager)mContext.getSystemService(
- * Context.POWER_SERVICE);
+ * PowerManager pm = mContext.getSystemService(PowerManager.class);
* PowerManager.WakeLock wl = pm.newWakeLock(
* PowerManager.SCREEN_DIM_WAKE_LOCK
* | PowerManager.ON_AFTER_RELEASE,
@@ -1162,6 +1162,8 @@
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
* This window flag will be correctly managed by the platform
* as the user moves between applications and doesn't require a special permission.
+ * Additionally using the flag will keep only the appropriate screen on in a
+ * multi-display scenario while using a wake lock will keep every screen powered on.
* </p>
*
* <p>
@@ -1179,7 +1181,7 @@
* can be transformed by java optimizer and obfuscator tools.
* <li>avoid wrapping the tag or a prefix to avoid collision with wake lock
* tags from the platform (e.g. *alarm*).
- * <li>never include personnally identifiable information for privacy
+ * <li>never include personally identifiable information for privacy
* reasons.
* </ul>
* </p>
@@ -1200,7 +1202,27 @@
*/
public WakeLock newWakeLock(int levelAndFlags, String tag) {
validateWakeLockParameters(levelAndFlags, tag);
- return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
+ return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName(),
+ Display.INVALID_DISPLAY);
+ }
+
+ /**
+ * Creates a new wake lock with the specified level and flags.
+ * <p>
+ * The wakelock will only apply to the {@link com.android.server.display.DisplayGroup} of the
+ * provided {@code displayId}. If {@code displayId} is {@link Display#INVALID_DISPLAY} then it
+ * will apply to all {@link com.android.server.display.DisplayGroup DisplayGroups}.
+ *
+ * @param levelAndFlags Combination of wake lock level and flag values defining
+ * the requested behavior of the WakeLock.
+ * @param tag Your class name (or other tag) for debugging purposes.
+ * @param displayId The display id to which this wake lock is tied.
+ *
+ * @hide
+ */
+ public WakeLock newWakeLock(int levelAndFlags, String tag, int displayId) {
+ validateWakeLockParameters(levelAndFlags, tag);
+ return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName(), displayId);
}
/** @hide */
@@ -2603,19 +2625,17 @@
private WorkSource mWorkSource;
private String mHistoryTag;
private final String mTraceName;
+ private final int mDisplayId;
- private final Runnable mReleaser = new Runnable() {
- public void run() {
- release(RELEASE_FLAG_TIMEOUT);
- }
- };
+ private final Runnable mReleaser = () -> release(RELEASE_FLAG_TIMEOUT);
- WakeLock(int flags, String tag, String packageName) {
+ WakeLock(int flags, String tag, String packageName, int displayId) {
mFlags = flags;
mTag = tag;
mPackageName = packageName;
mToken = new Binder();
mTraceName = "WakeLock (" + mTag + ")";
+ mDisplayId = displayId;
}
@Override
@@ -2696,7 +2716,7 @@
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
try {
mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
- mHistoryTag);
+ mHistoryTag, mDisplayId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index bf859d4..f9e4f73 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -131,6 +131,7 @@
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @TestApi
public static final int NFC_UID = 1027;
/**
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 8c105be..ef075e1 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -16,6 +16,7 @@
package android.permission;
+import android.content.AttributionSource;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
@@ -85,4 +86,8 @@
boolean setAutoRevokeExempted(String packageName, boolean exempted, int userId);
boolean isAutoRevokeExempted(String packageName, int userId);
+
+ AttributionSource registerAttributionSource(in AttributionSource source);
+
+ boolean isRegisteredAttributionSource(in AttributionSource source);
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index baa25f0..936cbfc 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -44,6 +44,7 @@
import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.location.LocationManager;
import android.media.AudioManager;
+import android.content.AttributionSource;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -1099,6 +1100,48 @@
callingFeatureId, pid, uid);
}
+ /**
+ * Registers an attribution source with the OS. An app can only register an attribution
+ * source for itself. Once an attribution source has been registered another app can
+ * check whether this registration exists and thus trust the payload in the source
+ * object. This is important for permission checking and specifically for app op blaming
+ * since a malicious app should not be able to force the OS to blame another app
+ * that doesn't participate in an attribution chain.
+ *
+ * @param source The attribution source to register.
+ *
+ * @see #isRegisteredAttributionSource(AttributionSource)
+ *
+ * @hide
+ */
+ public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) {
+ try {
+ return mPermissionManager.registerAttributionSource(source);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return null;
+ }
+
+ /**
+ * Checks whether an attribution source is registered.
+ *
+ * @param source The attribution source to check.
+ * @return Whether this is a registered source.
+ *
+ * @see #registerAttributionSource(AttributionSource)
+ *
+ * @hide
+ */
+ public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) {
+ try {
+ return mPermissionManager.isRegisteredAttributionSource(source);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return false;
+ }
+
/* @hide */
private static int checkPermissionUncached(@Nullable String permission, int pid, int uid) {
final IActivityManager am = ActivityManager.getService();
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index b704d66..a5a24c0 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -1102,8 +1102,7 @@
// signed with platform signature can hold MANAGE_DOCUMENTS, we are going to check for
// MANAGE_DOCUMENTS or associated URI permission here instead
final Uri rootUri = extraUri;
- enforceWritePermissionInner(rootUri, getCallingPackage(), getCallingAttributionTag(),
- null);
+ enforceWritePermissionInner(rootUri, getCallingAttributionSource());
final String rootId = DocumentsContract.getRootId(rootUri);
ejectRoot(rootId);
@@ -1121,8 +1120,7 @@
}
if (METHOD_IS_CHILD_DOCUMENT.equals(method)) {
- enforceReadPermissionInner(documentUri, getCallingPackage(),
- getCallingAttributionTag(), null);
+ enforceReadPermissionInner(documentUri, getCallingAttributionSource());
final Uri childUri = extraTargetUri;
final String childAuthority = childUri.getAuthority();
@@ -1134,8 +1132,7 @@
&& isChildDocument(documentId, childId));
} else if (METHOD_CREATE_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(),
- getCallingAttributionTag(), null);
+ enforceWritePermissionInner(documentUri, getCallingAttributionSource());
final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
@@ -1149,8 +1146,7 @@
out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
} else if (METHOD_CREATE_WEB_LINK_INTENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(),
- getCallingAttributionTag(), null);
+ enforceWritePermissionInner(documentUri, getCallingAttributionSource());
final Bundle options = extras.getBundle(DocumentsContract.EXTRA_OPTIONS);
final IntentSender intentSender = createWebLinkIntent(documentId, options);
@@ -1158,8 +1154,7 @@
out.putParcelable(DocumentsContract.EXTRA_RESULT, intentSender);
} else if (METHOD_RENAME_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(),
- getCallingAttributionTag(), null);
+ enforceWritePermissionInner(documentUri, getCallingAttributionSource());
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
final String newDocumentId = renameDocument(documentId, displayName);
@@ -1183,8 +1178,7 @@
}
} else if (METHOD_DELETE_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(),
- getCallingAttributionTag(), null);
+ enforceWritePermissionInner(documentUri, getCallingAttributionSource());
deleteDocument(documentId);
// Document no longer exists, clean up any grants.
@@ -1194,10 +1188,8 @@
final Uri targetUri = extraTargetUri;
final String targetId = DocumentsContract.getDocumentId(targetUri);
- enforceReadPermissionInner(documentUri, getCallingPackage(),
- getCallingAttributionTag(), null);
- enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingAttributionTag(),
- null);
+ enforceReadPermissionInner(documentUri, getCallingAttributionSource());
+ enforceWritePermissionInner(targetUri, getCallingAttributionSource());
final String newDocumentId = copyDocument(documentId, targetId);
@@ -1220,12 +1212,9 @@
final Uri targetUri = extraTargetUri;
final String targetId = DocumentsContract.getDocumentId(targetUri);
- enforceWritePermissionInner(documentUri, getCallingPackage(),
- getCallingAttributionTag(), null);
- enforceReadPermissionInner(parentSourceUri, getCallingPackage(),
- getCallingAttributionTag(), null);
- enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingAttributionTag(),
- null);
+ enforceWritePermissionInner(documentUri, getCallingAttributionSource());
+ enforceReadPermissionInner(parentSourceUri, getCallingAttributionSource());
+ enforceWritePermissionInner(targetUri, getCallingAttributionSource());
final String newDocumentId = moveDocument(documentId, parentSourceId, targetId);
@@ -1246,10 +1235,8 @@
final Uri parentSourceUri = extraParentUri;
final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri);
- enforceReadPermissionInner(parentSourceUri, getCallingPackage(),
- getCallingAttributionTag(), null);
- enforceWritePermissionInner(documentUri, getCallingPackage(),
- getCallingAttributionTag(), null);
+ enforceReadPermissionInner(parentSourceUri, getCallingAttributionSource());
+ enforceWritePermissionInner(documentUri, getCallingAttributionSource());
removeDocument(documentId, parentSourceId);
// It's responsibility of the provider to revoke any grants, as the document may be
@@ -1258,8 +1245,7 @@
final boolean isTreeUri = isTreeUri(documentUri);
if (isTreeUri) {
- enforceReadPermissionInner(documentUri, getCallingPackage(),
- getCallingAttributionTag(), null);
+ enforceReadPermissionInner(documentUri, getCallingAttributionSource());
} else {
getContext().enforceCallingPermission(Manifest.permission.MANAGE_DOCUMENTS, null);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5d924cc..22d74ca 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2754,7 +2754,7 @@
arg.putBoolean(CALL_METHOD_OVERRIDEABLE_BY_RESTORE_KEY, true);
}
IContentProvider cp = mProviderHolder.getProvider(cr);
- cp.call(cr.getPackageName(), cr.getAttributionTag(),
+ cp.call(cr.getAttributionSource(),
mProviderHolder.mUri.getAuthority(), mCallSetCommand, name, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't set key " + name + " in " + mUri, e);
@@ -2774,7 +2774,7 @@
args.putString(CALL_METHOD_PREFIX_KEY, prefix);
args.putSerializable(CALL_METHOD_FLAGS_KEY, keyValues);
IContentProvider cp = mProviderHolder.getProvider(cr);
- Bundle bundle = cp.call(cr.getPackageName(), cr.getAttributionTag(),
+ Bundle bundle = cp.call(cr.getAttributionSource(),
mProviderHolder.mUri.getAuthority(),
mCallSetAllCommand, null, args);
return bundle.getBoolean(KEY_CONFIG_SET_RETURN);
@@ -2862,14 +2862,14 @@
if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
final long token = Binder.clearCallingIdentity();
try {
- b = cp.call(cr.getPackageName(), cr.getAttributionTag(),
+ b = cp.call(cr.getAttributionSource(),
mProviderHolder.mUri.getAuthority(), mCallGetCommand, name,
args);
} finally {
Binder.restoreCallingIdentity(token);
}
} else {
- b = cp.call(cr.getPackageName(), cr.getAttributionTag(),
+ b = cp.call(cr.getAttributionSource(),
mProviderHolder.mUri.getAuthority(), mCallGetCommand, name, args);
}
if (b != null) {
@@ -2939,13 +2939,13 @@
if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
final long token = Binder.clearCallingIdentity();
try {
- c = cp.query(cr.getPackageName(), cr.getAttributionTag(), mUri,
+ c = cp.query(cr.getAttributionSource(), mUri,
SELECT_VALUE_PROJECTION, queryArgs, null);
} finally {
Binder.restoreCallingIdentity(token);
}
} else {
- c = cp.query(cr.getPackageName(), cr.getAttributionTag(), mUri,
+ c = cp.query(cr.getAttributionSource(), mUri,
SELECT_VALUE_PROJECTION, queryArgs, null);
}
if (c == null) {
@@ -3051,7 +3051,7 @@
}
// Fetch all flags for the namespace at once for caching purposes
- Bundle b = cp.call(cr.getPackageName(), cr.getAttributionTag(),
+ Bundle b = cp.call(cr.getAttributionSource(),
mProviderHolder.mUri.getAuthority(), mCallListCommand, null, args);
if (b == null) {
// Invalid response, return an empty map
@@ -5877,7 +5877,7 @@
}
arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
+ cp.call(resolver.getAttributionSource(),
sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_SECURE, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
@@ -9176,6 +9176,22 @@
public static final String ASSIST_GESTURE_SETUP_COMPLETE = "assist_gesture_setup_complete";
/**
+ * Whether the assistant can be triggered by a touch gesture.
+ *
+ * @hide
+ */
+ public static final String ASSIST_TOUCH_GESTURE_ENABLED =
+ "assist_touch_gesture_enabled";
+
+ /**
+ * Whether the assistant can be triggered by long-pressing the home button
+ *
+ * @hide
+ */
+ public static final String ASSIST_LONG_PRESS_HOME_ENABLED =
+ "assist_long_press_home_enabled";
+
+ /**
* Control whether Trust Agents are in active unlock or extend unlock mode.
* @hide
*/
@@ -9740,6 +9756,12 @@
"accessibility_magnification_mode";
/**
+ * Magnification mode value that is a default value for the magnification logging feature.
+ * @hide
+ */
+ public static final int ACCESSIBILITY_MAGNIFICATION_MODE_NONE = 0x0;
+
+ /**
* Magnification mode value that magnifies whole display.
* @hide
*/
@@ -14914,7 +14936,7 @@
}
arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
+ cp.call(resolver.getAttributionSource(),
sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_GLOBAL, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
@@ -16053,7 +16075,7 @@
arg.putString(Settings.CALL_METHOD_PREFIX_KEY, createPrefix(namespace));
}
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
+ cp.call(resolver.getAttributionSource(),
sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_CONFIG, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset to defaults for " + DeviceConfig.CONTENT_URI, e);
@@ -16082,7 +16104,7 @@
arg.putInt(CALL_METHOD_USER_KEY, userHandle);
arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, callback);
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
+ cp.call(resolver.getAttributionSource(),
sProviderHolder.mUri.getAuthority(),
CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg);
} catch (RemoteException e) {
diff --git a/core/java/android/provider/TEST_MAPPING b/core/java/android/provider/TEST_MAPPING
index ae2836f..c55572e 100644
--- a/core/java/android/provider/TEST_MAPPING
+++ b/core/java/android/provider/TEST_MAPPING
@@ -19,6 +19,14 @@
},
{
"name": "SettingsProviderTest"
+ },
+ {
+ "name": "CtsAppSecurityHostTestCases",
+ "options": [
+ {
+ "include-filter": "android.appsecurity.cts.ReadableSettingsFieldsTest"
+ }
+ ]
}
]
}
diff --git a/core/java/android/service/displayhash/DisplayHasherService.java b/core/java/android/service/displayhash/DisplayHasherService.java
index 2105d84..d300cf1 100644
--- a/core/java/android/service/displayhash/DisplayHasherService.java
+++ b/core/java/android/service/displayhash/DisplayHasherService.java
@@ -52,6 +52,16 @@
"android.service.displayhash.extra.VERIFIED_DISPLAY_HASH";
/**
+ * Name under which a DisplayHasherService component publishes information
+ * about itself. This meta-data must reference an XML resource containing a
+ * {@link com.android.internal.R.styleable#DisplayHasherService} tag.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String SERVICE_META_DATA = "android.displayhash.display_hasher_service";
+
+ /**
* The {@link Intent} action that must be declared as handled by a service in its manifest
* for the system to recognize it as a DisplayHash providing service.
*
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 73e0da1..8ca0e7c 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -48,6 +48,7 @@
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SharedMemory;
+import android.service.voice.HotwordDetectionService.InitializationStatus;
import android.util.Slog;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
@@ -260,6 +261,7 @@
private static final int MSG_DETECTION_PAUSE = 4;
private static final int MSG_DETECTION_RESUME = 5;
private static final int MSG_HOTWORD_REJECTED = 6;
+ private static final int MSG_HOTWORD_STATUS_REPORTED = 7;
private final String mText;
private final Locale mLocale;
@@ -523,6 +525,15 @@
*/
public void onRejected(@Nullable HotwordRejectedResult result) {
}
+
+ /**
+ * Called when the {@link HotwordDetectionService} is created by the system and given a
+ * short amount of time to report it's initialization state.
+ *
+ * @param status Info about initialization state of {@link HotwordDetectionService}.
+ */
+ public void onHotwordDetectionServiceInitialized(@InitializationStatus int status) {
+ }
}
/**
@@ -559,7 +570,7 @@
mTargetSdkVersion = targetSdkVersion;
mSupportHotwordDetectionService = supportHotwordDetectionService;
if (mSupportHotwordDetectionService) {
- updateState(options, sharedMemory);
+ updateStateLocked(options, sharedMemory, mInternalCallback);
}
try {
Identity identity = new Identity();
@@ -583,20 +594,34 @@
* such data to the trusted process.
*
* @throws IllegalStateException if this AlwaysOnHotwordDetector wasn't specified to use a
- * {@link HotwordDetectionService} when it was created.
+ * {@link HotwordDetectionService} when it was created. In addition, if this
+ * AlwaysOnHotwordDetector is in an invalid or error state.
*/
public final void updateState(@Nullable PersistableBundle options,
@Nullable SharedMemory sharedMemory) {
if (DBG) {
Slog.d(TAG, "updateState()");
}
- if (!mSupportHotwordDetectionService) {
- throw new IllegalStateException(
- "updateState called, but it doesn't support hotword detection service");
+ synchronized (mLock) {
+ if (!mSupportHotwordDetectionService) {
+ throw new IllegalStateException(
+ "updateState called, but it doesn't support hotword detection service");
+ }
+ if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) {
+ throw new IllegalStateException(
+ "updateState called on an invalid detector or error state");
+ }
+ updateStateLocked(options, sharedMemory, null /* callback */);
}
+ }
+ private void updateStateLocked(@Nullable PersistableBundle options,
+ @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
+ if (DBG) {
+ Slog.d(TAG, "updateStateLocked()");
+ }
try {
- mModelManagementService.updateState(options, sharedMemory);
+ mModelManagementService.updateState(options, sharedMemory, callback);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1147,6 +1172,18 @@
Slog.i(TAG, "onRecognitionResumed");
mHandler.sendEmptyMessage(MSG_DETECTION_RESUME);
}
+
+ @Override
+ public void onStatusReported(int status) {
+ if (DBG) {
+ Slog.d(TAG, "onStatusReported(" + status + ")");
+ } else {
+ Slog.i(TAG, "onStatusReported");
+ }
+ Message message = Message.obtain(mHandler, MSG_HOTWORD_STATUS_REPORTED);
+ message.arg1 = status;
+ message.sendToTarget();
+ }
}
class MyHandler extends Handler {
@@ -1178,6 +1215,9 @@
case MSG_HOTWORD_REJECTED:
mExternalCallback.onRejected((HotwordRejectedResult) msg.obj);
break;
+ case MSG_HOTWORD_STATUS_REPORTED:
+ mExternalCallback.onHotwordDetectionServiceInitialized(msg.arg1);
+ break;
default:
super.handleMessage(msg);
}
diff --git a/core/java/android/service/voice/HotwordDetectedResult.java b/core/java/android/service/voice/HotwordDetectedResult.java
index dd6f698..f5d796f 100644
--- a/core/java/android/service/voice/HotwordDetectedResult.java
+++ b/core/java/android/service/voice/HotwordDetectedResult.java
@@ -21,8 +21,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.os.Bundle;
import android.os.Parcelable;
+import android.os.PersistableBundle;
import com.android.internal.util.DataClass;
@@ -92,16 +92,20 @@
}
/**
- * Triggered phrase.
+ * An ID representing the keyphrase that triggered the successful detection.
*
- * <p>This phrase has to be listed in the AndroidManifest of the application in order for
- * trigger to be accepted by the system.
+ * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
*/
- // TODO(b/183128696): allow listing this in the manifest.
- @Nullable
- private final String mHotwordPhrase;
- private static String defaultHotwordPhrase() {
- return null;
+ private final int mHotwordPhraseId;
+ private static int defaultHotwordPhraseId() {
+ return 0;
+ }
+
+ /**
+ * Returns the maximum value of {@link #getHotwordPhraseId()}.
+ */
+ public static int getMaxHotwordPhraseId() {
+ return 63;
}
/**
@@ -115,11 +119,14 @@
*
* <p>The use of this method is discouraged, and support for it will be removed in future
* versions of Android.
+ *
+ * <p>This is a PersistableBundle so it doesn't allow any remotable objects or other contents
+ * that can be used to communicate with other processes.
*/
@NonNull
- private final Bundle mExtras;
- private static Bundle defaultExtras() {
- return new Bundle();
+ private final PersistableBundle mExtras;
+ private static PersistableBundle defaultExtras() {
+ return new PersistableBundle();
}
/**
@@ -136,7 +143,7 @@
- // Code below generated by codegen v1.0.22.
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -155,15 +162,15 @@
int byteOffset,
int score,
int personalizedScore,
- @Nullable String hotwordPhrase,
- @NonNull Bundle extras) {
+ int hotwordPhraseId,
+ @NonNull PersistableBundle extras) {
this.mConfidenceLevel = confidenceLevel;
com.android.internal.util.AnnotationValidations.validate(
HotwordDetector.HotwordConfidenceLevelValue.class, null, mConfidenceLevel);
this.mByteOffset = byteOffset;
this.mScore = score;
this.mPersonalizedScore = personalizedScore;
- this.mHotwordPhrase = hotwordPhrase;
+ this.mHotwordPhraseId = hotwordPhraseId;
this.mExtras = extras;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mExtras);
@@ -209,9 +216,14 @@
return mPersonalizedScore;
}
+ /**
+ * An ID representing the keyphrase that triggered the successful detection.
+ *
+ * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
+ */
@DataClass.Generated.Member
- public @Nullable String getHotwordPhrase() {
- return mHotwordPhrase;
+ public int getHotwordPhraseId() {
+ return mHotwordPhraseId;
}
/**
@@ -227,7 +239,7 @@
* versions of Android.
*/
@DataClass.Generated.Member
- public @NonNull Bundle getExtras() {
+ public @NonNull PersistableBundle getExtras() {
return mExtras;
}
@@ -242,7 +254,7 @@
"byteOffset = " + mByteOffset + ", " +
"score = " + mScore + ", " +
"personalizedScore = " + mPersonalizedScore + ", " +
- "hotwordPhrase = " + mHotwordPhrase + ", " +
+ "hotwordPhraseId = " + mHotwordPhraseId + ", " +
"extras = " + mExtras +
" }";
}
@@ -264,7 +276,7 @@
&& mByteOffset == that.mByteOffset
&& mScore == that.mScore
&& mPersonalizedScore == that.mPersonalizedScore
- && java.util.Objects.equals(mHotwordPhrase, that.mHotwordPhrase)
+ && mHotwordPhraseId == that.mHotwordPhraseId
&& java.util.Objects.equals(mExtras, that.mExtras);
}
@@ -279,7 +291,7 @@
_hash = 31 * _hash + mByteOffset;
_hash = 31 * _hash + mScore;
_hash = 31 * _hash + mPersonalizedScore;
- _hash = 31 * _hash + java.util.Objects.hashCode(mHotwordPhrase);
+ _hash = 31 * _hash + mHotwordPhraseId;
_hash = 31 * _hash + java.util.Objects.hashCode(mExtras);
return _hash;
}
@@ -290,15 +302,12 @@
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
- byte flg = 0;
- if (mHotwordPhrase != null) flg |= 0x10;
- dest.writeByte(flg);
dest.writeInt(mConfidenceLevel);
dest.writeInt(mByteOffset);
dest.writeInt(mScore);
dest.writeInt(mPersonalizedScore);
- if (mHotwordPhrase != null) dest.writeString(mHotwordPhrase);
- dest.writeBundle(mExtras);
+ dest.writeInt(mHotwordPhraseId);
+ dest.writeTypedObject(mExtras, flags);
}
@Override
@@ -312,13 +321,12 @@
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
- byte flg = in.readByte();
int confidenceLevel = in.readInt();
int byteOffset = in.readInt();
int score = in.readInt();
int personalizedScore = in.readInt();
- String hotwordPhrase = (flg & 0x10) == 0 ? null : in.readString();
- Bundle extras = in.readBundle();
+ int hotwordPhraseId = in.readInt();
+ PersistableBundle extras = (PersistableBundle) in.readTypedObject(PersistableBundle.CREATOR);
this.mConfidenceLevel = confidenceLevel;
com.android.internal.util.AnnotationValidations.validate(
@@ -326,7 +334,7 @@
this.mByteOffset = byteOffset;
this.mScore = score;
this.mPersonalizedScore = personalizedScore;
- this.mHotwordPhrase = hotwordPhrase;
+ this.mHotwordPhraseId = hotwordPhraseId;
this.mExtras = extras;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mExtras);
@@ -359,8 +367,8 @@
private int mByteOffset;
private int mScore;
private int mPersonalizedScore;
- private @Nullable String mHotwordPhrase;
- private @NonNull Bundle mExtras;
+ private int mHotwordPhraseId;
+ private @NonNull PersistableBundle mExtras;
private long mBuilderFieldsSet = 0L;
@@ -417,11 +425,16 @@
return this;
}
+ /**
+ * An ID representing the keyphrase that triggered the successful detection.
+ *
+ * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
+ */
@DataClass.Generated.Member
- public @NonNull Builder setHotwordPhrase(@NonNull String value) {
+ public @NonNull Builder setHotwordPhraseId(int value) {
checkNotUsed();
mBuilderFieldsSet |= 0x10;
- mHotwordPhrase = value;
+ mHotwordPhraseId = value;
return this;
}
@@ -438,7 +451,7 @@
* versions of Android.
*/
@DataClass.Generated.Member
- public @NonNull Builder setExtras(@NonNull Bundle value) {
+ public @NonNull Builder setExtras(@NonNull PersistableBundle value) {
checkNotUsed();
mBuilderFieldsSet |= 0x20;
mExtras = value;
@@ -463,7 +476,7 @@
mPersonalizedScore = defaultPersonalizedScore();
}
if ((mBuilderFieldsSet & 0x10) == 0) {
- mHotwordPhrase = defaultHotwordPhrase();
+ mHotwordPhraseId = defaultHotwordPhraseId();
}
if ((mBuilderFieldsSet & 0x20) == 0) {
mExtras = defaultExtras();
@@ -473,7 +486,7 @@
mByteOffset,
mScore,
mPersonalizedScore,
- mHotwordPhrase,
+ mHotwordPhraseId,
mExtras);
return o;
}
@@ -487,10 +500,10 @@
}
@DataClass.Generated(
- time = 1616110545582L,
- codegenVersion = "1.0.22",
+ time = 1616965644404L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
- inputSignatures = "public static final int BYTE_OFFSET_UNSET\nprivate final @android.service.voice.HotwordDetector.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate final int mByteOffset\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final @android.annotation.Nullable java.lang.String mHotwordPhrase\nprivate final @android.annotation.NonNull android.os.Bundle mExtras\nprivate static int defaultConfidenceLevel()\nprivate static int defaultByteOffset()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static java.lang.String defaultHotwordPhrase()\nprivate static android.os.Bundle defaultExtras()\npublic static int getMaxBundleSize()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+ inputSignatures = "public static final int BYTE_OFFSET_UNSET\nprivate final @android.service.voice.HotwordDetector.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate final int mByteOffset\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final int mHotwordPhraseId\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static int defaultConfidenceLevel()\nprivate static int defaultByteOffset()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static int defaultHotwordPhraseId()\npublic static int getMaxHotwordPhraseId()\nprivate static android.os.PersistableBundle defaultExtras()\npublic static int getMaxBundleSize()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index fb731a0..7c14c2e 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -37,10 +37,13 @@
import android.os.SharedMemory;
import android.util.Log;
+import com.android.internal.app.IHotwordRecognitionStatusCallback;
+
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;
+import java.util.function.IntConsumer;
/**
* Implemented by an application that wants to offer detection for hotword. The system will
@@ -54,6 +57,39 @@
// TODO (b/177502877): Set the Debug flag to false before shipping.
private static final boolean DBG = true;
+ private static final long UPDATE_TIMEOUT_MILLIS = 5000;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "INITIALIZATION_STATUS_" }, value = {
+ INITIALIZATION_STATUS_SUCCESS,
+ INITIALIZATION_STATUS_CUSTOM_ERROR_1,
+ INITIALIZATION_STATUS_CUSTOM_ERROR_2,
+ INITIALIZATION_STATUS_UNKNOWN,
+ })
+ public @interface InitializationStatus {}
+
+ /**
+ * Indicates that the updated status is successful.
+ */
+ public static final int INITIALIZATION_STATUS_SUCCESS = 0;
+
+ /**
+ * Indicates that the updated status is failure for some application specific reasons.
+ */
+ public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_1 = 1;
+
+ /**
+ * Indicates that the updated status is failure for some application specific reasons.
+ */
+ public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_2 = 2;
+
+ /**
+ * Indicates that the callback wasn’t invoked within the timeout.
+ * This is used by system.
+ */
+ public static final int INITIALIZATION_STATUS_UNKNOWN = 100;
+
/**
* Source for the given audio stream.
*
@@ -104,15 +140,16 @@
}
@Override
- public void updateState(PersistableBundle options, SharedMemory sharedMemory)
- throws RemoteException {
+ public void updateState(PersistableBundle options, SharedMemory sharedMemory,
+ IHotwordRecognitionStatusCallback callback) throws RemoteException {
if (DBG) {
Log.d(TAG, "#updateState");
}
- mHandler.sendMessage(obtainMessage(HotwordDetectionService::onUpdateState,
+ mHandler.sendMessage(obtainMessage(HotwordDetectionService::onUpdateStateInternal,
HotwordDetectionService.this,
options,
- sharedMemory));
+ sharedMemory,
+ callback));
}
@Override
@@ -207,12 +244,20 @@
* @param sharedMemory The unrestricted data blob to provide to the
* {@link HotwordDetectionService}. Use this to provide the hotword models data or other
* such data to the trusted process.
+ * @param callbackTimeoutMillis Timeout in milliseconds for the operation to invoke the
+ * statusCallback.
+ * @param statusCallback Use this to return the updated result. This is non-null only when the
+ * {@link HotwordDetectionService} is being initialized; and it is null if the state is updated
+ * after that.
*
* @hide
*/
@SystemApi
- public void onUpdateState(@Nullable PersistableBundle options,
- @Nullable SharedMemory sharedMemory) {
+ public void onUpdateState(
+ @Nullable PersistableBundle options,
+ @Nullable SharedMemory sharedMemory,
+ @DurationMillisLong long callbackTimeoutMillis,
+ @Nullable @InitializationStatus IntConsumer statusCallback) {
// TODO: Handle the unimplemented case by throwing?
}
@@ -268,6 +313,23 @@
throw new UnsupportedOperationException();
}
+ private void onUpdateStateInternal(@Nullable PersistableBundle options,
+ @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
+ // TODO (b/183684347): Implement timeout case.
+ IntConsumer intConsumer = null;
+ if (callback != null) {
+ intConsumer =
+ value -> {
+ try {
+ callback.onStatusReported(value);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ };
+ }
+ onUpdateState(options, sharedMemory, UPDATE_TIMEOUT_MILLIS, intConsumer);
+ }
+
/**
* Callback for returning the detection result.
*
diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java
index 2649124..f4e5dda 100644
--- a/core/java/android/service/voice/HotwordDetector.java
+++ b/core/java/android/service/voice/HotwordDetector.java
@@ -27,6 +27,7 @@
import android.media.AudioFormat;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
+import android.service.voice.HotwordDetectionService.InitializationStatus;
/**
* Basic functionality for hotword detectors.
@@ -144,5 +145,13 @@
* {@link HotwordDetectionService}.
*/
void onRejected(@Nullable HotwordRejectedResult result);
+
+ /**
+ * Called when the {@link HotwordDetectionService} is created by the system and given a
+ * short amount of time to report it's initialization state.
+ *
+ * @param status Info about initialization state of {@link HotwordDetectionService}.
+ */
+ void onHotwordDetectionServiceInitialized(@InitializationStatus int status);
}
}
diff --git a/core/java/android/service/voice/IHotwordDetectionService.aidl b/core/java/android/service/voice/IHotwordDetectionService.aidl
index cb140f9..cac8333 100644
--- a/core/java/android/service/voice/IHotwordDetectionService.aidl
+++ b/core/java/android/service/voice/IHotwordDetectionService.aidl
@@ -22,6 +22,8 @@
import android.os.SharedMemory;
import android.service.voice.IDspHotwordDetectionCallback;
+import com.android.internal.app.IHotwordRecognitionStatusCallback;
+
/**
* Provide the interface to communicate with hotword detection service.
*
@@ -41,5 +43,6 @@
in PersistableBundle options,
in IDspHotwordDetectionCallback callback);
- void updateState(in PersistableBundle options, in SharedMemory sharedMemory);
+ void updateState(in PersistableBundle options, in SharedMemory sharedMemory,
+ in IHotwordRecognitionStatusCallback callback);
}
diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java
index f49a9d4..376596b 100644
--- a/core/java/android/service/voice/SoftwareHotwordDetector.java
+++ b/core/java/android/service/voice/SoftwareHotwordDetector.java
@@ -67,7 +67,7 @@
mHandler = new Handler(Looper.getMainLooper());
try {
- mManagerService.updateState(options, sharedMemory);
+ mManagerService.updateState(options, sharedMemory, null /* callback */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 920c6a7..71784ef 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -761,11 +761,18 @@
public void notifyLocalColorsChanged(@NonNull List<RectF> regions,
@NonNull List<WallpaperColors> colors)
throws RuntimeException {
- for (int i = 0; i < regions.size() && i < colors.size() && colors.get(i) != null; i++) {
+ for (int i = 0; i < regions.size() && i < colors.size(); i++) {
+ WallpaperColors color = colors.get(i);
+ RectF area = regions.get(i);
+ if (color == null || area == null) {
+ Log.wtf(TAG, "notifyLocalColorsChanged null values. color: "
+ + color + " area " + area);
+ continue;
+ }
try {
mConnection.onLocalWallpaperColorsChanged(
- regions.get(i),
- colors.get(i),
+ area,
+ color,
mDisplayContext.getDisplayId()
);
} catch (RemoteException e) {
@@ -1355,7 +1362,8 @@
+ xOffsetStep);
}
//below is the default implementation
- if (xOffset % xOffsetStep > MIN_PAGE_ALLOWED_MARGIN) return;
+ if (xOffset % xOffsetStep > MIN_PAGE_ALLOWED_MARGIN
+ || !mSurfaceHolder.getSurface().isValid()) return;
int xPage;
int xPages;
if (!validStep(xOffsetStep)) {
@@ -1671,6 +1679,10 @@
}
for (int i = 0; i < areas.size(); i++) {
RectF currentArea = areas.get(i);
+ if (currentArea == null || !isValid(currentArea)) {
+ Log.wtf(TAG, "invalid local area " + currentArea);
+ continue;
+ }
EngineWindowPage page;
RectF area;
int pageIndx;
diff --git a/core/java/android/speech/IRecognitionService.aidl b/core/java/android/speech/IRecognitionService.aidl
index cc1cded..9a5e534 100644
--- a/core/java/android/speech/IRecognitionService.aidl
+++ b/core/java/android/speech/IRecognitionService.aidl
@@ -17,6 +17,7 @@
package android.speech;
import android.os.Bundle;
+import android.content.AttributionSource;
import android.content.Intent;
import android.speech.IRecognitionListener;
@@ -39,11 +40,10 @@
* this intent can contain extra parameters to manipulate the behavior of the recognition
* client. For more information see {@link RecognizerIntent}.
* @param listener to receive callbacks, note that this must be non-null
- * @param packageName the package name calling this API
- * @param featureId The feature in the package
+ * @param attributionSource The attribution source of the caller.
*/
void startListening(in Intent recognizerIntent, in IRecognitionListener listener,
- String packageName, String featureId, int callingUid);
+ in AttributionSource attributionSource);
/**
* Stops listening for speech. Speech captured so far will be recognized as
@@ -51,18 +51,14 @@
* is called during the speech capturing.
*
* @param listener to receive callbacks, note that this must be non-null
- * @param packageName the package name calling this API
- * @param featureId The feature in the package
*/
- void stopListening(in IRecognitionListener listener, String packageName, String featureId);
+ void stopListening(in IRecognitionListener listener);
/**
* Cancels the speech recognition.
*
* @param listener to receive callbacks, note that this must be non-null
* @param packageName the package name calling this API
- * @param featureId The feature in the package
- * @param isShutdown Whether the cancellation is caused by a client calling #shutdown
*/
- void cancel(in IRecognitionListener listener, String packageName, String featureId, boolean isShutdown);
+ void cancel(in IRecognitionListener listener, boolean isShutdown);
}
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index fd584f1..4afa9473 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -16,11 +16,16 @@
package android.speech;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
+import android.app.AppOpsManager;
import android.app.Service;
+import android.content.Context;
+import android.content.ContextParams;
import android.content.Intent;
import android.content.PermissionChecker;
import android.os.Binder;
@@ -28,13 +33,13 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.content.AttributionSource;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
-import com.android.internal.util.Preconditions;
-
import java.lang.ref.WeakReference;
+import java.util.Objects;
/**
* This class provides a base class for recognition service implementations. This class should be
@@ -86,13 +91,13 @@
switch (msg.what) {
case MSG_START_LISTENING:
StartListeningArgs args = (StartListeningArgs) msg.obj;
- dispatchStartListening(args.mIntent, args.mListener, args.mCallingUid);
+ dispatchStartListening(args.mIntent, args.mListener, args.mAttributionSource);
break;
case MSG_STOP_LISTENING:
dispatchStopListening((IRecognitionListener) msg.obj);
break;
case MSG_CANCEL:
- dispatchCancel((IRecognitionListener) msg.obj);
+ dispatchCancel((IRecognitionListener) msg.obj, msg.arg1 == 1);
break;
case MSG_RESET:
dispatchClearCallback();
@@ -102,10 +107,11 @@
};
private void dispatchStartListening(Intent intent, final IRecognitionListener listener,
- int callingUid) {
+ @NonNull AttributionSource attributionSource) {
if (mCurrentCallback == null) {
if (DBG) Log.d(TAG, "created new mCurrentCallback, listener = " + listener.asBinder());
- mCurrentCallback = new Callback(listener, callingUid);
+ mCurrentCallback = new Callback(listener, attributionSource);
+
RecognitionService.this.onStartListening(intent, mCurrentCallback);
} else {
try {
@@ -133,13 +139,16 @@
}
}
- private void dispatchCancel(IRecognitionListener listener) {
+ private void dispatchCancel(IRecognitionListener listener, boolean shutDown) {
if (mCurrentCallback == null) {
if (DBG) Log.d(TAG, "cancel called with no preceding startListening - ignoring");
} else if (mCurrentCallback.mListener.asBinder() != listener.asBinder()) {
Log.w(TAG, "cancel called by client who did not call startListening - ignoring");
} else { // the correct state
RecognitionService.this.onCancel(mCurrentCallback);
+ if (shutDown) {
+ mCurrentCallback.finishRecordAudioOpAttributionToCallerIfNeeded();
+ }
mCurrentCallback = null;
if (DBG) Log.d(TAG, "canceling - setting mCurrentCallback to null");
}
@@ -153,12 +162,13 @@
public final Intent mIntent;
public final IRecognitionListener mListener;
- public final int mCallingUid;
+ public final @NonNull AttributionSource mAttributionSource;
- public StartListeningArgs(Intent intent, IRecognitionListener listener, int callingUid) {
+ public StartListeningArgs(Intent intent, IRecognitionListener listener,
+ @NonNull AttributionSource attributionSource) {
this.mIntent = intent;
this.mListener = listener;
- this.mCallingUid = callingUid;
+ this.mAttributionSource = attributionSource;
}
}
@@ -247,18 +257,19 @@
*/
public class Callback {
private final IRecognitionListener mListener;
- private final int mCallingUid;
+ private final @NonNull AttributionSource mCallingAttributionSource;
+ private @Nullable Context mAttributionContext;
- private Callback(IRecognitionListener listener, int callingUid) {
+ private Callback(IRecognitionListener listener,
+ @NonNull AttributionSource attributionSource) {
mListener = listener;
- mCallingUid = callingUid;
+ mCallingAttributionSource = attributionSource;
}
/**
* The service should call this method when the user has started to speak.
*/
public void beginningOfSpeech() throws RemoteException {
- if (DBG) Log.d(TAG, "beginningOfSpeech");
mListener.onBeginningOfSpeech();
}
@@ -270,6 +281,7 @@
* single channel audio stream. The sample rate is implementation dependent.
*/
public void bufferReceived(byte[] buffer) throws RemoteException {
+ startRecordAudioOpAttributionToCallerIfNeeded();
mListener.onBufferReceived(buffer);
}
@@ -302,6 +314,7 @@
* {@link SpeechRecognizer#RESULTS_RECOGNITION} as a parameter
*/
public void partialResults(Bundle partialResults) throws RemoteException {
+ startRecordAudioOpAttributionToCallerIfNeeded();
mListener.onPartialResults(partialResults);
}
@@ -323,6 +336,7 @@
* {@link SpeechRecognizer#RESULTS_RECOGNITION} as a parameter
*/
public void results(Bundle results) throws RemoteException {
+ startRecordAudioOpAttributionToCallerIfNeeded();
Message.obtain(mHandler, MSG_RESET).sendToTarget();
mListener.onResults(results);
}
@@ -342,7 +356,65 @@
* is being processed. This is obtained from {@link Binder#getCallingUid()}.
*/
public int getCallingUid() {
- return mCallingUid;
+ return mCallingAttributionSource.getUid();
+ }
+
+ /**
+ * Gets the permission identity of the calling app. If you want to attribute
+ * the mic access to the calling app you can create an attribution context
+ * via {@link android.content.Context#createContext(android.content.ContextParams)}
+ * and passing this identity to {@link
+ * android.content.ContextParams.Builder#setNextAttributionSource(AttributionSource)}.
+ *
+ *
+ *
+ *
+ * @return The permission identity of the calling app.
+ *
+ * @see android.content.ContextParams.Builder#setNextAttributionSource(
+ * AttributionSource)
+ */
+ @SuppressLint("CallbackMethodName")
+ public @NonNull AttributionSource getCallingAttributionSource() {
+ return mCallingAttributionSource;
+ }
+
+ private void startRecordAudioOpAttributionToCallerIfNeeded() throws RemoteException {
+ if (!isProxyingRecordAudioToCaller()) {
+ final int result = PermissionChecker.checkPermissionAndStartDataDelivery(
+ RecognitionService.this, Manifest.permission.RECORD_AUDIO,
+ getAttributionContextForCaller().getAttributionSource(),
+ /*message*/ null);
+ if (result == PermissionChecker.PERMISSION_GRANTED) {
+ return;
+ }
+ error(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
+ }
+ }
+
+ private @NonNull Context getAttributionContextForCaller() {
+ if (mAttributionContext == null) {
+ mAttributionContext = createContext(new ContextParams.Builder()
+ .setNextAttributionSource(mCallingAttributionSource)
+ .build());
+ }
+ return mAttributionContext;
+ }
+
+ void finishRecordAudioOpAttributionToCallerIfNeeded() {
+ if (isProxyingRecordAudioToCaller()) {
+ final String op = AppOpsManager.permissionToOp(Manifest.permission.RECORD_AUDIO);
+ PermissionChecker.finishDataDelivery(RecognitionService.this,
+ op, getAttributionContextForCaller().getAttributionSource());
+ }
+ }
+
+ private boolean isProxyingRecordAudioToCaller() {
+ final int op = AppOpsManager.permissionToOpCode(Manifest.permission.RECORD_AUDIO);
+ final AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
+ return appOpsManager.isProxying(op, getAttributionTag(),
+ mCallingAttributionSource.getUid(),
+ mCallingAttributionSource.getPackageName());
}
}
@@ -356,44 +428,35 @@
@Override
public void startListening(Intent recognizerIntent, IRecognitionListener listener,
- String packageName, String featureId, int callingUid) {
- Preconditions.checkNotNull(packageName);
-
+ @NonNull AttributionSource attributionSource) {
+ Objects.requireNonNull(attributionSource);
+ attributionSource.enforceCallingUid();
if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
final RecognitionService service = mServiceRef.get();
- if (service != null && service.checkPermissions(listener, true /*forDataDelivery*/,
- packageName, featureId)) {
+ if (service != null) {
service.mHandler.sendMessage(Message.obtain(service.mHandler,
MSG_START_LISTENING, service.new StartListeningArgs(
- recognizerIntent, listener, callingUid)));
+ recognizerIntent, listener, attributionSource)));
}
}
@Override
- public void stopListening(IRecognitionListener listener, String packageName,
- String featureId) {
- Preconditions.checkNotNull(packageName);
-
+ public void stopListening(IRecognitionListener listener) {
if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder());
final RecognitionService service = mServiceRef.get();
- if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/,
- packageName, featureId)) {
+ if (service != null) {
service.mHandler.sendMessage(Message.obtain(service.mHandler,
MSG_STOP_LISTENING, listener));
}
}
@Override
- public void cancel(IRecognitionListener listener, String packageName,
- String featureId, boolean isShutdown) {
- Preconditions.checkNotNull(packageName);
-
+ public void cancel(IRecognitionListener listener, boolean isShutdown) {
if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
final RecognitionService service = mServiceRef.get();
- if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/,
- packageName, featureId)) {
+ if (service != null) {
service.mHandler.sendMessage(Message.obtain(service.mHandler,
- MSG_CANCEL, listener));
+ MSG_CANCEL, isShutdown ? 1 : 0, 0, listener));
}
}
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 9b93a64..7aa5ee5 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -386,8 +386,7 @@
return;
}
try {
- mService.startListening(recognizerIntent, mListener, mContext.getOpPackageName(),
- mContext.getAttributionTag(), android.os.Process.myUid());
+ mService.startListening(recognizerIntent, mListener, mContext.getAttributionSource());
if (DBG) Log.d(TAG, "service start listening command succeded");
} catch (final RemoteException e) {
Log.e(TAG, "startListening() failed", e);
@@ -401,8 +400,7 @@
return;
}
try {
- mService.stopListening(mListener, mContext.getOpPackageName(),
- mContext.getAttributionTag());
+ mService.stopListening(mListener);
if (DBG) Log.d(TAG, "service stop listening command succeded");
} catch (final RemoteException e) {
Log.e(TAG, "stopListening() failed", e);
@@ -416,11 +414,7 @@
return;
}
try {
- mService.cancel(
- mListener,
- mContext.getOpPackageName(),
- mContext.getAttributionTag(),
- false /* isShutdown */);
+ mService.cancel(mListener, /*isShutdown*/ false);
if (DBG) Log.d(TAG, "service cancel command succeded");
} catch (final RemoteException e) {
Log.e(TAG, "cancel() failed", e);
@@ -463,8 +457,7 @@
public void destroy() {
if (mService != null) {
try {
- mService.cancel(mListener, mContext.getOpPackageName(),
- mContext.getAttributionTag(), true /* isShutdown */);
+ mService.cancel(mListener, /*isShutdown*/ true);
} catch (final RemoteException e) {
// Not important
}
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 1da7dc4..49065aa 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -703,6 +703,10 @@
* calling {@link TelephonyManager#getCallState()} from within this callback may return a
* different state than the callback reports.
*
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+ * targeting API level 31+.
+ *
* @param state call state
* @param phoneNumber call phone number. If application does not have
* {@link android.Manifest.permission#READ_CALL_LOG READ_CALL_LOG} permission or carrier
@@ -712,6 +716,7 @@
* @deprecated Use {@link TelephonyCallback.CallStateListener} instead.
*/
@Deprecated
+ @RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
public void onCallStateChanged(@CallState int state, String phoneNumber) {
// default implementation empty
}
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index 18949cd..1ab6e0f 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -752,6 +752,7 @@
*
* @param state the current call state
*/
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public void onCallStateChanged(@Annotation.CallState int state);
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 572e50a..913ceae 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -70,7 +70,7 @@
DEFAULT_FLAGS.put("settings_tether_all_in_one", "false");
DEFAULT_FLAGS.put("settings_silky_home", "true");
DEFAULT_FLAGS.put("settings_contextual_home", "false");
- DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "true");
+ DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "false");
DEFAULT_FLAGS.put(SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES, "true");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "false");
}
diff --git a/core/java/android/view/ContentInfo.java b/core/java/android/view/ContentInfo.java
index 547bc9d..b55d9b3 100644
--- a/core/java/android/view/ContentInfo.java
+++ b/core/java/android/view/ContentInfo.java
@@ -26,6 +26,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.util.Pair;
+import android.view.inputmethod.InputContentInfo;
import com.android.internal.util.Preconditions;
@@ -141,6 +142,10 @@
private final Uri mLinkUri;
@Nullable
private final Bundle mExtras;
+ @Nullable
+ private final InputContentInfo mInputContentInfo;
+ @Nullable
+ private final DragAndDropPermissions mDragAndDropPermissions;
private ContentInfo(Builder b) {
this.mClip = Objects.requireNonNull(b.mClip);
@@ -149,6 +154,23 @@
this.mFlags = Preconditions.checkFlagsArgument(b.mFlags, FLAG_CONVERT_TO_PLAIN_TEXT);
this.mLinkUri = b.mLinkUri;
this.mExtras = b.mExtras;
+ this.mInputContentInfo = b.mInputContentInfo;
+ this.mDragAndDropPermissions = b.mDragAndDropPermissions;
+ }
+
+ /**
+ * If the content came from a source that supports proactive release of URI permissions
+ * (e.g. IME), releases permissions; otherwise a no-op.
+ *
+ * @hide
+ */
+ public void releasePermissions() {
+ if (mInputContentInfo != null) {
+ mInputContentInfo.releasePermission();
+ }
+ if (mDragAndDropPermissions != null) {
+ mDragAndDropPermissions.release();
+ }
}
@NonNull
@@ -275,6 +297,10 @@
private Uri mLinkUri;
@Nullable
private Bundle mExtras;
+ @Nullable
+ private InputContentInfo mInputContentInfo;
+ @Nullable
+ private DragAndDropPermissions mDragAndDropPermissions;
/**
* Creates a new builder initialized with the data from the given builder.
@@ -285,6 +311,8 @@
mFlags = other.mFlags;
mLinkUri = other.mLinkUri;
mExtras = other.mExtras;
+ mInputContentInfo = other.mInputContentInfo;
+ mDragAndDropPermissions = other.mDragAndDropPermissions;
}
/**
@@ -355,6 +383,31 @@
}
/**
+ * Set the {@link InputContentInfo} object if the content is coming from the IME. This can
+ * be used for proactive cleanup of permissions.
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder setInputContentInfo(@Nullable InputContentInfo inputContentInfo) {
+ mInputContentInfo = inputContentInfo;
+ return this;
+ }
+
+ /**
+ * Set the {@link DragAndDropPermissions} object if the content is coming via drag-and-drop.
+ * This can be used for proactive cleanup of permissions.
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder setDragAndDropPermissions(@Nullable DragAndDropPermissions permissions) {
+ mDragAndDropPermissions = permissions;
+ return this;
+ }
+
+
+ /**
* @return A new {@link ContentInfo} instance with the data from this builder.
*/
@NonNull
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 1e2271a..bf152cb 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1096,6 +1096,22 @@
}
/**
+ * @hide
+ * Returns the display's HDR supported types.
+ *
+ * @see #isHdr()
+ * @see HdrCapabilities#getSupportedHdrTypes()
+ */
+ @TestApi
+ @NonNull
+ public int[] getReportedHdrTypes() {
+ synchronized (mLock) {
+ updateDisplayInfoLocked();
+ return mDisplayInfo.hdrCapabilities.getSupportedHdrTypes();
+ }
+ }
+
+ /**
* Returns whether this display supports any HDR type.
*
* @see #getHdrCapabilities()
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 10721ad..1706799 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -20,6 +20,7 @@
import android.view.IRemoteAnimationFinishedCallback;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
+import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
/**
@@ -43,11 +44,10 @@
* accordingly. This should be called before `finish`
* @param taskId for which the leash should be updated
* @param destinationBounds bounds of the final PiP window
- * @param windowCrop bounds to crop as part of final transform.
- * @param float9 An array of 9 floats to be used as matrix transform.
+ * @param finishTransaction leash operations for the final transform.
*/
- void setFinishTaskBounds(int taskId, in Rect destinationBounds, in Rect windowCrop,
- in float[] float9);
+ void setFinishTaskBounds(int taskId, in Rect destinationBounds,
+ in PictureInPictureSurfaceTransaction finishTransaction);
/**
* Notifies to the system that the animation into Recents should end, and all leashes associated
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index e1f13f2..d0a3e4b 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -777,6 +777,15 @@
VerifiedDisplayHash verifyDisplayHash(in DisplayHash displayHash);
/**
+ * Call to enable or disable the throttling when generating a display hash. This should only be
+ * used for testing. Throttling is enabled by default.
+ *
+ * Must be called from a process that has {@link android.Manifest.permission#READ_FRAME_BUFFER}
+ * permission.
+ */
+ void setDisplayHashThrottlingEnabled(boolean enable);
+
+ /**
* Registers a listener for a {@link android.window.WindowContext} to handle configuration
* changes from the server side.
* <p>
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 8db6456..0686104 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -51,8 +51,8 @@
}
@Override
- public void onWindowFocusGained() {
- super.onWindowFocusGained();
+ public void onWindowFocusGained(boolean hasViewFocus) {
+ super.onWindowFocusGained(hasViewFocus);
getImm().registerImeConsumer(this);
}
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 5e0579d..25dda5b 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -54,6 +54,8 @@
InputChannel inputChannel, MessageQueue messageQueue);
private static native void nativeDispose(long receiverPtr);
private static native void nativeFinishInputEvent(long receiverPtr, int seq, boolean handled);
+ private static native void nativeReportTimeline(long receiverPtr, int inputEventId,
+ long gpuCompletedTime, long presentTime);
private static native boolean nativeConsumeBatchedInputEvents(long receiverPtr,
long frameTimeNanos);
private static native String nativeDump(long receiverPtr, String prefix);
@@ -209,11 +211,11 @@
}
/**
- * Report the latency information for a specific input event.
+ * Report the timing / latency information for a specific input event.
*/
- public final void reportLatencyInfo(int inputEventId, long gpuCompletedTime, long presentTime) {
- Trace.traceBegin(Trace.TRACE_TAG_INPUT, "reportLatencyInfo");
- // TODO(b/169866723) : send this data to InputDispatcher via InputChannel
+ public final void reportTimeline(int inputEventId, long gpuCompletedTime, long presentTime) {
+ Trace.traceBegin(Trace.TRACE_TAG_INPUT, "reportTimeline");
+ nativeReportTimeline(mReceiverPtr, inputEventId, gpuCompletedTime, presentTime);
Trace.traceEnd(Trace.TRACE_TAG_INPUT);
}
diff --git a/core/java/android/view/InputEventSender.java b/core/java/android/view/InputEventSender.java
index 40eb438..d144218 100644
--- a/core/java/android/view/InputEventSender.java
+++ b/core/java/android/view/InputEventSender.java
@@ -112,6 +112,16 @@
}
/**
+ * Called when timeline is sent to the publisher.
+ *
+ * @param inputEventId The id of the input event that caused the frame being reported
+ * @param gpuCompletedTime The time when the frame left the app process
+ * @param presentTime The time when the frame was presented on screen
+ */
+ public void onTimelineReported(int inputEventId, long gpuCompletedTime, long presentTime) {
+ }
+
+ /**
* Sends an input event.
* Must be called on the same Looper thread to which the sender is attached.
*
@@ -143,4 +153,11 @@
private void dispatchInputEventFinished(int seq, boolean handled) {
onInputEventFinished(seq, handled);
}
+
+ // Called from native code.
+ @SuppressWarnings("unused")
+ private void dispatchTimelineReported(
+ int inputEventId, long gpuCompletedTime, long presentTime) {
+ onTimelineReported(inputEventId, gpuCompletedTime, presentTime);
+ }
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index a68f528..c001ec9 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1302,8 +1302,8 @@
/**
* Called when current window gains focus.
*/
- public void onWindowFocusGained() {
- getSourceConsumer(ITYPE_IME).onWindowFocusGained();
+ public void onWindowFocusGained(boolean hasViewFocused) {
+ getSourceConsumer(ITYPE_IME).onWindowFocusGained(hasViewFocused);
}
/**
@@ -1366,8 +1366,9 @@
final InsetsSourceControl imeControl = consumer != null ? consumer.getControl() : null;
// Skip showing animation once that made by system for some reason.
// (e.g. starting window with IME snapshot)
- if (imeControl != null && show) {
- skipAnim = imeControl.getAndClearSkipAnimationOnce();
+ if (imeControl != null) {
+ skipAnim = imeControl.getAndClearSkipAnimationOnce() && show
+ && consumer.hasViewFocusWhenWindowFocusGain();
}
}
applyAnimation(types, show, fromIme, skipAnim);
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index fd1c3b8..bc50dbe 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -81,6 +81,11 @@
private final Supplier<Transaction> mTransactionSupplier;
private @Nullable InsetsSourceControl mSourceControl;
private boolean mHasWindowFocus;
+
+ /**
+ * Whether the view has focus returned by {@link #onWindowFocusGained(boolean)}.
+ */
+ private boolean mHasViewFocusWhenWindowFocusGain;
private Rect mPendingFrame;
private Rect mPendingVisibleFrame;
@@ -223,8 +228,9 @@
/**
* Called when current window gains focus
*/
- public void onWindowFocusGained() {
+ public void onWindowFocusGained(boolean hasViewFocus) {
mHasWindowFocus = true;
+ mHasViewFocusWhenWindowFocusGain = hasViewFocus;
}
/**
@@ -238,6 +244,10 @@
return mHasWindowFocus;
}
+ boolean hasViewFocusWhenWindowFocusGain() {
+ return mHasViewFocusWhenWindowFocusGain;
+ }
+
boolean applyLocalVisibilityOverride() {
final InsetsSource source = mState.peekSource(mType);
final boolean isVisible = source != null ? source.isVisible() : getDefaultVisibility(mType);
diff --git a/core/java/android/view/RoundedCorner.java b/core/java/android/view/RoundedCorner.java
index 56b4383..d10fc44 100644
--- a/core/java/android/view/RoundedCorner.java
+++ b/core/java/android/view/RoundedCorner.java
@@ -29,16 +29,10 @@
/**
* Represents a rounded corner of the display.
- *
- * <code>
- * ________
- * / ^
- * / | Radius
- * | v
- * | X <- Center point
- * |<----->
- * Radius
- * </code>
+ * <p>
+ * <img src="{@docRoot}reference/android/images/rounded_corner/rounded-corner-info.png" height="120"
+ * alt="A figure to describe what the rounded corner radius and the center point are. "/>
+ * </p>
*
* <p>Note: The rounded corner formed by the radius and the center is an approximation.</p>
*
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fb52899..fd3254e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -107,6 +107,7 @@
import android.util.FloatProperty;
import android.util.LayoutDirection;
import android.util.Log;
+import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
import android.util.Pair;
import android.util.Pools.SynchronizedPool;
@@ -26800,8 +26801,10 @@
if (permissions != null) {
permissions.takeTransient();
}
- final ContentInfo payload = new ContentInfo.Builder(
- event.getClipData(), SOURCE_DRAG_AND_DROP).build();
+ final ContentInfo payload =
+ new ContentInfo.Builder(event.getClipData(), SOURCE_DRAG_AND_DROP)
+ .setDragAndDropPermissions(permissions)
+ .build();
ContentInfo remainingPayload = performReceiveContent(payload);
// Return true unless none of the payload was consumed.
return remainingPayload != payload;
@@ -29540,6 +29543,10 @@
return mScrollCaptureInternal;
}
+ ViewRoot getViewRoot() {
+ return mViewRootImpl;
+ }
+
public void dump(String prefix, PrintWriter writer) {
String innerPrefix = prefix + " ";
writer.println(prefix + "AttachInfo:");
@@ -30741,6 +30748,31 @@
}
/**
+ * Returns a {@link ViewTranslationRequest} list which represents the content to be translated
+ * in the virtual view. This is called if this view returned a virtual view structure
+ * from {@link #onProvideContentCaptureStructure} and the system determined that those virtual
+ * views were relevant for translation.
+ *
+ * <p>The default implementation does nothing.</p>
+ *
+ * @param virtualChildIds the virtual child ids which represents the child views in the virtual
+ * view.
+ * @param supportedFormats the supported translation formats. For now, the only possible value
+ * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
+ * @param requestsCollector a {@link ViewTranslationRequest} collector that can be called
+ * multiple times to collect the information to be translated in the virtual view. One
+ * {@link ViewTranslationRequest} per virtual child. The {@link ViewTranslationRequest} must
+ * contains the {@link AutofillId} corresponding to the virtualChildIds. Do not keep this
+ * Consumer after the method returns.
+ */
+ @SuppressLint("NullableCollection")
+ public void onCreateTranslationRequests(@NonNull long[] virtualChildIds,
+ @NonNull @DataFormat int[] supportedFormats,
+ @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
+ // no-op
+ }
+
+ /**
* Returns a {@link ViewTranslationCallback} that is used to display/hide the translated
* information. If the View supports displaying translated content, it should implement
* {@link ViewTranslationCallback}.
@@ -30782,13 +30814,29 @@
}
/**
+ * Called when the content from {@link View#onCreateTranslationRequest} had been translated by
+ * the TranslationService.
+ *
+ * <p> The default implementation does nothing.</p>
+ *
+ * @param response a {@link ViewTranslationResponse} SparseArray for the request that send by
+ * {@link View#onCreateTranslationRequests} that contains the translated information which can
+ * be shown in the view. The key of SparseArray is
+ * the virtual child ids.
+ */
+ public void onTranslationResponse(@NonNull LongSparseArray<ViewTranslationResponse> response) {
+ // no-op
+ }
+
+ /**
* Dispatch to collect the {@link ViewTranslationRequest}s for translation purpose by traversing
* the hierarchy when the app requests ui translation. Typically, this method should only be
* overridden by subclasses that provide a view hierarchy (such as {@link ViewGroup}). Other
* classes should override {@link View#onCreateTranslationRequest}. When requested to start the
* ui translation, the system will call this method to traverse the view hierarchy to call
* {@link View#onCreateTranslationRequest} to build {@link ViewTranslationRequest}s and create a
- * {@link android.view.translation.Translator} to translate the requests.
+ * {@link android.view.translation.Translator} to translate the requests. All the
+ * {@link ViewTranslationRequest}s must be added when the traversal is done.
*
* <p> The default implementation will call {@link View#onCreateTranslationRequest} to build
* {@link ViewTranslationRequest} if the view should be translated. </p>
@@ -30808,14 +30856,15 @@
@NonNull List<ViewTranslationRequest> requests) {
AutofillId autofillId = getAutofillId();
if (viewIds.containsKey(autofillId)) {
- ViewTranslationRequest request = null;
if (viewIds.get(autofillId) == null) {
- request = onCreateTranslationRequest(supportedFormats);
+ ViewTranslationRequest request = onCreateTranslationRequest(supportedFormats);
if (request != null && request.getKeys().size() > 0) {
requests.add(request);
}
} else {
- // TODO: handle virtual view
+ onCreateTranslationRequests(viewIds.get(autofillId), supportedFormats, request -> {
+ requests.add(request);
+ });
}
}
}
@@ -30886,4 +30935,20 @@
callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
}
}
+
+ /**
+ * @return The {@link android.view.ViewRoot} interface for this View. This will only
+ * return a non-null value when called between {@link #onAttachedToWindow} and
+ * {@link #onDetachedFromWindow}.
+ *
+ * The ViewRoot itself is not a View, it is just the interface to the windowing-system
+ * object that contains the entire view hierarchy. For the root View of a given hierarchy
+ * see {@link #getRootView}.
+ */
+ public @Nullable ViewRoot getViewRoot() {
+ if (mAttachInfo != null) {
+ return mAttachInfo.getViewRoot();
+ }
+ return null;
+ }
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
new file mode 100644
index 0000000..3c75598
--- /dev/null
+++ b/core/java/android/view/ViewRoot.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UiThread;
+
+/**
+ * Provides an interface to the root-Surface of a View Hierarchy or Window. This
+ * is used in combination with the {@link android.view.SurfaceControl} API to enable
+ * attaching app created SurfaceControl to the ViewRoot's surface hierarchy, and enable
+ * SurfaceTransactions to be performed in sync with the ViewRoot drawing. This object
+ * is obtained from {@link android.view.View#getViewRoot} and
+ * {@link android.view.Window#getViewRoot}. It must be used from the UI thread of
+ * the object it was obtained from.
+ */
+@UiThread
+public interface ViewRoot {
+ /**
+ * Create a transaction which will reparent {@param child} to the ViewRoot. See
+ * {@link SurfaceControl.Transaction#reparent}. This transacton must be applied
+ * or merged in to another transaction by the caller, otherwise it will have
+ * no effect.
+ *
+ * @param child The SurfaceControl to reparent.
+ * @return A new transaction which performs the reparent operation when applied.
+ */
+ @Nullable SurfaceControl.Transaction buildReparentTransaction(@NonNull SurfaceControl child);
+
+ /**
+ * Consume the passed in transaction, and request the ViewRoot to apply it with the
+ * next draw. This transaction will be merged with the buffer transaction from the ViewRoot
+ * and they will show up on-screen atomically synced.
+ *
+ * This will not cause a draw to be scheduled, and if there are no other changes
+ * to the View hierarchy you may need to call {@link android.view.View#invalidate}
+ */
+ boolean applyTransactionOnDraw(@NonNull SurfaceControl.Transaction t);
+}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0a246a6..e2cf962 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -224,7 +224,7 @@
*/
@SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
public final class ViewRootImpl implements ViewParent,
- View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
+ View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks, ViewRoot {
private static final String TAG = "ViewRootImpl";
private static final boolean DBG = false;
private static final boolean LOCAL_LOGV = false;
@@ -3344,8 +3344,9 @@
}
// TODO (b/131181940): Make sure this doesn't leak Activity with mActivityConfigCallback
// config changes.
+ final View focusedView = mView != null ? mView.findFocus() : null;
if (hasWindowFocus) {
- mInsetsController.onWindowFocusGained();
+ mInsetsController.onWindowFocusGained(focusedView != null /* hasViewFocused */);
} else {
mInsetsController.onWindowFocusLost();
}
@@ -3394,8 +3395,7 @@
// Note: must be done after the focus change callbacks,
// so all of the view state is set up correctly.
- mImeFocusController.onPostWindowFocus(mView != null ? mView.findFocus() : null,
- hasWindowFocus, mWindowAttributes);
+ mImeFocusController.onPostWindowFocus(focusedView, hasWindowFocus, mWindowAttributes);
if (hasWindowFocus) {
// Clear the forward bit. We can just do this directly, since
@@ -8601,7 +8601,7 @@
return;
}
final long gpuCompletedTime = data[FrameMetrics.Index.GPU_COMPLETED];
- mReceiver.reportLatencyInfo(inputEventId, gpuCompletedTime, presentTime);
+ mReceiver.reportTimeline(inputEventId, gpuCompletedTime, presentTime);
}
}
HardwareRendererObserver mHardwareRendererObserver;
@@ -10249,4 +10249,21 @@
t.apply();
}
}
+
+ @Override
+ @Nullable public SurfaceControl.Transaction buildReparentTransaction(
+ @NonNull SurfaceControl child) {
+ if (mSurfaceControl.isValid()) {
+ return new SurfaceControl.Transaction().reparent(child, mSurfaceControl);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean applyTransactionOnDraw(@NonNull SurfaceControl.Transaction t) {
+ registerRtFrameCallback(frame -> {
+ mergeWithNextTransaction(t, frame);
+ });
+ return true;
+ }
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index c814e5a..eacb639 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -2717,4 +2717,14 @@
public @Nullable WindowInsetsController getInsetsController() {
return null;
}
+
+ /**
+ * This will be null before a content view is added, e.g. via
+ * {@link #setContentView} or {@link #addContentView}.
+ *
+ * @return The {@link android.view.ViewRoot} interface for this Window
+ */
+ public @Nullable ViewRoot getViewRoot() {
+ return null;
+ }
}
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index 9ab2c2b..d14dc6e 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -158,6 +158,7 @@
* @param event An event.
*/
public void onAccessibilityEvent(AccessibilityEvent event) {
+ AccessibilityNodeInfo nodeToRefresh = null;
synchronized (mLock) {
if (DEBUG) {
Log.i(LOG_TAG, "onAccessibilityEvent(" + event + ")");
@@ -166,17 +167,19 @@
switch (eventType) {
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
if (mAccessibilityFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- refreshCachedNodeLocked(mAccessibilityFocusedWindow, mAccessibilityFocus);
+ removeCachedNodeLocked(mAccessibilityFocusedWindow, mAccessibilityFocus);
}
mAccessibilityFocus = event.getSourceNodeId();
mAccessibilityFocusedWindow = event.getWindowId();
- refreshCachedNodeLocked(mAccessibilityFocusedWindow, mAccessibilityFocus);
+ nodeToRefresh = removeCachedNodeLocked(mAccessibilityFocusedWindow,
+ mAccessibilityFocus);
} break;
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
if (mAccessibilityFocus == event.getSourceNodeId()
&& mAccessibilityFocusedWindow == event.getWindowId()) {
- refreshCachedNodeLocked(mAccessibilityFocusedWindow, mAccessibilityFocus);
+ nodeToRefresh = removeCachedNodeLocked(mAccessibilityFocusedWindow,
+ mAccessibilityFocus);
mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
mAccessibilityFocusedWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
}
@@ -184,17 +187,18 @@
case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
if (mInputFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- refreshCachedNodeLocked(event.getWindowId(), mInputFocus);
+ removeCachedNodeLocked(event.getWindowId(), mInputFocus);
}
mInputFocus = event.getSourceNodeId();
- refreshCachedNodeLocked(event.getWindowId(), mInputFocus);
+ nodeToRefresh = removeCachedNodeLocked(event.getWindowId(), mInputFocus);
} break;
case AccessibilityEvent.TYPE_VIEW_SELECTED:
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
case AccessibilityEvent.TYPE_VIEW_CLICKED:
case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
- refreshCachedNodeLocked(event.getWindowId(), event.getSourceNodeId());
+ nodeToRefresh = removeCachedNodeLocked(event.getWindowId(),
+ event.getSourceNodeId());
} break;
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
@@ -205,7 +209,7 @@
& AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) != 0) {
clearSubTreeLocked(windowId, sourceId);
} else {
- refreshCachedNodeLocked(windowId, sourceId);
+ nodeToRefresh = removeCachedNodeLocked(windowId, sourceId);
}
}
} break;
@@ -218,8 +222,8 @@
if (event.getWindowChanges()
== AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED) {
// Don't need to clear all cache. Unless the changes are related to
- // content, we won't clear all cache here.
- refreshCachedWindowLocked(event.getWindowId());
+ // content, we won't clear all cache here with clear().
+ clearWindowCacheLocked();
break;
}
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
@@ -228,59 +232,34 @@
}
}
+ if (nodeToRefresh != null) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Refreshing and re-adding cached node.");
+ }
+ if (mAccessibilityNodeRefresher.refreshNode(nodeToRefresh, true)) {
+ add(nodeToRefresh);
+ }
+ }
if (CHECK_INTEGRITY) {
checkIntegrity();
}
}
- private void refreshCachedNodeLocked(int windowId, long sourceId) {
+ private AccessibilityNodeInfo removeCachedNodeLocked(int windowId, long sourceId) {
if (DEBUG) {
- Log.i(LOG_TAG, "Refreshing cached node.");
+ Log.i(LOG_TAG, "Removing cached node.");
}
-
LongSparseArray<AccessibilityNodeInfo> nodes = mNodeCache.get(windowId);
if (nodes == null) {
- return;
+ return null;
}
AccessibilityNodeInfo cachedInfo = nodes.get(sourceId);
// If the source is not in the cache - nothing to do.
if (cachedInfo == null) {
- return;
+ return null;
}
- // The node changed so we will just refresh it right now.
- if (mAccessibilityNodeRefresher.refreshNode(cachedInfo, true)) {
- return;
- }
- // Weird, we could not refresh. Just evict the entire sub-tree.
- clearSubTreeLocked(windowId, sourceId);
- }
-
- private void refreshCachedWindowLocked(int windowId) {
- if (DEBUG) {
- Log.i(LOG_TAG, "Refreshing cached window.");
- }
-
- if (windowId == AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
- return;
- }
-
- final int displayCounts = mWindowCacheByDisplay.size();
- for (int i = 0; i < displayCounts; i++) {
- final SparseArray<AccessibilityWindowInfo> windowsOfDisplay =
- mWindowCacheByDisplay.valueAt(i);
- if (windowsOfDisplay == null) {
- continue;
- }
- final AccessibilityWindowInfo window = windowsOfDisplay.get(windowId);
- if (window == null) {
- continue;
- }
- if (!mAccessibilityNodeRefresher.refreshWindow(window)) {
- // If we fail to refresh the window, clear all windows.
- clearWindowCacheLocked();
- }
- return;
- }
+ nodes.remove(sourceId);
+ return cachedInfo;
}
/**
@@ -450,7 +429,7 @@
if (clone.isAccessibilityFocused()) {
if (mAccessibilityFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID
&& mAccessibilityFocus != sourceId) {
- refreshCachedNodeLocked(windowId, mAccessibilityFocus);
+ removeCachedNodeLocked(windowId, mAccessibilityFocus);
}
mAccessibilityFocus = sourceId;
mAccessibilityFocusedWindow = windowId;
diff --git a/core/java/android/view/displayhash/DisplayHashManager.java b/core/java/android/view/displayhash/DisplayHashManager.java
index 6b0c1a6..69dfc38 100644
--- a/core/java/android/view/displayhash/DisplayHashManager.java
+++ b/core/java/android/view/displayhash/DisplayHashManager.java
@@ -21,7 +21,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Log;
@@ -94,4 +96,19 @@
return null;
}
}
+
+ /**
+ * Call to enable or disable the throttling when generating a display hash. This should only be
+ * used for testing. Throttling is enabled by default.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.READ_FRAME_BUFFER)
+ public void setDisplayHashThrottlingEnabled(boolean enable) {
+ try {
+ WindowManagerGlobal.getWindowManagerService().setDisplayHashThrottlingEnabled(enable);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/view/displayhash/DisplayHashResultCallback.java b/core/java/android/view/displayhash/DisplayHashResultCallback.java
index 04d29ee..6e3d9a8 100644
--- a/core/java/android/view/displayhash/DisplayHashResultCallback.java
+++ b/core/java/android/view/displayhash/DisplayHashResultCallback.java
@@ -72,13 +72,20 @@
*/
int DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM = -5;
+ /**
+ * The caller requested to generate the hash too frequently. The caller should try again at a
+ * after some time has passed to ensure the system isn't overloaded.
+ */
+ int DISPLAY_HASH_ERROR_TOO_MANY_REQUESTS = -6;
+
/** @hide */
@IntDef(prefix = {"DISPLAY_HASH_ERROR_"}, value = {
DISPLAY_HASH_ERROR_UNKNOWN,
DISPLAY_HASH_ERROR_INVALID_BOUNDS,
DISPLAY_HASH_ERROR_MISSING_WINDOW,
DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN,
- DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM
+ DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM,
+ DISPLAY_HASH_ERROR_TOO_MANY_REQUESTS
})
@Retention(RetentionPolicy.SOURCE)
@interface DisplayHashErrorCode {
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index c5bce28..9f796c0 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -959,10 +959,10 @@
}
final ClipData clip = new ClipData(inputContentInfo.getDescription(),
new ClipData.Item(inputContentInfo.getContentUri()));
- final ContentInfo payload =
- new ContentInfo.Builder(clip, SOURCE_INPUT_METHOD)
+ final ContentInfo payload = new ContentInfo.Builder(clip, SOURCE_INPUT_METHOD)
.setLinkUri(inputContentInfo.getLinkUri())
.setExtras(opts)
+ .setInputContentInfo(inputContentInfo)
.build();
return mTargetView.performReceiveContent(payload) == null;
}
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index de4554b..d2db0df 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -101,11 +101,12 @@
* @param privilegedOperations IPC endpoint to do some privileged
* operations that are allowed only to the
* current IME.
+ * @param configChanges {@link InputMethodInfo#getConfigChanges()} declared by IME.
* @hide
*/
@MainThread
default void initializeInternal(IBinder token, int displayId,
- IInputMethodPrivilegedOperations privilegedOperations) {
+ IInputMethodPrivilegedOperations privilegedOperations, int configChanges) {
updateInputMethodDisplay(displayId);
attachToken(token);
}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index cc533eb..c26b302 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -18,19 +18,23 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
+import android.inputmethodservice.InputMethodService;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -61,6 +65,8 @@
* @attr ref android.R.styleable#InputMethod_supportsSwitchingToNextInputMethod
* @attr ref android.R.styleable#InputMethod_supportsInlineSuggestions
* @attr ref android.R.styleable#InputMethod_suppressesSpellChecker
+ * @attr ref android.R.styleable#InputMethod_showInInputMethodPicker
+ * @attr ref android.R.styleable#InputMethod_configChanges
*/
public final class InputMethodInfo implements Parcelable {
static final String TAG = "InputMethodInfo";
@@ -124,6 +130,17 @@
private final boolean mSuppressesSpellChecker;
/**
+ * The flag whether this IME should be shown as an option in the IME picker.
+ */
+ private final boolean mShowInInputMethodPicker;
+
+ /**
+ * The flag for configurations IME assumes the responsibility for handling in
+ * {@link InputMethodService#onConfigurationChanged(Configuration)}}.
+ */
+ private final int mHandledConfigChanges;
+
+ /**
* @param service the {@link ResolveInfo} corresponds in which the IME is implemented.
* @return a unique ID to be returned by {@link #getId()}. We have used
* {@link ComponentName#flattenToShortString()} for this purpose (and it is already
@@ -167,6 +184,7 @@
boolean supportsSwitchingToNextInputMethod = false; // false as default
boolean inlineSuggestionsEnabled = false; // false as default
boolean suppressesSpellChecker = false; // false as default
+ boolean showInInputMethodPicker = true; // true as default
mForceDefault = false;
PackageManager pm = context.getPackageManager();
@@ -212,6 +230,10 @@
com.android.internal.R.styleable.InputMethod_supportsInlineSuggestions, false);
suppressesSpellChecker = sa.getBoolean(
com.android.internal.R.styleable.InputMethod_suppressesSpellChecker, false);
+ showInInputMethodPicker = sa.getBoolean(
+ com.android.internal.R.styleable.InputMethod_showInInputMethodPicker, true);
+ mHandledConfigChanges = sa.getInt(
+ com.android.internal.R.styleable.InputMethod_configChanges, 0);
sa.recycle();
final int depth = parser.getDepth();
@@ -284,6 +306,7 @@
mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
mSuppressesSpellChecker = suppressesSpellChecker;
+ mShowInInputMethodPicker = showInInputMethodPicker;
mIsVrOnly = isVrOnly;
}
@@ -295,9 +318,11 @@
mSupportsSwitchingToNextInputMethod = source.readInt() == 1;
mInlineSuggestionsEnabled = source.readInt() == 1;
mSuppressesSpellChecker = source.readBoolean();
+ mShowInInputMethodPicker = source.readBoolean();
mIsVrOnly = source.readBoolean();
mService = ResolveInfo.CREATOR.createFromParcel(source);
mSubtypes = new InputMethodSubtypeArray(source);
+ mHandledConfigChanges = source.readInt();
mForceDefault = false;
}
@@ -309,7 +334,22 @@
this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
- false /* inlineSuggestionsEnabled */, false /* isVrOnly */);
+ false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
+ 0 /* handledConfigChanges */);
+ }
+
+ /**
+ * Temporary API for creating a built-in input method for test.
+ * @hide
+ */
+ @TestApi
+ public InputMethodInfo(@NonNull String packageName, @NonNull String className,
+ @NonNull CharSequence label, @NonNull String settingsActivity,
+ int handledConfigChanges) {
+ this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
+ settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
+ false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
+ false /* inlineSuggestionsEnabled */, false /* isVrOnly */, handledConfigChanges);
}
/**
@@ -321,7 +361,7 @@
boolean forceDefault) {
this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
true /* supportsSwitchingToNextInputMethod */, false /* inlineSuggestionsEnabled */,
- false /* isVrOnly */);
+ false /* isVrOnly */, 0 /* handledconfigChanges */);
}
/**
@@ -332,7 +372,8 @@
List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
boolean supportsSwitchingToNextInputMethod, boolean isVrOnly) {
this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
- supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly);
+ supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly,
+ 0 /* handledConfigChanges */);
}
/**
@@ -342,7 +383,7 @@
public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
boolean supportsSwitchingToNextInputMethod, boolean inlineSuggestionsEnabled,
- boolean isVrOnly) {
+ boolean isVrOnly, int handledConfigChanges) {
final ServiceInfo si = ri.serviceInfo;
mService = ri;
mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -354,7 +395,9 @@
mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
mSuppressesSpellChecker = false;
+ mShowInInputMethodPicker = true;
mIsVrOnly = isVrOnly;
+ mHandledConfigChanges = handledConfigChanges;
}
private static ResolveInfo buildFakeResolveInfo(String packageName, String className,
@@ -501,13 +544,25 @@
}
}
+ /**
+ * Returns the bit mask of kinds of configuration changes that this IME
+ * can handle itself (without being restarted by the system).
+ *
+ * @attr ref android.R.styleable#InputMethod_configChanges
+ */
+ @ActivityInfo.Config
+ public int getConfigChanges() {
+ return mHandledConfigChanges;
+ }
+
public void dump(Printer pw, String prefix) {
pw.println(prefix + "mId=" + mId
+ " mSettingsActivityName=" + mSettingsActivityName
+ " mIsVrOnly=" + mIsVrOnly
+ " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod
+ " mInlineSuggestionsEnabled=" + mInlineSuggestionsEnabled
- + " mSuppressesSpellChecker=" + mSuppressesSpellChecker);
+ + " mSuppressesSpellChecker=" + mSuppressesSpellChecker
+ + " mShowInInputMethodPicker=" + mShowInInputMethodPicker);
pw.println(prefix + "mIsDefaultResId=0x"
+ Integer.toHexString(mIsDefaultResId));
pw.println(prefix + "Service:");
@@ -583,6 +638,14 @@
}
/**
+ * Return {@code true} if this input method should be shown in the IME picker.
+ * @hide
+ */
+ public boolean showInInputMethodPicker() {
+ return mShowInInputMethodPicker;
+ }
+
+ /**
* Used to package this object into a {@link Parcel}.
*
* @param dest The {@link Parcel} to be written.
@@ -597,9 +660,11 @@
dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0);
dest.writeInt(mInlineSuggestionsEnabled ? 1 : 0);
dest.writeBoolean(mSuppressesSpellChecker);
+ dest.writeBoolean(mShowInInputMethodPicker);
dest.writeBoolean(mIsVrOnly);
mService.writeToParcel(dest, flags);
mSubtypes.writeToParcel(dest);
+ dest.writeInt(mHandledConfigChanges);
}
/**
diff --git a/core/java/android/view/translation/TranslationManager.java b/core/java/android/view/translation/TranslationManager.java
index dfa7095..b89488b 100644
--- a/core/java/android/view/translation/TranslationManager.java
+++ b/core/java/android/view/translation/TranslationManager.java
@@ -121,17 +121,16 @@
}
/**
- * Create a Translator for translation.
+ * Creates an on-device Translator for natural language translation.
*
* <p><strong>NOTE: </strong>Call on a worker thread.
*
* @param translationContext {@link TranslationContext} containing the specs for creating the
* Translator.
- * @return a {@link Translator} to be used for calling translation APIs.
*/
@Nullable
@WorkerThread
- public Translator createTranslator(@NonNull TranslationContext translationContext) {
+ public Translator createOnDeviceTranslator(@NonNull TranslationContext translationContext) {
Objects.requireNonNull(translationContext, "translationContext cannot be null");
synchronized (mLock) {
@@ -166,8 +165,16 @@
}
}
+ /** @deprecated Use {@link #createOnDeviceTranslator(TranslationContext)} */
+ @Deprecated
+ @Nullable
+ @WorkerThread
+ public Translator createTranslator(@NonNull TranslationContext translationContext) {
+ return createOnDeviceTranslator(translationContext);
+ }
+
/**
- * Returns a set of {@link TranslationCapability}s describing the capabilities for
+ * Returns a set of {@link TranslationCapability}s describing the capabilities for on-device
* {@link Translator}s.
*
* <p>These translation capabilities contains a source and target {@link TranslationSpec}
@@ -184,7 +191,7 @@
*/
@NonNull
@WorkerThread
- public Set<TranslationCapability> getTranslationCapabilities(
+ public Set<TranslationCapability> getOnDeviceTranslationCapabilities(
@TranslationSpec.DataFormat int sourceFormat,
@TranslationSpec.DataFormat int targetFormat) {
try {
@@ -206,8 +213,18 @@
}
}
+ /** @deprecated Use {@link #getOnDeviceTranslationCapabilities(int, int)} */
+ @Deprecated
+ @NonNull
+ @WorkerThread
+ public Set<TranslationCapability> getTranslationCapabilities(
+ @TranslationSpec.DataFormat int sourceFormat,
+ @TranslationSpec.DataFormat int targetFormat) {
+ return getOnDeviceTranslationCapabilities(sourceFormat, targetFormat);
+ }
+
/**
- * Registers a {@link PendingIntent} to listen for updates on states of
+ * Registers a {@link PendingIntent} to listen for updates on states of on-device
* {@link TranslationCapability}s.
*
* <p>IMPORTANT: the pending intent must be called to start a service, or a broadcast if it is
@@ -217,7 +234,7 @@
* @param targetFormat data format for the expected translated output data.
* @param pendingIntent the pending intent to invoke when updates are received.
*/
- public void addTranslationCapabilityUpdateListener(
+ public void addOnDeviceTranslationCapabilityUpdateListener(
@TranslationSpec.DataFormat int sourceFormat,
@TranslationSpec.DataFormat int targetFormat,
@NonNull PendingIntent pendingIntent) {
@@ -231,14 +248,26 @@
}
/**
- * Unregisters a {@link PendingIntent} to listen for updates on states of
+ * @deprecated Use {@link #addOnDeviceTranslationCapabilityUpdateListener(int, int,
+ * PendingIntent)}
+ */
+ @Deprecated
+ public void addTranslationCapabilityUpdateListener(
+ @TranslationSpec.DataFormat int sourceFormat,
+ @TranslationSpec.DataFormat int targetFormat,
+ @NonNull PendingIntent pendingIntent) {
+ addOnDeviceTranslationCapabilityUpdateListener(sourceFormat, targetFormat, pendingIntent);
+ }
+
+ /**
+ * Unregisters a {@link PendingIntent} to listen for updates on states of on-device
* {@link TranslationCapability}s.
*
* @param sourceFormat data format for the input data to be translated.
* @param targetFormat data format for the expected translated output data.
* @param pendingIntent the pending intent to unregister
*/
- public void removeTranslationCapabilityUpdateListener(
+ public void removeOnDeviceTranslationCapabilityUpdateListener(
@TranslationSpec.DataFormat int sourceFormat,
@TranslationSpec.DataFormat int targetFormat,
@NonNull PendingIntent pendingIntent) {
@@ -262,10 +291,24 @@
}
}
+ /**
+ * @deprecated Use {@link #removeOnDeviceTranslationCapabilityUpdateListener(int, int,
+ * PendingIntent)}
+ */
+ @Deprecated
+ public void removeTranslationCapabilityUpdateListener(
+ @TranslationSpec.DataFormat int sourceFormat,
+ @TranslationSpec.DataFormat int targetFormat,
+ @NonNull PendingIntent pendingIntent) {
+ removeOnDeviceTranslationCapabilityUpdateListener(
+ sourceFormat, targetFormat, pendingIntent);
+ }
+
//TODO: Add method to propagate updates to mTCapabilityUpdateListeners
/**
- * Returns an immutable PendingIntent which can used by apps to launch translation settings.
+ * Returns an immutable PendingIntent which can be used to launch an activity to view/edit
+ * on-device translation settings.
*
* @return An immutable PendingIntent or {@code null} if one of reason met:
* <ul>
@@ -274,7 +317,7 @@
* </ul>
**/
@Nullable
- public PendingIntent getTranslationSettingsActivityIntent() {
+ public PendingIntent getOnDeviceTranslationSettingsActivityIntent() {
final SyncResultReceiver resultReceiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
try {
mService.getServiceSettingsActivity(resultReceiver, mContext.getUserId());
@@ -289,6 +332,13 @@
}
}
+ /** @deprecated Use {@link #getOnDeviceTranslationSettingsActivityIntent()} */
+ @Deprecated
+ @Nullable
+ public PendingIntent getTranslationSettingsActivityIntent() {
+ return getOnDeviceTranslationSettingsActivityIntent();
+ }
+
void removeTranslator(int id) {
synchronized (mLock) {
mTranslators.remove(id);
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index cfe892f..7d1df9c 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -30,7 +30,9 @@
import android.os.HandlerThread;
import android.os.Process;
import android.util.ArrayMap;
+import android.util.IntArray;
import android.util.Log;
+import android.util.LongSparseArray;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -238,29 +240,88 @@
final SparseArray<ViewTranslationResponse> translatedResult =
response.getViewTranslationResponses();
final SparseArray<ViewTranslationResponse> viewsResult = new SparseArray<>();
- final SparseArray<ViewTranslationResponse> virtualViewsResult = new SparseArray<>();
- final List<AutofillId> viewIds = new ArrayList<>();
+ final SparseArray<LongSparseArray<ViewTranslationResponse>> virtualViewsResult =
+ new SparseArray<>();
+ final IntArray viewIds = new IntArray(1);
for (int i = 0; i < translatedResult.size(); i++) {
final ViewTranslationResponse result = translatedResult.valueAt(i);
final AutofillId autofillId = result.getAutofillId();
+ if (viewIds.indexOf(autofillId.getViewId()) < 0) {
+ viewIds.add(autofillId.getViewId());
+ }
if (autofillId.isNonVirtual()) {
viewsResult.put(translatedResult.keyAt(i), result);
- viewIds.add(autofillId);
} else {
- virtualViewsResult.put(translatedResult.keyAt(i), result);
+ final boolean isVirtualViewAdded =
+ virtualViewsResult.indexOfKey(autofillId.getViewId()) >= 0;
+ final LongSparseArray<ViewTranslationResponse> childIds =
+ isVirtualViewAdded ? virtualViewsResult.get(autofillId.getViewId())
+ : new LongSparseArray<>();
+ childIds.put(autofillId.getVirtualChildLongId(), result);
+ if (!isVirtualViewAdded) {
+ virtualViewsResult.put(autofillId.getViewId(), childIds);
+ }
}
}
+ // Traverse tree and get views by the responsed AutofillId
+ findViewsTraversalByAutofillIds(viewIds);
+
if (viewsResult.size() > 0) {
- onTranslationCompleted(viewsResult, viewIds);
+ onTranslationCompleted(viewsResult);
}
- //TODO(b/177960696): call virtual views onTranslationCompleted()
+ if (virtualViewsResult.size() > 0) {
+ onVirtualViewTranslationCompleted(virtualViewsResult);
+ }
+ }
+
+ /**
+ * The method is used to handle the translation result for the vertual views.
+ */
+ private void onVirtualViewTranslationCompleted(
+ SparseArray<LongSparseArray<ViewTranslationResponse>> translatedResult) {
+ if (!mActivity.isResumed()) {
+ if (DEBUG) {
+ Log.v(TAG, "onTranslationCompleted: Activity is not resumed.");
+ }
+ return;
+ }
+ synchronized (mLock) {
+ if (mCurrentState == STATE_UI_TRANSLATION_FINISHED) {
+ Log.w(TAG, "onTranslationCompleted: the translation state is finished now. "
+ + "Skip to show the translated text.");
+ return;
+ }
+ for (int i = 0; i < translatedResult.size(); i++) {
+ final AutofillId autofillId = new AutofillId(translatedResult.keyAt(i));
+ final View view = mViews.get(autofillId).get();
+ if (view == null) {
+ Log.w(TAG, "onTranslationCompleted: the view for autofill id " + autofillId
+ + " may be gone.");
+ continue;
+ }
+ final LongSparseArray<ViewTranslationResponse> virtualChildResponse =
+ translatedResult.valueAt(i);
+ mActivity.runOnUiThread(() -> {
+ if (view.getViewTranslationCallback() == null) {
+ if (DEBUG) {
+ Log.d(TAG, view + " doesn't support showing translation because of "
+ + "null ViewTranslationCallback.");
+ }
+ return;
+ }
+ view.onTranslationResponse(virtualChildResponse);
+ if (view.getViewTranslationCallback() != null) {
+ view.getViewTranslationCallback().onShowTranslation(view);
+ }
+ });
+ }
+ }
}
/**
* The method is used to handle the translation result for non-vertual views.
*/
- private void onTranslationCompleted(SparseArray<ViewTranslationResponse> translatedResult,
- List<AutofillId> viewIds) {
+ private void onTranslationCompleted(SparseArray<ViewTranslationResponse> translatedResult) {
if (!mActivity.isResumed()) {
if (DEBUG) {
Log.v(TAG, "onTranslationCompleted: Activity is not resumed.");
@@ -277,8 +338,6 @@
+ "Skip to show the translated text.");
return;
}
- // Traverse tree and get views by the responsed AutofillId
- findViewsTraversalByAutofillIds(viewIds);
for (int i = 0; i < resultCount; i++) {
final ViewTranslationResponse response = translatedResult.valueAt(i);
final AutofillId autofillId = response.getAutofillId();
@@ -300,7 +359,9 @@
return;
}
view.onTranslationResponse(response);
- view.getViewTranslationCallback().onShowTranslation(view);
+ if (view.getViewTranslationCallback() != null) {
+ view.getViewTranslationCallback().onShowTranslation(view);
+ }
});
}
}
@@ -343,23 +404,29 @@
// Filter the request views's AutofillId
SparseIntArray virtualViewChildCount = getRequestVirtualViewChildCount(views);
Map<AutofillId, long[]> viewIds = new ArrayMap<>();
+ Map<AutofillId, Integer> unusedIndices = null;
for (int i = 0; i < views.size(); i++) {
AutofillId autofillId = views.get(i);
if (autofillId.isNonVirtual()) {
viewIds.put(autofillId, null);
} else {
+ if (unusedIndices == null) {
+ unusedIndices = new ArrayMap<>();
+ }
// The virtual id get from content capture is long, see getVirtualChildLongId()
// e.g. 1001, 1001:2, 1002:1 -> 1001, <1,2>; 1002, <1>
AutofillId virtualViewAutofillId = new AutofillId(autofillId.getViewId());
long[] childs;
+ int end = 0;
if (viewIds.containsKey(virtualViewAutofillId)) {
childs = viewIds.get(virtualViewAutofillId);
+ end = unusedIndices.get(virtualViewAutofillId);
} else {
int childCount = virtualViewChildCount.get(autofillId.getViewId());
childs = new long[childCount];
viewIds.put(virtualViewAutofillId, childs);
}
- int end = childs.length;
+ unusedIndices.put(virtualViewAutofillId, end + 1);
childs[end] = autofillId.getVirtualChildLongId();
}
}
@@ -403,7 +470,7 @@
return new int[] {TranslationSpec.DATA_FORMAT_TEXT};
}
- private void findViewsTraversalByAutofillIds(List<AutofillId> sourceViewIds) {
+ private void findViewsTraversalByAutofillIds(IntArray sourceViewIds) {
final ArrayList<ViewRootImpl> roots =
WindowManagerGlobal.getInstance().getRootViews(mActivity.getActivityToken());
for (int rootNum = 0; rootNum < roots.size(); rootNum++) {
@@ -417,7 +484,7 @@
}
private void findViewsTraversalByAutofillIds(ViewGroup viewGroup,
- List<AutofillId> sourceViewIds) {
+ IntArray sourceViewIds) {
final int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; ++i) {
final View child = viewGroup.getChildAt(i);
@@ -429,9 +496,10 @@
}
}
- private void addViewIfNeeded(List<AutofillId> sourceViewIds, View view) {
+ private void addViewIfNeeded(IntArray sourceViewIds, View view) {
final AutofillId autofillId = view.getAutofillId();
- if (sourceViewIds.contains(autofillId)) {
+ if ((sourceViewIds.indexOf(autofillId.getViewId()) >= 0)
+ && !mViews.containsKey(autofillId)) {
mViews.put(autofillId, new WeakReference<>(view));
}
}
diff --git a/core/java/android/view/translation/ViewTranslationRequest.java b/core/java/android/view/translation/ViewTranslationRequest.java
index 180b1c2..4d8fb99 100644
--- a/core/java/android/view/translation/ViewTranslationRequest.java
+++ b/core/java/android/view/translation/ViewTranslationRequest.java
@@ -35,7 +35,8 @@
* Wrapper class representing a translation request associated with a {@link android.view.View} to
* be used by {@link android.service.translation.TranslationService}.
*/
-@DataClass(genBuilder = true, genToString = true, genEqualsHashCode = true, genGetters = false)
+@DataClass(genBuilder = false, genToString = true, genEqualsHashCode = true, genGetters = false,
+ genHiddenConstructor = true)
public final class ViewTranslationRequest implements Parcelable {
/**
@@ -91,10 +92,39 @@
return Collections.emptyMap();
}
- @DataClass.Suppress({"addTranslationRequestValue", "setAutofillId"})
- abstract static class BaseBuilder {
+ /**
+ * A builder for building ViewTranslationRequest.
+ */
+ public static final class Builder {
- abstract Builder setTranslationRequestValues(Map<String, TranslationRequestValue> value);
+ private @NonNull AutofillId mAutofillId;
+ private @NonNull Map<String, TranslationRequestValue> mTranslationRequestValues;
+
+ private long mBuilderFieldsSet = 0L;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @param autofillId The {@link AutofillId} of the view associated with this request.
+ */
+ public Builder(@NonNull AutofillId autofillId) {
+ mAutofillId = autofillId;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAutofillId);
+ }
+
+ /**
+ * Creates a new Builder.
+ *
+ * @param autofillId the {@link AutofillId} of the non-virtual view hosting the virtual view
+ * hierarchy associated with this request.
+ * @param virtualChildId the id of the virtual child, relative to the parent.
+ */
+ public Builder(@NonNull AutofillId autofillId, long virtualChildId) {
+ mAutofillId = new AutofillId(autofillId, virtualChildId, AutofillId.NO_SESSION);
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAutofillId);
+ }
/**
* Sets the corresponding {@link TranslationRequestValue} for the provided key.
@@ -104,20 +134,50 @@
* @return this builder.
*/
@SuppressLint("MissingGetterMatchingBuilder")
- public Builder setValue(String key,
- TranslationRequestValue value) {
- final Builder builder = (Builder) this;
- if (builder.mTranslationRequestValues == null) {
+ @NonNull
+ public Builder setValue(@NonNull String key, @NonNull TranslationRequestValue value) {
+ if (mTranslationRequestValues == null) {
setTranslationRequestValues(new ArrayMap<>());
}
- builder.mTranslationRequestValues.put(key, value);
- return builder;
+ mTranslationRequestValues.put(key, value);
+ return this;
+ }
+
+ /**
+ * Builds the instance. This builder should not be touched after calling this!
+ */
+ @NonNull
+ public ViewTranslationRequest build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mTranslationRequestValues = defaultTranslationRequestValues();
+ }
+ ViewTranslationRequest o = new ViewTranslationRequest(
+ mAutofillId,
+ mTranslationRequestValues);
+ return o;
+ }
+
+ Builder setTranslationRequestValues(@NonNull Map<String, TranslationRequestValue> value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mTranslationRequestValues = value;
+ return this;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x4) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
}
}
- // Code below generated by codegen v1.0.22.
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -130,8 +190,15 @@
//@formatter:off
+ /**
+ * Creates a new ViewTranslationRequest.
+ *
+ * @param autofillId
+ * The {@link AutofillId} of the view associated with this request.
+ * @hide
+ */
@DataClass.Generated.Member
- /* package-private */ ViewTranslationRequest(
+ public ViewTranslationRequest(
@NonNull AutofillId autofillId,
@NonNull Map<String,TranslationRequestValue> translationRequestValues) {
this.mAutofillId = autofillId;
@@ -234,67 +301,11 @@
}
};
- /**
- * A builder for {@link ViewTranslationRequest}
- */
- @SuppressWarnings("WeakerAccess")
- @DataClass.Generated.Member
- public static final class Builder extends BaseBuilder {
-
- private @NonNull AutofillId mAutofillId;
- private @NonNull Map<String,TranslationRequestValue> mTranslationRequestValues;
-
- private long mBuilderFieldsSet = 0L;
-
- /**
- * Creates a new Builder.
- *
- * @param autofillId
- * The {@link AutofillId} of the view associated with this request.
- */
- public Builder(
- @NonNull AutofillId autofillId) {
- mAutofillId = autofillId;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mAutofillId);
- }
-
- @DataClass.Generated.Member
- @Override
- @NonNull Builder setTranslationRequestValues(@NonNull Map<String,TranslationRequestValue> value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x2;
- mTranslationRequestValues = value;
- return this;
- }
-
- /** Builds the instance. This builder should not be touched after calling this! */
- public @NonNull ViewTranslationRequest build() {
- checkNotUsed();
- mBuilderFieldsSet |= 0x4; // Mark builder used
-
- if ((mBuilderFieldsSet & 0x2) == 0) {
- mTranslationRequestValues = defaultTranslationRequestValues();
- }
- ViewTranslationRequest o = new ViewTranslationRequest(
- mAutofillId,
- mTranslationRequestValues);
- return o;
- }
-
- private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x4) != 0) {
- throw new IllegalStateException(
- "This Builder should not be reused. Use a new Builder instance instead");
- }
- }
- }
-
@DataClass.Generated(
- time = 1614992269658L,
- codegenVersion = "1.0.22",
+ time = 1617119791798L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/translation/ViewTranslationRequest.java",
- inputSignatures = "public static final java.lang.String ID_TEXT\nprivate final @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"translationRequestValue\") java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> mTranslationRequestValues\npublic @android.annotation.NonNull android.view.translation.TranslationRequestValue getValue(java.lang.String)\npublic @android.annotation.NonNull java.util.Set<java.lang.String> getKeys()\npublic @android.annotation.NonNull android.view.autofill.AutofillId getAutofillId()\nprivate static java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> defaultTranslationRequestValues()\nclass ViewTranslationRequest extends java.lang.Object implements [android.os.Parcelable]\nabstract android.view.translation.ViewTranslationRequest.Builder setTranslationRequestValues(java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue>)\npublic @android.annotation.SuppressLint android.view.translation.ViewTranslationRequest.Builder setValue(java.lang.String,android.view.translation.TranslationRequestValue)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genToString=true, genEqualsHashCode=true, genGetters=false)\nabstract android.view.translation.ViewTranslationRequest.Builder setTranslationRequestValues(java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue>)\npublic @android.annotation.SuppressLint android.view.translation.ViewTranslationRequest.Builder setValue(java.lang.String,android.view.translation.TranslationRequestValue)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final java.lang.String ID_TEXT\nprivate final @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"translationRequestValue\") java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> mTranslationRequestValues\npublic @android.annotation.NonNull android.view.translation.TranslationRequestValue getValue(java.lang.String)\npublic @android.annotation.NonNull java.util.Set<java.lang.String> getKeys()\npublic @android.annotation.NonNull android.view.autofill.AutofillId getAutofillId()\nprivate static java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> defaultTranslationRequestValues()\nclass ViewTranslationRequest extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate @android.annotation.NonNull java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> mTranslationRequestValues\nprivate long mBuilderFieldsSet\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.view.translation.ViewTranslationRequest.Builder setValue(java.lang.String,android.view.translation.TranslationRequestValue)\npublic @android.annotation.NonNull android.view.translation.ViewTranslationRequest build()\n android.view.translation.ViewTranslationRequest.Builder setTranslationRequestValues(java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue>)\nprivate void checkNotUsed()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=false, genToString=true, genEqualsHashCode=true, genGetters=false, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 487d13e..6d4fa65 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -45,6 +45,7 @@
import android.print.PrintDocumentAdapter;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.LongSparseArray;
import android.util.SparseArray;
import android.view.DragEvent;
import android.view.KeyEvent;
@@ -64,6 +65,9 @@
import android.view.inputmethod.InputConnection;
import android.view.inspector.InspectableProperty;
import android.view.textclassifier.TextClassifier;
+import android.view.translation.TranslationSpec.DataFormat;
+import android.view.translation.ViewTranslationRequest;
+import android.view.translation.ViewTranslationResponse;
import android.widget.AbsoluteLayout;
import java.io.BufferedWriter;
@@ -73,6 +77,7 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
/**
* A View that displays web pages.
@@ -2854,6 +2859,20 @@
return mProvider.getViewDelegate().isVisibleToUserForAutofill(virtualId);
}
+ @Override
+ @Nullable
+ public void onCreateTranslationRequests(@NonNull long[] virtualChildIds,
+ @NonNull @DataFormat int[] supportedFormats,
+ @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
+ mProvider.getViewDelegate().onCreateTranslationRequests(virtualChildIds, supportedFormats,
+ requestsCollector);
+ }
+
+ @Override
+ public void onTranslationResponse(@NonNull LongSparseArray<ViewTranslationResponse> response) {
+ mProvider.getViewDelegate().onTranslationResponse(response);
+ }
+
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 18a110b..770a156 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.content.Intent;
import android.content.res.Configuration;
@@ -33,6 +34,7 @@
import android.os.Handler;
import android.os.Message;
import android.print.PrintDocumentAdapter;
+import android.util.LongSparseArray;
import android.util.SparseArray;
import android.view.DragEvent;
import android.view.KeyEvent;
@@ -47,6 +49,9 @@
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.textclassifier.TextClassifier;
+import android.view.translation.TranslationSpec.DataFormat;
+import android.view.translation.ViewTranslationRequest;
+import android.view.translation.ViewTranslationResponse;
import android.webkit.WebView.HitTestResult;
import android.webkit.WebView.PictureListener;
import android.webkit.WebView.VisualStateCallback;
@@ -56,6 +61,7 @@
import java.io.File;
import java.util.Map;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
/**
* WebView backend provider interface: this interface is the abstract backend to a WebView
@@ -358,6 +364,19 @@
@SuppressWarnings("unused") int flags) {
}
+ @SuppressLint("NullableCollection")
+ default void onCreateTranslationRequests(
+ @NonNull @SuppressWarnings("unused") long[] virtualChildIds,
+ @NonNull @SuppressWarnings("unused") @DataFormat int[] supportedFormats,
+ @NonNull @SuppressWarnings("unused")
+ Consumer<ViewTranslationRequest> requestsCollector) {
+ }
+
+ default void onTranslationResponse(
+ @NonNull @SuppressWarnings("unused")
+ LongSparseArray<ViewTranslationResponse> response) {
+ }
+
public AccessibilityNodeProvider getAccessibilityNodeProvider();
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 238ce85..48e25c51 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2894,8 +2894,8 @@
final int originalLength = mTextView.getText().length();
Selection.setSelection((Spannable) mTextView.getText(), offset);
final ClipData clip = event.getClipData();
- final ContentInfo payload =
- new ContentInfo.Builder(clip, SOURCE_DRAG_AND_DROP)
+ final ContentInfo payload = new ContentInfo.Builder(clip, SOURCE_DRAG_AND_DROP)
+ .setDragAndDropPermissions(permissions)
.build();
mTextView.performReceiveContent(payload);
if (dragDropIntoItself) {
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index 27fcde2..1683878 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -232,11 +232,8 @@
*
* @return The duration of the scroll in milliseconds.
*
- * @hide Pending removal once nothing depends on it
- * @deprecated OverScrollers don't necessarily have a fixed duration.
- * This function will lie to the best of its ability.
+ * @hide
*/
- @Deprecated
public final int getDuration() {
return Math.max(mScrollerX.mDuration, mScrollerY.mDuration);
}
@@ -249,13 +246,8 @@
* @see #setFinalX(int)
* @see #setFinalY(int)
*
- * @hide Pending removal once nothing depends on it
- * @deprecated OverScrollers don't necessarily have a fixed duration.
- * Instead of setting a new final position and extending
- * the duration of an existing scroll, use startScroll
- * to begin a new animation.
+ * @hide
*/
- @Deprecated
@UnsupportedAppUsage
public void extendDuration(int extend) {
mScrollerX.extendDuration(extend);
@@ -269,13 +261,8 @@
* @see #extendDuration(int)
* @see #setFinalY(int)
*
- * @hide Pending removal once nothing depends on it
- * @deprecated OverScroller's final position may change during an animation.
- * Instead of setting a new final position and extending
- * the duration of an existing scroll, use startScroll
- * to begin a new animation.
+ * @hide
*/
- @Deprecated
public void setFinalX(int newX) {
mScrollerX.setFinalPosition(newX);
}
@@ -287,13 +274,8 @@
* @see #extendDuration(int)
* @see #setFinalX(int)
*
- * @hide Pending removal once nothing depends on it
- * @deprecated OverScroller's final position may change during an animation.
- * Instead of setting a new final position and extending
- * the duration of an existing scroll, use startScroll
- * to begin a new animation.
+ * @hide
*/
- @Deprecated
public void setFinalY(int newY) {
mScrollerY.setFinalPosition(newY);
}
@@ -710,13 +692,14 @@
void setFinalPosition(int position) {
mFinal = position;
+ mSplineDistance = mFinal - mStart;
mFinished = false;
}
void extendDuration(int extend) {
final long time = AnimationUtils.currentAnimationTimeMillis();
final int elapsedTime = (int) (time - mStartTime);
- mDuration = elapsedTime + extend;
+ mDuration = mSplineDuration = elapsedTime + extend;
mFinished = false;
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index cb2bba1..29c78b5 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -6342,6 +6342,9 @@
/**
* Set the ID of the top-level view of the XML layout.
*
+ * The view's ID is changed right after inflation, before it gets added to its parent. The ID
+ * of a given view can never change after the initial inflation.
+ *
* Set to {@link View#NO_ID} to reset and simply keep the id defined in the XML layout.
*
* @throws UnsupportedOperationException if the method is called on a RemoteViews defined in
diff --git a/core/java/android/window/PictureInPictureSurfaceTransaction.aidl b/core/java/android/window/PictureInPictureSurfaceTransaction.aidl
new file mode 100644
index 0000000..fe460bd
--- /dev/null
+++ b/core/java/android/window/PictureInPictureSurfaceTransaction.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+parcelable PictureInPictureSurfaceTransaction;
diff --git a/core/java/android/window/PictureInPictureSurfaceTransaction.java b/core/java/android/window/PictureInPictureSurfaceTransaction.java
new file mode 100644
index 0000000..bde91d9
--- /dev/null
+++ b/core/java/android/window/PictureInPictureSurfaceTransaction.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Represents a set of {@link android.view.SurfaceControl.Transaction} operations used to
+ * operate on the {@link android.view.SurfaceControl} for picture-in-picture.
+ *
+ * @hide
+ */
+public final class PictureInPictureSurfaceTransaction implements Parcelable {
+
+ public final float mPositionX;
+ public final float mPositionY;
+
+ public final float mScaleX;
+ public final float mScaleY;
+
+ public final float mRotation;
+ public final float mCornerRadius;
+
+ private final Rect mWindowCrop = new Rect();
+
+ public PictureInPictureSurfaceTransaction(Parcel in) {
+ mPositionX = in.readFloat();
+ mPositionY = in.readFloat();
+ mScaleX = in.readFloat();
+ mScaleY = in.readFloat();
+ mRotation = in.readFloat();
+ mCornerRadius = in.readFloat();
+ mWindowCrop.set(Objects.requireNonNull(in.readTypedObject(Rect.CREATOR)));
+ }
+
+ public PictureInPictureSurfaceTransaction(float positionX, float positionY,
+ float scaleX, float scaleY,
+ float rotation, float cornerRadius,
+ @Nullable Rect windowCrop) {
+ mPositionX = positionX;
+ mPositionY = positionY;
+ mScaleX = scaleX;
+ mScaleY = scaleY;
+ mRotation = rotation;
+ mCornerRadius = cornerRadius;
+ if (windowCrop != null) {
+ mWindowCrop.set(windowCrop);
+ }
+ }
+
+ public PictureInPictureSurfaceTransaction(PictureInPictureSurfaceTransaction other) {
+ this(other.mPositionX, other.mPositionY,
+ other.mScaleX, other.mScaleY,
+ other.mRotation, other.mCornerRadius,
+ other.mWindowCrop);
+ }
+
+ public Rect getWindowCrop() {
+ return new Rect(mWindowCrop);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof PictureInPictureSurfaceTransaction)) return false;
+ PictureInPictureSurfaceTransaction that = (PictureInPictureSurfaceTransaction) o;
+ return Objects.equals(mPositionX, that.mPositionX)
+ && Objects.equals(mPositionY, that.mPositionY)
+ && Objects.equals(mScaleX, that.mScaleX)
+ && Objects.equals(mScaleY, that.mScaleY)
+ && Objects.equals(mRotation, that.mRotation)
+ && Objects.equals(mCornerRadius, that.mCornerRadius)
+ && Objects.equals(mWindowCrop, that.mWindowCrop);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPositionX, mPositionY, mScaleX, mScaleY,
+ mRotation, mCornerRadius, mWindowCrop);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeFloat(mPositionX);
+ out.writeFloat(mPositionY);
+ out.writeFloat(mScaleX);
+ out.writeFloat(mScaleY);
+ out.writeFloat(mRotation);
+ out.writeFloat(mCornerRadius);
+ out.writeTypedObject(mWindowCrop, 0 /* flags */);
+ }
+
+ @Override
+ public String toString() {
+ return "PictureInPictureSurfaceTransaction("
+ + " posX=" + mPositionX
+ + " posY=" + mPositionY
+ + " scaleX=" + mScaleX
+ + " scaleY=" + mScaleY
+ + " rotation=" + mRotation
+ + " cornerRadius=" + mCornerRadius
+ + " crop=" + mWindowCrop
+ + ")";
+ }
+
+ public static final @android.annotation.NonNull Creator<PictureInPictureSurfaceTransaction>
+ CREATOR =
+ new Creator<PictureInPictureSurfaceTransaction>() {
+ public PictureInPictureSurfaceTransaction createFromParcel(Parcel in) {
+ return new PictureInPictureSurfaceTransaction(in);
+ }
+ public PictureInPictureSurfaceTransaction[] newArray(int size) {
+ return new PictureInPictureSurfaceTransaction[size];
+ }
+ };
+}
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index a0b4e24..3b35b6df 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -76,6 +76,9 @@
/** The container is the recipient of a transferred starting-window */
public static final int FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT = 1 << 3;
+ /** The first unused bit. This can be used by remotes to attach custom flags to this change. */
+ public static final int FLAG_FIRST_CUSTOM = 1 << 4;
+
/** @hide */
@IntDef(prefix = { "FLAG_" }, value = {
FLAG_NONE,
@@ -252,7 +255,8 @@
* Indication that `change` is independent of parents (ie. it has a different type of
* transition vs. "going along for the ride")
*/
- public static boolean isIndependent(TransitionInfo.Change change, TransitionInfo info) {
+ public static boolean isIndependent(@NonNull TransitionInfo.Change change,
+ @NonNull TransitionInfo info) {
// If the change has no parent (it is root), then it is independent
if (change.getParent() == null) return true;
@@ -343,7 +347,7 @@
* Sets the taskinfo of this container if this is a task. WARNING: this takes the
* reference, so don't modify it afterwards.
*/
- public void setTaskInfo(ActivityManager.RunningTaskInfo taskInfo) {
+ public void setTaskInfo(@Nullable ActivityManager.RunningTaskInfo taskInfo) {
mTaskInfo = taskInfo;
}
@@ -424,8 +428,8 @@
return mEndRotation;
}
- @Override
/** @hide */
+ @Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedObject(mContainer, flags);
dest.writeTypedObject(mParent, flags);
@@ -454,8 +458,8 @@
}
};
- @Override
/** @hide */
+ @Override
public int describeContents() {
return 0;
}
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index c62ea33..26a6f0d 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -23,6 +23,7 @@
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -338,6 +339,18 @@
}
/**
+ * Starts a task by id. The task is expected to already exist (eg. as a recent task).
+ * @param taskId Id of task to start.
+ * @param options bundle containing ActivityOptions for the task's top activity.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction startTask(int taskId, @Nullable Bundle options) {
+ mHierarchyOps.add(HierarchyOp.createForTaskLaunch(taskId, options));
+ return this;
+ }
+
+ /**
* Merges another WCT into this one.
* @param transfer When true, this will transfer everything from other potentially leaving
* other in an unusable state. When false, other is left alone, but
@@ -663,6 +676,11 @@
public static final int HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT = 2;
public static final int HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT = 3;
public static final int HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS = 4;
+ public static final int HIERARCHY_OP_TYPE_LAUNCH_TASK = 5;
+
+ // The following key(s) are for use with mLaunchOptions:
+ // When launching a task (eg. from recents), this is the taskId to be launched.
+ public static final String LAUNCH_KEY_TASK_ID = "android:transaction.hop.taskId";
private final int mType;
@@ -678,36 +696,47 @@
final private int[] mWindowingModes;
final private int[] mActivityTypes;
+ private final Bundle mLaunchOptions;
+
public static HierarchyOp createForReparent(
@NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) {
return new HierarchyOp(HIERARCHY_OP_TYPE_REPARENT,
- container, reparent, null, null, toTop);
+ container, reparent, null, null, toTop, null);
}
public static HierarchyOp createForReorder(@NonNull IBinder container, boolean toTop) {
return new HierarchyOp(HIERARCHY_OP_TYPE_REORDER,
- container, container, null, null, toTop);
+ container, container, null, null, toTop, null);
}
public static HierarchyOp createForChildrenTasksReparent(IBinder currentParent,
IBinder newParent, int[] windowingModes, int[] activityTypes, boolean onTop) {
return new HierarchyOp(HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT,
- currentParent, newParent, windowingModes, activityTypes, onTop);
+ currentParent, newParent, windowingModes, activityTypes, onTop, null);
}
public static HierarchyOp createForSetLaunchRoot(IBinder container,
int[] windowingModes, int[] activityTypes) {
return new HierarchyOp(HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT,
- container, null, windowingModes, activityTypes, false);
+ container, null, windowingModes, activityTypes, false, null);
}
public static HierarchyOp createForAdjacentRoots(IBinder root1, IBinder root2) {
return new HierarchyOp(HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS,
- root1, root2, null, null, false);
+ root1, root2, null, null, false, null);
}
- private HierarchyOp(int type, @NonNull IBinder container, @Nullable IBinder reparent,
- int[] windowingModes, int[] activityTypes, boolean toTop) {
+ /** Create a hierarchy op for launching a task. */
+ public static HierarchyOp createForTaskLaunch(int taskId, @Nullable Bundle options) {
+ final Bundle fullOptions = options == null ? new Bundle() : options;
+ fullOptions.putInt(LAUNCH_KEY_TASK_ID, taskId);
+ return new HierarchyOp(HIERARCHY_OP_TYPE_LAUNCH_TASK, null, null, null, null, true,
+ fullOptions);
+ }
+
+ private HierarchyOp(int type, @Nullable IBinder container, @Nullable IBinder reparent,
+ int[] windowingModes, int[] activityTypes, boolean toTop,
+ @Nullable Bundle launchOptions) {
mType = type;
mContainer = container;
mReparent = reparent;
@@ -716,6 +745,7 @@
mActivityTypes = activityTypes != null ?
Arrays.copyOf(activityTypes, activityTypes.length) : null;
mToTop = toTop;
+ mLaunchOptions = launchOptions;
}
public HierarchyOp(@NonNull HierarchyOp copy) {
@@ -725,6 +755,7 @@
mToTop = copy.mToTop;
mWindowingModes = copy.mWindowingModes;
mActivityTypes = copy.mActivityTypes;
+ mLaunchOptions = copy.mLaunchOptions;
}
protected HierarchyOp(Parcel in) {
@@ -734,6 +765,7 @@
mToTop = in.readBoolean();
mWindowingModes = in.createIntArray();
mActivityTypes = in.createIntArray();
+ mLaunchOptions = in.readBundle();
}
public int getType() {
@@ -771,6 +803,11 @@
return mActivityTypes;
}
+ @Nullable
+ public Bundle getLaunchOptions() {
+ return mLaunchOptions;
+ }
+
@Override
public String toString() {
switch (mType) {
@@ -790,6 +827,8 @@
case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS:
return "{SetAdjacentRoot: container=" + mContainer
+ " adjacentRoot=" + mReparent + "}";
+ case HIERARCHY_OP_TYPE_LAUNCH_TASK:
+ return "{LaunchTask: " + mLaunchOptions + "}";
default:
return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent
+ " mToTop=" + mToTop + " mWindowingMode=" + mWindowingModes
@@ -805,6 +844,7 @@
dest.writeBoolean(mToTop);
dest.writeIntArray(mWindowingModes);
dest.writeIntArray(mActivityTypes);
+ dest.writeBundle(mLaunchOptions);
}
@Override
diff --git a/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java b/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java
index 7baa53b..a600a94 100644
--- a/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java
+++ b/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java
@@ -133,6 +133,17 @@
duration);
}
+ /**
+ * Logs the activated mode of the magnification when the IME window is shown on the screen.
+ * Calls this when the magnification is enabled and the IME window is shown on the screen.
+ *
+ * @param mode The activated magnification mode.
+ */
+ public static void logMagnificationModeWithImeOn(int mode) {
+ FrameworkStatsLog.write(FrameworkStatsLog.MAGNIFICATION_MODE_WITH_IME_ON_REPORTED,
+ convertToLoggingMagnificationMode(mode));
+ }
+
private static int convertToLoggingShortcutType(@ShortcutType int shortcutType) {
switch (shortcutType) {
case ACCESSIBILITY_BUTTON:
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index 22a2564..c056e26 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -40,6 +40,23 @@
private static final String TAG = "AssistUtils";
+ /** bundle key: how was the assistant invoked? */
+ public static final String INVOCATION_TYPE_KEY = "invocation_type";
+ /** value for INVOCATION_TYPE_KEY: no data */
+ public static final int INVOCATION_TYPE_UNKNOWN = 0;
+ /** value for INVOCATION_TYPE_KEY: on-screen swipe gesture */
+ public static final int INVOCATION_TYPE_GESTURE = 1;
+ /** value for INVOCATION_TYPE_KEY: device-specific physical gesture */
+ public static final int INVOCATION_TYPE_PHYSICAL_GESTURE = 2;
+ /** value for INVOCATION_TYPE_KEY: voice hotword */
+ public static final int INVOCATION_TYPE_VOICE = 3;
+ /** value for INVOCATION_TYPE_KEY: search bar affordance */
+ public static final int INVOCATION_TYPE_QUICK_SEARCH_BAR = 4;
+ /** value for INVOCATION_TYPE_KEY: long press on home navigation button */
+ public static final int INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS = 5;
+ /** value for INVOCATION_TYPE_KEY: long press on physical power button */
+ public static final int INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS = 6;
+
private final Context mContext;
private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index eecd0cf..01bb199 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -20,6 +20,7 @@
import android.app.AsyncNotedAppOp;
import android.app.SyncNotedAppOp;
import android.app.RuntimeAppOpAccessMessage;
+import android.content.AttributionSource;
import android.content.pm.ParceledListSlice;
import android.os.Bundle;
import android.os.RemoteCallback;
@@ -52,17 +53,13 @@
// End of methods also called by native code.
// Any new method exposed to native must be added after the last one, do not reorder
- int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
- String proxiedAttributionTag, int proxyUid, String proxyPackageName,
- String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message,
- boolean shouldCollectMessage);
- int startProxyOperation(IBinder clientId, int code, int proxiedUid, String proxiedPackageName,
- @nullable String proxiedAttributionTag, int proxyUid, String proxyPackageName,
- @nullable String proxyAttributionTag, boolean startIfModeDefault,
- boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage);
- void finishProxyOperation(IBinder clientId, int code, int proxiedUid, String proxiedPackageName,
- @nullable String proxiedAttributionTag, int proxyUid, String proxyPackageName,
- @nullable String proxyAttributionTag);
+ int noteProxyOperation(int code, in AttributionSource attributionSource,
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ boolean skipProxyOperation);
+ int startProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource,
+ boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
+ boolean shouldCollectMessage, boolean skipProxyOperation);
+ void finishProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource);
// Remaining methods are only used in Java.
int checkPackage(int uid, String packageName);
@@ -83,6 +80,7 @@
void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep);
void addHistoricalOps(in AppOpsManager.HistoricalOps ops);
void resetHistoryParameters();
+ void resetPackageOpsNoHistory(String packageName);
void clearHistory();
void rebootHistory(long offlineDurationMillis);
List<AppOpsManager.PackageOps> getUidOps(int uid, in int[] ops);
@@ -100,6 +98,8 @@
void startWatchingActive(in int[] ops, IAppOpsActiveCallback callback);
void stopWatchingActive(IAppOpsActiveCallback callback);
boolean isOperationActive(int code, int uid, String packageName);
+ boolean isProxying(int op, String proxyPackageName, String proxyAttributionTag, int proxiedUid,
+ String proxiedPackageName);
void startWatchingStarted(in int[] ops, IAppOpsStartedCallback callback);
void stopWatchingStarted(IAppOpsStartedCallback callback);
diff --git a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
index 23314e7..9bec505 100644
--- a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
+++ b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
@@ -66,4 +66,12 @@
* Called when the recognition is resumed after it was temporarily paused.
*/
void onRecognitionResumed();
+
+ /**
+ * Called when the {@link HotwordDetectionService} reported the result for requesting update
+ * state action.
+ *
+ * @param status The status about the result of requesting update state action.
+ */
+ void onStatusReported(int status);
}
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index bb6233b..fffeb02 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -26,6 +26,7 @@
import android.os.RemoteCallback;
import android.os.SharedMemory;
+import com.android.internal.app.IHotwordRecognitionStatusCallback;
import com.android.internal.app.IVoiceActionCheckCallback;
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
@@ -238,8 +239,12 @@
* @param sharedMemory The unrestricted data blob to provide to the
* {@link HotwordDetectionService}. Use this to provide the hotword models data or other
* such data to the trusted process.
+ * @param callback Use this to report {@link HotwordDetectionService} status.
*/
- void updateState(in PersistableBundle options, in SharedMemory sharedMemory);
+ void updateState(
+ in PersistableBundle options,
+ in SharedMemory sharedMemory,
+ in IHotwordRecognitionStatusCallback callback);
/**
* Requests to shutdown hotword detection service.
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
index e4dd7b0..20e520e 100644
--- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -29,7 +29,7 @@
* Actual operations are implemented and handled by InputMethodManagerService.
*/
oneway interface IInputMethodPrivilegedOperations {
- void setImeWindowStatus(int vis, int backDisposition, in IVoidResultCallback resultCallback);
+ void setImeWindowStatusAsync(int vis, int backDisposition);
void reportStartInput(in IBinder startInputToken, in IVoidResultCallback resultCallback);
void createInputContentUriToken(in Uri contentUri, in String packageName,
in IIInputContentUriTokenResultCallback resultCallback);
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index 04cf3f3..98c75b9 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -95,8 +95,7 @@
}
/**
- * Calls {@link IInputMethodPrivilegedOperations#setImeWindowStatus(int, int,
- * IVoidResultCallback)}.
+ * Calls {@link IInputMethodPrivilegedOperations#setImeWindowStatusAsync(int, int}.
*
* @param vis visibility flags
* @param backDisposition disposition flags
@@ -107,15 +106,13 @@
* @see android.inputmethodservice.InputMethodService#BACK_DISPOSITION_ADJUST_NOTHING
*/
@AnyThread
- public void setImeWindowStatus(int vis, int backDisposition) {
+ public void setImeWindowStatusAsync(int vis, int backDisposition) {
final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
if (ops == null) {
return;
}
try {
- final Completable.Void value = Completable.createVoid();
- ops.setImeWindowStatus(vis, backDisposition, ResultCallbacks.of(value));
- Completable.getResult(value);
+ ops.setImeWindowStatusAsync(vis, backDisposition);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/com/android/internal/os/DmabufInfoReader.java b/core/java/com/android/internal/os/DmabufInfoReader.java
new file mode 100644
index 0000000..786a6ee
--- /dev/null
+++ b/core/java/com/android/internal/os/DmabufInfoReader.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.Nullable;
+
+/** Wrapper around libdmabufinfo. */
+public final class DmabufInfoReader {
+ private DmabufInfoReader() {}
+
+ /** Process dma-buf stats. */
+ public static final class ProcessDmabuf {
+ /** Size of buffers retained by the process. */
+ public final int retainedSizeKb;
+ /** Number of buffers retained by the process. */
+ public final int retainedBuffersCount;
+ /** Size of buffers mapped to the address space. */
+ public final int mappedSizeKb;
+ /** Count of buffers mapped to the address space. */
+ public final int mappedBuffersCount;
+
+ ProcessDmabuf(int retainedSizeKb, int retainedBuffersCount,
+ int mappedSizeKb, int mappedBuffersCount) {
+ this.retainedSizeKb = retainedSizeKb;
+ this.retainedBuffersCount = retainedBuffersCount;
+ this.mappedSizeKb = mappedSizeKb;
+ this.mappedBuffersCount = mappedBuffersCount;
+ }
+ }
+
+ /**
+ * Return stats for DMA-BUFs retained by process pid or null if the DMA-BUF
+ * stats could not be read.
+ */
+ @Nullable
+ public static native ProcessDmabuf getProcessStats(int pid);
+}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 2458fe3..f907e25 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -182,12 +182,6 @@
System.loadLibrary("android");
System.loadLibrary("compiler_rt");
System.loadLibrary("jnigraphics");
-
- try {
- System.loadLibrary("sfplugin_ccodec");
- } catch (Error | RuntimeException e) {
- // tolerate missing sfplugin_ccodec which is only present on Codec 2 devices
- }
}
native private static void nativePreloadAppProcessHALs();
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 611fe29..a6dc4e0 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -75,6 +75,7 @@
import android.util.Pair;
import android.util.SparseArray;
import android.util.TypedValue;
+import android.view.ViewRoot;
import android.view.ContextThemeWrapper;
import android.view.CrossWindowBlurListeners;
import android.view.Gravity;
@@ -3981,4 +3982,9 @@
public View getNavigationBarBackgroundView() {
return mDecor != null ? mDecor.getNavigationBarBackgroundView() : null;
}
+
+ @Override
+ public ViewRoot getViewRoot() {
+ return getViewRootImplOrNull();
+ }
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 3418768..e438d39 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -61,7 +61,6 @@
void notifyDataConnectionForSubscriber(
int phoneId, int subId, in PreciseDataConnectionState preciseState);
// Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
- void notifyCellLocation(in CellIdentity cellLocation);
void notifyCellLocationForSubscriber(in int subId, in CellIdentity cellLocation);
@UnsupportedAppUsage
void notifyCellInfo(in List<CellInfo> cellInfo);
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index c336373..8d82e33 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -35,7 +35,8 @@
* {@hide}
*/
oneway interface IInputMethod {
- void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps);
+ void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps,
+ int configChanges);
void onCreateInlineSuggestionsRequest(in InlineSuggestionsRequestInfo requestInfo,
in IInlineSuggestionsRequestCallback cb);
diff --git a/core/java/com/android/internal/widget/NotificationExpandButton.java b/core/java/com/android/internal/widget/NotificationExpandButton.java
index fc4cc57..7a8ead6 100644
--- a/core/java/com/android/internal/widget/NotificationExpandButton.java
+++ b/core/java/com/android/internal/widget/NotificationExpandButton.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.RemotableViewMethod;
@@ -165,11 +166,13 @@
private void updateColors() {
if (shouldShowNumber() && !mDisallowColor) {
mPillView.setBackgroundTintList(ColorStateList.valueOf(mHighlightPillColor));
- mIconView.setColorFilter(mHighlightTextColor);
+ mPillView.setBackgroundTintMode(PorterDuff.Mode.SRC_IN);
+ mIconView.setColorFilter(mHighlightTextColor, PorterDuff.Mode.SRC_IN);
mNumberView.setTextColor(mHighlightTextColor);
} else {
mPillView.setBackgroundTintList(ColorStateList.valueOf(mDefaultPillColor));
- mIconView.setColorFilter(mDefaultTextColor);
+ mPillView.setBackgroundTintMode(PorterDuff.Mode.SRC_IN);
+ mIconView.setColorFilter(mDefaultTextColor, PorterDuff.Mode.SRC_IN);
mNumberView.setTextColor(mDefaultTextColor);
}
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 20d257e..de85ff9 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -202,6 +202,7 @@
"com_android_internal_content_om_OverlayConfig.cpp",
"com_android_internal_net_NetworkUtilsInternal.cpp",
"com_android_internal_os_ClassLoaderFactory.cpp",
+ "com_android_internal_os_DmabufInfoReader.cpp",
"com_android_internal_os_FuseAppLoop.cpp",
"com_android_internal_os_KernelCpuBpfTracking.cpp",
"com_android_internal_os_KernelCpuTotalBpfMapReader.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 0c3f265..6636b1f 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -191,6 +191,7 @@
extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
+extern int register_com_android_internal_os_DmabufInfoReader(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
extern int register_com_android_internal_os_KernelCpuBpfTracking(JNIEnv* env);
extern int register_com_android_internal_os_KernelCpuTotalBpfMapReader(JNIEnv* env);
@@ -1616,6 +1617,7 @@
REG_JNI(register_android_animation_PropertyValuesHolder),
REG_JNI(register_android_security_Scrypt),
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
+ REG_JNI(register_com_android_internal_os_DmabufInfoReader),
REG_JNI(register_com_android_internal_os_FuseAppLoop),
REG_JNI(register_com_android_internal_os_KernelCpuBpfTracking),
REG_JNI(register_com_android_internal_os_KernelCpuTotalBpfMapReader),
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index bfeb01d..44597cc 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -27,6 +27,7 @@
#include <input/InputTransport.h>
#include <log/log.h>
#include <utils/Looper.h>
+#include <variant>
#include <vector>
#include "android_os_MessageQueue.h"
#include "android_view_InputChannel.h"
@@ -80,6 +81,7 @@
status_t initialize();
void dispose();
status_t finishInputEvent(uint32_t seq, bool handled);
+ status_t reportTimeline(int32_t inputEventId, nsecs_t gpuCompletedTime, nsecs_t presentTime);
status_t consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime,
bool* outConsumedBatch);
std::string dump(const char* prefix);
@@ -93,13 +95,19 @@
bool handled;
};
+ struct Timeline {
+ int32_t inputEventId;
+ std::array<nsecs_t, GraphicsTimeline::SIZE> timeline;
+ };
+ typedef std::variant<Finish, Timeline> OutboundEvent;
+
jobject mReceiverWeakGlobal;
InputConsumer mInputConsumer;
sp<MessageQueue> mMessageQueue;
PreallocatedInputEventFactory mInputEventFactory;
bool mBatchedInputEventPending;
int mFdEvents;
- std::vector<Finish> mFinishQueue;
+ std::vector<OutboundEvent> mOutboundQueue;
void setFdEvents(int events);
@@ -152,7 +160,23 @@
.seq = seq,
.handled = handled,
};
- mFinishQueue.push_back(finish);
+ mOutboundQueue.push_back(finish);
+ return processOutboundEvents();
+}
+
+status_t NativeInputEventReceiver::reportTimeline(int32_t inputEventId, nsecs_t gpuCompletedTime,
+ nsecs_t presentTime) {
+ if (kDebugDispatchCycle) {
+ ALOGD("channel '%s' ~ %s", getInputChannelName().c_str(), __func__);
+ }
+ std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
+ graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = gpuCompletedTime;
+ graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = presentTime;
+ Timeline timeline{
+ .inputEventId = inputEventId,
+ .timeline = graphicsTimeline,
+ };
+ mOutboundQueue.push_back(timeline);
return processOutboundEvents();
}
@@ -170,7 +194,7 @@
/**
* Receiver's primary role is to receive input events, but it has an additional duty of sending
- * 'ack' for events (using the call 'finishInputEvent').
+ * 'ack' for events (using the call 'finishInputEvent') and reporting input event timeline.
*
* If we are looking at the communication between InputPublisher and InputConsumer, we can say that
* from the InputConsumer's perspective, InputMessage's that are sent from publisher to consumer are
@@ -178,19 +202,31 @@
* InputPublisher are 'outbound / outgoing' events.
*
* NativeInputEventReceiver owns (and acts like) an InputConsumer. So the finish events are outbound
- * from InputEventReceiver (and will be sent to the InputPublisher).
+ * from InputEventReceiver (and will be sent to the InputPublisher). Likewise, timeline events are
+ * outbound events.
*
- * In this function, send as many events from 'mFinishQueue' as possible across the socket to the
+ * In this function, send as many events from 'mOutboundQueue' as possible across the socket to the
* InputPublisher. If no events are remaining, let the looper know so that it doesn't wake up
* unnecessarily.
*/
status_t NativeInputEventReceiver::processOutboundEvents() {
- while (!mFinishQueue.empty()) {
- const Finish& finish = *mFinishQueue.begin();
- status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
+ while (!mOutboundQueue.empty()) {
+ OutboundEvent& outbound = *mOutboundQueue.begin();
+ status_t status;
+
+ if (std::holds_alternative<Finish>(outbound)) {
+ const Finish& finish = std::get<Finish>(outbound);
+ status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
+ } else if (std::holds_alternative<Timeline>(outbound)) {
+ const Timeline& timeline = std::get<Timeline>(outbound);
+ status = mInputConsumer.sendTimeline(timeline.inputEventId, timeline.timeline);
+ } else {
+ LOG_ALWAYS_FATAL("Unexpected event type in std::variant");
+ status = BAD_VALUE;
+ }
if (status == OK) {
// Successful send. Erase the entry and keep trying to send more
- mFinishQueue.erase(mFinishQueue.begin());
+ mOutboundQueue.erase(mOutboundQueue.begin());
continue;
}
@@ -198,7 +234,7 @@
if (status == WOULD_BLOCK) {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Remaining outbound events: %zu.",
- getInputChannelName().c_str(), mFinishQueue.size());
+ getInputChannelName().c_str(), mOutboundQueue.size());
}
setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
return WOULD_BLOCK; // try again later
@@ -425,12 +461,23 @@
out += android::base::StringPrintf("mBatchedInputEventPending: %s\n",
toString(mBatchedInputEventPending));
- out = out + "mFinishQueue:\n";
- for (const Finish& finish : mFinishQueue) {
- out += android::base::StringPrintf(" seq=%" PRIu32 " handled=%s\n", finish.seq,
- toString(finish.handled));
+ out = out + "mOutboundQueue:\n";
+ for (const OutboundEvent& outbound : mOutboundQueue) {
+ if (std::holds_alternative<Finish>(outbound)) {
+ const Finish& finish = std::get<Finish>(outbound);
+ out += android::base::StringPrintf(" Finish: seq=%" PRIu32 " handled=%s\n", finish.seq,
+ toString(finish.handled));
+ } else if (std::holds_alternative<Timeline>(outbound)) {
+ const Timeline& timeline = std::get<Timeline>(outbound);
+ out += android::base::
+ StringPrintf(" Timeline: inputEventId=%" PRId32 " gpuCompletedTime=%" PRId64
+ ", presentTime=%" PRId64 "\n",
+ timeline.inputEventId,
+ timeline.timeline[GraphicsTimeline::GPU_COMPLETED_TIME],
+ timeline.timeline[GraphicsTimeline::PRESENT_TIME]);
+ }
}
- if (mFinishQueue.empty()) {
+ if (mOutboundQueue.empty()) {
out = out + " <empty>\n";
}
return addPrefix(out, prefix);
@@ -489,6 +536,25 @@
}
}
+static void nativeReportTimeline(JNIEnv* env, jclass clazz, jlong receiverPtr, jint inputEventId,
+ jlong gpuCompletedTime, jlong presentTime) {
+ if (IdGenerator::getSource(inputEventId) != IdGenerator::Source::INPUT_READER) {
+ // skip this event, it did not originate from hardware
+ return;
+ }
+ sp<NativeInputEventReceiver> receiver =
+ reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
+ status_t status = receiver->reportTimeline(inputEventId, gpuCompletedTime, presentTime);
+ if (status == OK || status == WOULD_BLOCK) {
+ return; // normal operation
+ }
+ if (status != DEAD_OBJECT) {
+ std::string message = android::base::StringPrintf("Failed to send timeline. status=%s(%d)",
+ strerror(-status), status);
+ jniThrowRuntimeException(env, message.c_str());
+ }
+}
+
static jboolean nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jlong receiverPtr,
jlong frameTimeNanos) {
sp<NativeInputEventReceiver> receiver =
@@ -520,6 +586,7 @@
(void*)nativeInit},
{"nativeDispose", "(J)V", (void*)nativeDispose},
{"nativeFinishInputEvent", "(JIZ)V", (void*)nativeFinishInputEvent},
+ {"nativeReportTimeline", "(JIJJ)V", (void*)nativeReportTimeline},
{"nativeConsumeBatchedInputEvents", "(JJ)Z", (void*)nativeConsumeBatchedInputEvents},
{"nativeDump", "(JLjava/lang/String;)Ljava/lang/String;", (void*)nativeDump},
};
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 10927b9..fd1b998 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -45,6 +45,7 @@
jclass clazz;
jmethodID dispatchInputEventFinished;
+ jmethodID dispatchTimelineReported;
} gInputEventSenderClassInfo;
@@ -75,9 +76,10 @@
}
int handleEvent(int receiveFd, int events, void* data) override;
- status_t receiveFinishedSignals(JNIEnv* env);
- bool notifyFinishedSignal(JNIEnv* env, jobject sender, const InputPublisher::Finished& finished,
- bool skipCallbacks);
+ status_t processConsumerResponse(JNIEnv* env);
+ bool notifyConsumerResponse(JNIEnv* env, jobject sender,
+ const InputPublisher::ConsumerResponse& response,
+ bool skipCallbacks);
};
NativeInputEventSender::NativeInputEventSender(JNIEnv* env, jobject senderWeak,
@@ -188,12 +190,12 @@
}
JNIEnv* env = AndroidRuntime::getJNIEnv();
- status_t status = receiveFinishedSignals(env);
+ status_t status = processConsumerResponse(env);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? 1 : 0;
}
-status_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) {
+status_t NativeInputEventSender::processConsumerResponse(JNIEnv* env) {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Receiving finished signals.", getInputChannelName().c_str());
}
@@ -206,18 +208,18 @@
}
bool skipCallbacks = false; // stop calling Java functions after an exception occurs
for (;;) {
- Result<InputPublisher::Finished> result = mInputPublisher.receiveFinishedSignal();
+ Result<InputPublisher::ConsumerResponse> result = mInputPublisher.receiveConsumerResponse();
if (!result.ok()) {
const status_t status = result.error().code();
if (status == WOULD_BLOCK) {
return OK;
}
- ALOGE("channel '%s' ~ Failed to consume finished signals. status=%d",
+ ALOGE("channel '%s' ~ Failed to process consumer response. status=%d",
getInputChannelName().c_str(), status);
return status;
}
- const bool notified = notifyFinishedSignal(env, senderObj.get(), *result, skipCallbacks);
+ const bool notified = notifyConsumerResponse(env, senderObj.get(), *result, skipCallbacks);
if (!notified) {
skipCallbacks = true;
}
@@ -225,16 +227,49 @@
}
/**
- * Invoke the Java function dispatchInputEventFinished for the received "Finished" signal.
- * Set the variable 'skipCallbacks' to 'true' if a Java exception occurred.
+ * Invoke the corresponding Java function for the different variants of response.
+ * If the response is a Finished object, invoke dispatchInputEventFinished.
+ * If the response is a Timeline object, invoke dispatchTimelineReported.
+ * Set 'skipCallbacks' to 'true' if a Java exception occurred.
* Java function will only be called if 'skipCallbacks' is originally 'false'.
*
* Return "false" if an exception occurred while calling the Java function
* "true" otherwise
*/
-bool NativeInputEventSender::notifyFinishedSignal(JNIEnv* env, jobject sender,
- const InputPublisher::Finished& finished,
- bool skipCallbacks) {
+bool NativeInputEventSender::notifyConsumerResponse(
+ JNIEnv* env, jobject sender, const InputPublisher::ConsumerResponse& response,
+ bool skipCallbacks) {
+ if (std::holds_alternative<InputPublisher::Timeline>(response)) {
+ const InputPublisher::Timeline& timeline = std::get<InputPublisher::Timeline>(response);
+
+ if (kDebugDispatchCycle) {
+ ALOGD("channel '%s' ~ Received timeline, inputEventId=%" PRId32
+ ", gpuCompletedTime=%" PRId64 ", presentTime=%" PRId64,
+ getInputChannelName().c_str(), timeline.inputEventId,
+ timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME],
+ timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
+ }
+
+ if (skipCallbacks) {
+ ALOGW("Java exception occurred. Skipping dispatchTimelineReported for "
+ "inputEventId=%" PRId32,
+ timeline.inputEventId);
+ return true;
+ }
+
+ env->CallVoidMethod(sender, gInputEventSenderClassInfo.dispatchTimelineReported,
+ timeline.inputEventId, timeline.graphicsTimeline);
+ if (env->ExceptionCheck()) {
+ ALOGE("Exception dispatching timeline, inputEventId=%" PRId32, timeline.inputEventId);
+ return false;
+ }
+
+ return true;
+ }
+
+ // Must be a Finished event
+ const InputPublisher::Finished& finished = std::get<InputPublisher::Finished>(response);
+
auto it = mPublishedSeqMap.find(finished.seq);
if (it == mPublishedSeqMap.end()) {
ALOGW("Received 'finished' signal for unknown seq number = %" PRIu32, finished.seq);
@@ -340,6 +375,9 @@
gInputEventSenderClassInfo.dispatchInputEventFinished = GetMethodIDOrDie(
env, gInputEventSenderClassInfo.clazz, "dispatchInputEventFinished", "(IZ)V");
+ gInputEventSenderClassInfo.dispatchTimelineReported =
+ GetMethodIDOrDie(env, gInputEventSenderClassInfo.clazz, "dispatchTimelineReported",
+ "(IJJ)V");
return res;
}
diff --git a/core/jni/com_android_internal_os_DmabufInfoReader.cpp b/core/jni/com_android_internal_os_DmabufInfoReader.cpp
new file mode 100644
index 0000000..4b0a6ac
--- /dev/null
+++ b/core/jni/com_android_internal_os_DmabufInfoReader.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dmabufinfo/dmabufinfo.h>
+#include "core_jni_helpers.h"
+
+namespace android {
+
+static jobject DmabufInfoReader_getProcessStats(JNIEnv *env, jobject, jint pid) {
+ std::vector<dmabufinfo::DmaBuffer> buffers;
+ if (!dmabufinfo::ReadDmaBufMapRefs(pid, &buffers)) {
+ return nullptr;
+ }
+ jint mappedSize = 0;
+ jint mappedCount = buffers.size();
+ for (const auto &buffer : buffers) {
+ mappedSize += buffer.size();
+ }
+ mappedSize /= 1024;
+
+ jint retainedSize = -1;
+ jint retainedCount = -1;
+ if (dmabufinfo::ReadDmaBufFdRefs(pid, &buffers)) {
+ retainedCount = buffers.size();
+ retainedSize = 0;
+ for (const auto &buffer : buffers) {
+ retainedSize += buffer.size();
+ }
+ retainedSize /= 1024;
+ }
+
+ jclass clazz = FindClassOrDie(env, "com/android/internal/os/DmabufInfoReader$ProcessDmabuf");
+ jmethodID constructID = GetMethodIDOrDie(env, clazz, "<init>", "(IIII)V");
+ return env->NewObject(clazz, constructID, retainedSize, retainedCount, mappedSize, mappedCount);
+}
+
+static const JNINativeMethod methods[] = {
+ {"getProcessStats", "(I)Lcom/android/internal/os/DmabufInfoReader$ProcessDmabuf;",
+ (void *)DmabufInfoReader_getProcessStats},
+};
+
+int register_com_android_internal_os_DmabufInfoReader(JNIEnv *env) {
+ return RegisterMethodsOrDie(env, "com/android/internal/os/DmabufInfoReader", methods,
+ NELEM(methods));
+}
+
+} // namespace android
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index f0badbe..530cb44 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -123,6 +123,8 @@
optional SettingProto gesture_silence_alerts_enabled = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto gesture_wake_enabled = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto gesture_setup_complete = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto touch_gesture_enabled = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto long_press_home_enabled = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Assist assist = 7;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index be306e0..fc264f3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1313,7 +1313,7 @@
android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_recordBackgroundAudio"
android:description="@string/permdesc_recordBackgroundAudio"
- android:protectionLevel="internal" />
+ android:protectionLevel="internal|role" />
<!-- ====================================================================== -->
<!-- Permissions for activity recognition -->
@@ -1405,7 +1405,7 @@
android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_backgroundCamera"
android:description="@string/permdesc_backgroundCamera"
- android:protectionLevel="internal" />
+ android:protectionLevel="internal|role" />
<!-- @SystemApi Required in addition to android.permission.CAMERA to be able to access
system only camera devices.
@@ -2016,6 +2016,12 @@
android:label="@string/permlab_preferredPaymentInfo"
android:protectionLevel="normal" />
+ <!-- @SystemApi Allows access to set NFC controller always on states.
+ <p>Protection level: signature|privileged
+ @hide -->
+ <permission android:name="android.permission.NFC_SET_CONTROLLER_ALWAYS_ON"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows an internal user to use privileged SecureElement APIs.
Applications holding this permission can access OMAPI reset system API
and bypass OMAPI AccessControlEnforcer.
@@ -5682,19 +5688,21 @@
<permission android:name="android.permission.RENOUNCE_PERMISSIONS"
android:protectionLevel="signature|privileged" />
+ <!-- Allows an application to read nearby streaming policy. The policy allows the device
+ to stream its notifications and apps to nearby devices.
+ @hide -->
+ <permission android:name="android.permission.READ_NEARBY_STREAMING_POLICY"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows the holder to set the source of the data when setting a clip on the
clipboard.
@hide -->
<permission android:name="android.permission.SET_CLIP_SOURCE"
android:protectionLevel="signature|recents" />
- <!-- Allows an application to request installs that update existing packages do so without
- user action via
- {@link android.content.pm.PackageInstaller.SessionParams#setRequireUserAction(boolean)}.
- This permission only grants the ability to make the request and is not a guarantee that the
- request will be honored. In order to execute the install, the caller must also have the
- "android.permission.REQUEST_INSTALL_PACKAGES" or "android.permission.INSTALL_PACKAGES"
- permissions.
+ <!-- Allows an application to indicate via
+ {@link android.content.pm.PackageInstaller.SessionParams#setRequireUserAction(boolean)}
+ that user action should not be required for an app update.
<p>Protection level: normal
-->
<permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION"
diff --git a/core/res/res/layout/chooser_action_button.xml b/core/res/res/layout/chooser_action_button.xml
index 16ffaa4..def429e 100644
--- a/core/res/res/layout/chooser_action_button.xml
+++ b/core/res/res/layout/chooser_action_button.xml
@@ -19,13 +19,13 @@
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:drawablePadding="8dp"
- android:textColor="?android:textColorPrimary"
+ android:textColor="@color/text_color_primary_device_default_light"
android:textSize="12sp"
android:maxWidth="192dp"
android:singleLine="true"
android:clickable="true"
android:background="@drawable/chooser_action_button_bg"
- android:drawableTint="?android:textColorPrimary"
+ android:drawableTint="@color/text_color_primary_device_default_light"
android:drawableTintMode="src_in"
style="?android:attr/borderlessButtonStyle"
/>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 39de289..eb17991 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Program loop tans"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programme wat batterykrag gebruik"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergroting"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Toeganklikheidsekuriteitbeleid"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruik tans batterykrag"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> programme gebruik tans batterykrag"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik vir besonderhede oor battery- en datagebruik"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"toegang tot jou fisieke aktiwiteit"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"foto\'s en video te neem"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Bluetooth-toestelle in die omtrek"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"ontdek en koppel aan Bluetooth-toestelle in die omtrek"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Oproeprekords"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"lees en skryf foonoproeprekord"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Foon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Laat die program toe om die opstelling van Bluetooth op die tablet te sien, en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Laat die program toe om die opstelling van Bluetooth op jou Android TV-toestel te bekyk, en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Laat die program toe om die opstelling van die Bluetooth op die foon te sien, en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"ontdek en bind Bluetooth-toestelle in die omtrek saam"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Laat die program toe om Bluetooth-toestelle in die omtrek te ontdek en saam te bind"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"koppel aan saamgebinde Bluetooth-toestelle"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Laat die program toe om aan saamgebinde Bluetooth-toestelle te koppel"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Voorkeur-NFC-betalingdiensinligting"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Laat die program toe om voorkeur-NFC-betalingdiensinligting soos geregistreerde hulpmiddels en roetebestemming te kry."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"beheer kortveldkommunikasie"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Kon nie staaf nie"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gebruik skermslot"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Voer jou toesteleiebewys in om voort te gaan."</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Gedeeltelike vingerafdruk is bespeur. Probeer asseblief weer."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Kon nie vingerafdruk verwerk nie. Probeer asseblief weer."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Vingerafdruksensor is vuil. Maak dit skoon en probeer weer."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Vinger is te vinnig beweeg. Probeer weer."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Vinger is te stadig beweer. Probeer asseblief weer."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Vingerafdruk is gestaaf"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Gesig is gestaaf"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gesig is gestaaf; druk asseblief bevestig"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Vingerafdrukhardeware is nie beskikbaar nie."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Vingerafdruk kan nie gestoor word nie. Verwyder asseblief \'n bestaande vingerafdruk."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Vingerafdrukuittelling is bereik. Probeer weer."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Vingerafdrukhandeling is gekanselleer."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Vingerafdrukhandeling is deur gebruiker gekanselleer."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Gesigslot"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Skryf jou gesig weer in"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Skryf asseblief jou gesig weer in om herkenning te verbeter"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Kon nie gesigdata akkuraat vasvang nie. Probeer weer."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Te helder. Probeer sagter beligting."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Te donker. Probeer helderder beligting."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Gekopieer"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> het uit <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> geplak"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> het uit knipbord geplak"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Meer"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Kieslys+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Werk"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Persoonlike aansig"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Werkaansig"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Kan dit nie met werkprogramme deel nie"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Jou IT-administrateur laat jou nie toe om hierdie inhoud met programme in jou werkprofiel te deel nie"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Kan dit nie met werkprogramme oopmaak nie"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Jou IT-administrateur laat jou nie toe om hierdie inhoud met programme in jou werkprofiel oop te maak nie"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Kan dit nie met persoonlike programme deel nie"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Jou IT-administrateur laat jou nie toe om hierdie inhoud met programme in jou persoonlike profiel te deel nie"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Kan nie met persoonlike programme oopmaak nie"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Jou IT-administrateur laat jou nie toe om hierdie inhoud met programme in jou persoonlike profiel oop te maak nie"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Werkprofiel is onderbreek"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Skakel aan"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Geen werkprogramme kan hierdie inhoud steun nie"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Geen werkprogramme kan hierdie inhoud oopmaak nie"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Geen persoonlike programme kan hierdie inhoud steun nie"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Geen persoonlike programme kan hierdie inhoud oopmaak nie"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM se netwerkontsluiting-PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM se netwerksubstelontsluiting-PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM se korporatiewe ontsluiting-PIN"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Vergroot deel van jou skerm"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Jy kan nou jou hele skerm of \'n spesifieke area vergroot, of tussen die twee opsies wissel."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Skakel aan in Instellings"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Maak toe"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Om voort te gaan, moet <b><xliff:g id="APP">%s</xliff:g></b> toegang tot jou toestel se mikrofoon hê."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index b8af80f..9dd9814 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP እየሠራ ነው"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ባትሪ በመፍጀት ላይ ያሉ መተግበሪያዎች"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ማጉላት"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"የተደራሽነት ደህንነት መመሪያ"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ባትሪ እየተጠቀመ ነው"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> መተግበሪያዎች ባትሪ እየተጠቀሙ ነው"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"በባትሪ እና ውሂብ አጠቃቀም ላይ ዝርዝሮችን ለማግኘት መታ ያድርጉ"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"የእርስዎን አካላዊ እንቅስቃሴ ይድረሱበት"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"ካሜራ"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ስዕሎች ያንሱ እና ቪዲዮ ይቅረጹ"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"በአቅራቢያ ያሉ የብሉቱዝ መሣሪያዎች"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"በአቅራቢያ ያሉ የብሉቱዝ መሣሪያዎችን ያግኙ እና ያገናኙ"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"የጥሪ ምዝገባ ማስታወሻዎች"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"የስልክ ጥሪ ምዝግባ ማስታወሻን ያንብቡ እና ይጻፉ"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ስልክ"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"መተግበሪያው በጡባዊ ተኮው ላይ ያለውን የብሉቱዝ ውቅር እንዲያይ እና ከተጣመሩ መሳሪያዎች ጋር ግንኙነቶችን እንዲያደርግና እንዲቀበል ይፈቅድለታል።"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"በእርስዎ የ Android TV መሣሪያ የብሉቱዝ ውቅረት ለማየት፣ እና ከተጣመረው መሣሪያ ጋር ግንኙነት ለመቀበል እንዲችል ለመተግበሪያው ይፈቅዳል።"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"መተግበሪያው በስልኩ ላይ ያለውን የብሉቱዝ ውቅር እንዲያይ እና ከተጣመሩ መሳሪያዎች ጋር ግንኙነቶችን እንዲያደርግና እንዲቀበል ይፈቅድለታል።"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"በአቅራቢያ ያሉ የብሉቱዝ መሣሪያዎችን ያግኙ እና ያጣምሩ"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"መተግበሪያው በአቅራቢያ ያሉ የብሉቱዝ መሣሪያዎችን እንዲያገኝ እና እንዲጣመር ይፈቅድለታል"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"ከተጣመሩ የብሉቱዝ መሣሪያዎች ጋር ያገናኙ"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"መተግበሪያው ከተጣመሩ የብሉቱዝ መሣሪያዎች ጋር እንዲገናኝ ይፈቅድለታል"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ተመራጭ NFC የክፍያ አገልግሎት መረጃ"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"እንደ የተመዘገቡ እርዳታዎች እና የጉዞ መሥመር መዳረሻ የመሳሰለ ተመራጭ nfc የክፍያ አገልግሎት መረጃን ለማግኘት ለመተግበሪያው ያፈቅድለታል።"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ቅርብ የግኑኙነትመስክ (NFC) ተቆጣጠር"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"ማረጋገጥ ላይ ስህተት"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"የማያ ገጽ መቆለፊን ይጠቀሙ"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"ለመቀጠል የመሣሪያዎን የመግቢያ ማስረጃ ያስገቡ"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"ከፊል የጣት አሻራ ተገኝቷል። እባክዎ እንደገና ይሞክሩ።"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ጣት አሻራን መስራት አልተቻለም። እባክዎ እንደገና ይሞክሩ።"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"የጣት አሻራ ዳሳሽ ቆሽሿል። እባክዎ ያጽዱት እና እንደገና ይሞክሩ።"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"ጣት ከልክ በላይ ቶሎ ተንቀሳቅሷል። እባክዎ እንደገና ይሞክሩ።"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ጣት ከልክ በላይ ተንቀራፎ ተንቀሳቅሷል። እባክዎ እንደገና ይሞክሩ።"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"የጣት አሻራ ትክክለኛነት ተረጋግጧል"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ፊት ተረጋግጧል"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ፊት ተረጋግጧል፣ እባክዎ አረጋግጥን ይጫኑ"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"የጣት አሻራ ሃርድዌር አይገኝም።"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"የጣት አሻራ ሊከማች አይችልም። እባክዎ አሁን ያለውን የጣት አሻራ ያስወግዱ።"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"የጣት አሻራ ማብቂያ ጊዜ ደርሷል። እንደገና ይሞክሩ።"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"የጣት አሻራ ስርዓተ ክወና ተትቷል።"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"የጣት አሻራ ክወና በተጠቃሚ ተሰርዟል።"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"በመልክ መክፈት"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"የእርስዎን ፊት ዳግመኛ ያስመዝግቡ"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ማንነትን ለይቶ ማወቅን ለማሻሻል፣ እባክዎ የእርስዎን ፊት ዳግም ያስመዝግቡ"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"ትክክለኛ የፊት ውሂብ ማንሳት አልተቻለም። እንደገና ይሞክሩ።"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"ከልክ በላይ ፈካ ያለ። ይበልጥ ረጋ ያለ ብርሃን አጠቃቀምን ይሞክሩ።"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"ከልክ በላይ ጨለማ ነው። ከዚህ ፈካ ያለ ብርሃን አጠቃቀምን ይሞክሩ።"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"ተቀድቷል"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ከ <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> ተለጥፏል"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ከቅንጣብ ሰሌዳ ተለጥፏል"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"ተጨማሪ"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"ምናሌ+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,7 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"አቋራጭ ይጠቀሙ"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ተቃራኒ ቀለም"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"የቀለም ማስተካከያ"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"የበለጠ ደብዛዛ"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ተጨማሪ ደብዛዛ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> በርቷል።"</string>
<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>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"ሥራ"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"የግል እይታ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"የስራ እይታ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"ይህን በሥራ መተግበሪያዎች ማጋራት አይቻልም"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"የእርስዎ አይቲ አስተዳዳሪ ይህን ይዘት በእርስዎ የሥራ መገለጫ ላይ ባሉ መተግበሪያዎች ማጋራትን አይፈቅድም"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"ይህን በሥራ መተግበሪያዎች መክፈት አይቻልም"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"የእርስዎ አይቲ አስተዳዳሪ ይህን ይዘት በእርስዎ የሥራ መገለጫ ላይ ባሉ መተግበሪያዎች መክፈትን አይፈቅድም"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"ይህን በግል መተግበሪያዎች ማጋራት አይቻልም"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"የእርስዎ አይቲ አስተዳዳሪ ይህን ይዘት በእርስዎ የግል መገለጫ ላይ ባሉ መተግበሪያዎች ማጋራትን አይፈቅድም"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"ይህን በግል መተግበሪያዎች መክፈት አይቻልም"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"የእርስዎ አይቲ አስተዳዳሪ ይህን ይዘት በእርስዎ የግል መገለጫ ላይ ባሉ መተግበሪያዎች መክፈትን አይፈቅድም"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"የሥራ መገለጫ ባለበት ቆሟል"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"አብራ"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"ምንም የሥራ መተግበሪያዎች ይህን ይዘት መደገፍ አይችሉም"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ምንም የሥራ መተግበሪያዎችን ይህን ይዘት መክፈት አይችሉም"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"ምንም የግል መተግበሪያዎች ይህን ይዘት መደገፍ አይችሉም"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"ምንም የግል መተግበሪያዎችን ይህን ይዘት መክፈት አይችሉም"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"የሲም አውታረ መረብ መክፈቻ ፒን"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"የሲም አውታረ መረብ ንኡስ ስብስብ መክፈቻ ፒን"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"የሲም ኮርፖሬት መክፈቻ ፒን"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"የማያ ገጽዎን ክፍል ያጉሉ"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"አሁን የእርስዎን የሙሉ ገጽ እይታ፣ አንድ የተወሰነ ቦታ ማጉላት ወይም በሁለቱም አማራጮች መካከል መቀያየር ይችላሉ።"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"በቅንብሮች ውስጥ ያብሩ"</string>
<string name="dismiss_action" msgid="1728820550388704784">"አሰናብት"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"ለመቀጠል፣ <b><xliff:g id="APP">%s</xliff:g></b> ወደ መሳሪያዎ ማይክሮፎን መድረስ ይፈልጋል።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index fc94e1c..b2f83b7 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -306,7 +306,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"التطبيق قيد التشغيل"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"التطبيقات التي تستهلك البطارية"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"التكبير"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"سياسة أمان \"تسهيل الاستخدام\""</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"يستخدم تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> البطارية"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"تستخدم <xliff:g id="NUMBER">%1$d</xliff:g> من التطبيقات البطارية"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"انقر للحصول على تفاصيل حول البطارية واستخدام البيانات"</string>
@@ -331,6 +332,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"الوصول إلى بيانات نشاطك البدني"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"الكاميرا"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"التقاط صور وتسجيل فيديو"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"الأجهزة القريبة التي تتضمّن بلوتوث"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"تسمح هذه الأذونات للتطبيق باكتشاف الأجهزة القريبة التي تتضمّن بلوتوث والربط بها."</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"سجلّ المكالمات"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"قراءة سجلّ المكالمات الهاتفية والكتابة إليه"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"الهاتف"</string>
@@ -544,6 +547,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"للسماح للتطبيق بعرض إعداد البلوتوث على الجهاز اللوحي وإجراء اتصالات وقبولها مع الأجهزة المقترنة."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"للسماح للتطبيق بعرض بيانات ضبط البلوتوث على جهاز Android TV وإجراء اتصالات مع الأجهزة المقترنة وقبولها."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"للسماح للتطبيق بعرض إعداد البلوتوث على الهاتف وإجراء اتصالات وقبولها مع الأجهزة المقترنة."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"اكتشاف أجهزة قريبة تتضمّن بلوتوث والاقتران بها"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"يسمح هذا الإذن للتطبيق باكتشاف الأجهزة القريبة التي تتضمّن بلوتوث والاقتران بها."</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"تسمح بالربط الأجهزة المقترنة التي تتضمّن بلوتوث."</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"يسمح هذا الإذن للتطبيق بالارتباط بالأجهزة المقترنة التي تتضمّن بلوتوث."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"معلومات الخدمات المدفوعة باستخدام الاتصال قصير المدى NFC المفضّل"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"يسمح هذا الإذن للتطبيق بالحصول على معلومات الخدمات المدفوعة باستخدام الاتصال قصير المدى NFC المفضّل، مثلاً المساعدات المسجّلة ووجهة المسار."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"التحكم في اتصال الحقل القريب"</string>
@@ -579,18 +586,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"خطأ في المصادقة"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"استخدام قفل الشاشة"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"إدخال بيانات اعتماد الجهاز للمتابعة"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"تم اكتشاف جزء من بصمة الإصبع فقط؛ يرجى إعادة المحاولة."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"تعذرت معالجة بصمة الإصبع. يُرجى إعادة المحاولة."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"زر استشعار بصمات الأصابع متّسخ. يُرجى تنظيفه وإعادة المحاولة."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"لقد حرّكت إصبعك بسرعة، يُرجى إعادة المحاولة."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"تم تحريك الإصبع ببطء شديد. يُرجى إعادة المحاولة."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"تم مصادقة بصمة الإصبع"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"تمّت مصادقة الوجه"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"تمّت مصادقة الوجه، يُرجى الضغط على \"تأكيد\"."</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"جهاز بصمة الإصبع غير متاح."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"يتعذر تخزين بصمة الإصبع؛ يرجى إزالة إحدى البصمات المخزنة."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"تم بلوغ مهلة إدخال بصمة الإصبع. أعد المحاولة."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"تم إلغاء تشغيل بصمة الإصبع."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"تم إلغاء تشغيل بصمة الإصبع بواسطة المستخدم."</string>
@@ -615,6 +632,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"فتح القفل بالوجه"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"إعادة تسجيل وجهك"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"لتحسين قدرة الجهاز على معرفة وجهك، يُرجى إعادة تسجيل الوجه."</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"تعذّر تسجيل بيانات دقيقة للوجه. حاول مرة أخرى."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"ساطع للغاية. تجربة مستوى سطوع أقلّ."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"الصورة معتمة للغاية. يُرجى زيادة السطوع."</string>
@@ -1018,6 +1043,12 @@
<string name="copied" msgid="4675902854553014676">"تم النسخ."</string>
<string name="pasted_from_app" msgid="5627698450808256545">"تم لصق محتوى في <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> من <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>."</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"تم لصق محتوى في <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> من الحافظة."</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"المزيد"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"القائمة+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1777,8 +1808,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استخدام الاختصار"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"قلب الألوان"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"تصحيح الألوان"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (3222994553174604132) -->
- <skip />
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"زيادة تعتيم الشاشة"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم تفعيل <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<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">"اضغط مع الاستمرار على مفتاحي مستوى الصوت لمدة 3 ثوانٍ لاستخدام <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -2247,20 +2277,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"للعمل"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"عرض المحتوى الشخصي"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"عرض محتوى العمل"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"تتعذّر مشاركة هذا المحتوى باستخدام تطبيقات العمل"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"لا يسمح لك مشرف تكنولوجيا المعلومات بمشاركة هذا المحتوى باستخدام التطبيقات في ملفك الشخصي للعمل."</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"لا يمكن فتح هذا المحتوى باستخدام تطبيقات العمل"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"لا يسمح لك مشرف تكنولوجيا المعلومات بفتح هذا المحتوى باستخدام التطبيقات في ملفك الشخصي للعمل."</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"تتعذّر مشاركة هذا المحتوى باستخدام التطبيقات الشخصية"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"لا يسمح لك مشرف تكنولوجيا المعلومات بمشاركة هذا المحتوى باستخدام التطبيقات في ملفك الشخصي."</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"يتعذّر فتح هذا المحتوى باستخدام التطبيقات الشخصية"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"لا يسمح لك مشرف تكنولوجيا المعلومات بفتح هذا المحتوى باستخدام التطبيقات في ملفك الشخصي."</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"الملف الشخصي للعمل متوقف مؤقتًا."</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"تفعيل"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"لا يمكن لتطبيقات العمل أن تتوافق مع هذا المحتوى."</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"لا يمكن لتطبيقات العمل أن تفتح هذا المحتوى."</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"لا يمكن للتطبيقات الشخصية أن تدعم هذا المحتوى."</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"لا يمكن للتطبيقات الشخصية أن تفتح هذا المحتوى."</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"رقم التعريف الشخصي لإلغاء قفل شبكة شريحة SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"رقم التعريف الشخصي لإلغاء قفل المجموعة الفرعية لشبكة شريحة SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"رقم التعريف الشخصي لإلغاء قفل شريحة SIM للشركات"</string>
@@ -2373,8 +2414,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"تكبير جزء من الشاشة"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"يمكنك الآن تكبير الشاشة كلها أو جزء معيّن منها أو التبديل بين الخيارين."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"التفعيل من خلال \"الإعدادات\""</string>
<string name="dismiss_action" msgid="1728820550388704784">"إغلاق"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"للمتابعة، يحتاج <b><xliff:g id="APP">%s</xliff:g></b> إلى الوصول إلى ميكروفون الجهاز."</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index caebacf..3c7e372 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"এপ্ চলি আছে"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"বেটাৰি খৰচ কৰা এপসমূহ"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বিবৰ্ধন"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"সাধ্য সুবিধাৰ সুৰক্ষা নীতি"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বেটাৰি ব্যৱহাৰ কৰি আছে"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টা এপে বেটাৰি ব্যৱহাৰ কৰি আছে"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"বেটাৰি আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে বিশদভাৱে জানিবলৈ টিপক"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"শাৰীৰিক কাৰ্যকলাপ এক্সেছ কৰা"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"কেমেৰা"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ফট\' তুলিব আৰু ভিডিঅ\' ৰেকৰ্ড কৰিব পাৰে"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"নিকটৱৰ্তী ব্লুটুথ ডিভাইচ"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"নিকটৱৰ্তী ব্লুটুথ ডিভাইচ বিচাৰি উলিয়াওক আৰু সেইসমূহৰ সৈতে সংযোগ কৰক"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"কল লগসমূহ"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ফ\'নৰ কল লগ পঢ়ক আৰু লিখক"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ফ’ন"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"টেবলেটত ব্লুটুথৰ কনফিগাৰেশ্বন চাবলৈ আৰু যোৰা লগোৱা ডিভাইচসমূহৰ জৰিয়তে সংযোগ কৰিবলৈ আৰু সংযোগৰ অনুৰোধ স্বীকাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে৷"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"এপ্টোক আপোনাৰ Android TV ডিভাইচটোত ব্লুটুথৰ কনফিগাৰেশ্বন চাবলৈ আৰু পেয়াৰ কৰি থোৱা ডিভাইচসমূহৰ সৈতে সংযোগ কৰিবলৈ আৰু গ্ৰহণ কৰিবলৈ অনুমতি দিয়ে।"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ফ\'নটোত ব্লুটুথৰ কনফিগাৰেশ্বন চাবলৈ আৰু যোৰা লগোৱা ডিভাইচসমূহৰ জৰিয়তে সংযোগ কৰিবলৈ আৰু সংযোগৰ অনুৰোধ স্বীকাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে৷"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"নিকটৱৰ্তী ব্লুটুথ ডিভাইচ বিচাৰক আৰু তাৰ সৈতে সংযোগ কৰক"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"এপ্টোক নিকটৱৰ্তী ব্লুটুথ ডিভাইচ বিচাৰি উলিয়াবলৈ আৰু সেইসমূহৰ সৈতে পেয়াৰ কৰিবলৈ অনুমতি দিয়ে"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"পেয়াৰ কৰা ব্লুটুথ ডিভাইচৰ সৈতে সংযোগ কৰক"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"এপ্টোক পেয়াৰ কৰা ব্লুটুথ ডিভাইচৰ সৈতে সংযোগ কৰিবলৈ অনুমতি দিয়ে"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"অগ্ৰাধিকাৰ দিয়া NFC পৰিশোধ সেৱাৰ তথ্য"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"এপ্টোক অগ্ৰাধিকাৰ দিয়া nfc পৰিশোধ সেৱাৰ পঞ্জীকৃত সহায়কসমূহ আৰু পৰিশোধ কৰিব লগা লক্ষ্যস্থান দৰে তথ্য পাবলৈ অনুমতি দিয়ে।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"নিয়েৰ ফিল্ড কমিউনিকেশ্বন নিয়ন্ত্ৰণ কৰক"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"আসোঁৱাহৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰি থকা হৈছে"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"স্ক্ৰীন ল\'ক ব্যৱহাৰ কৰক"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"অব্যাহত ৰাখিবলৈ আপোনাৰ ডিভাইচৰ ক্ৰেডেনশ্বিয়েল দিয়ক"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"ফিংগাৰপ্ৰিণ্ট আংশিকভাৱে চিনাক্ত কৰা হৈছে। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ফিগাৰপ্ৰিণ্টৰ প্ৰক্ৰিয়া সম্পাদন কৰিবপৰা নগ\'ল। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো লেতেৰা হৈ আছে। অনুগ্ৰহ কৰি পৰিষ্কাৰ কৰি আকৌ চেষ্টা কৰক।"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"আঙুলিৰ গতি অতি ক্ষিপ্ৰ আছিল। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"আঙুলিৰ গতি অতি মন্থৰ আছিল। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"ফিংগাৰপ্ৰিণ্টৰ সত্যাপন কৰা হ’ল"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল, অনুগ্ৰহ কৰি ‘নিশ্চিত কৰক’ বুটামটো টিপক"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ নাই।"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ফিংগাৰপ্ৰিণ্ট সঞ্চয় কৰিব পৰা নগ\'ল। পূর্বে সঞ্চিত ফিংগাৰপ্ৰিণ্ট এটা আঁতৰাওক।"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"ফিংগাৰপ্ৰিণ্ট গ্ৰহণৰ সময়সীমা উকলি গৈছে। আকৌ চেষ্টা কৰক।"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ফিংগাৰপ্ৰিণ্ট কাৰ্য বাতিল কৰা হ’ল।"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ব্যৱহাৰকাৰীয়ে ফিংগাৰপ্ৰিণ্ট ক্ৰিয়া বাতিল কৰিছে।"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"মুখাৱয়বৰদ্বাৰা আনলক কৰা সুবিধা"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"আপোনাৰ মুখমণ্ডল পুনৰ পঞ্জীয়ণ কৰক"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"চিনাক্তকৰণৰ সুবিধাটো উন্নত কৰিবলৈ, অনুগ্ৰহ কৰি আপোনাৰ মুখমণ্ডল পুনৰ পঞ্জীয়ন কৰক"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"সঠিক মুখমণ্ডলৰ ডেটা কেপচাৰ নহ’ল। আকৌ চেষ্টা কৰক।"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"অতি উজ্জ্বল। ইয়াতকৈ কম পোহৰৰ উৎস ব্যৱহাৰ কৰক।"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"অতি আন্ধাৰ। উজ্জ্বল লাইট ব্যৱহাৰ কৰক।"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"প্ৰতিলিপি কৰা হ’ল"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>ৰ পৰা <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> পে’ষ্ট কৰা হৈছে"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"ক্লিপব’ৰ্ডৰ পৰা <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> পে’ষ্ট কৰা হৈছে"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"অধিক"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"মেনু+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"মেটা+"</string>
@@ -1689,7 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"শ্বৰ্টকাট ব্যৱহাৰ কৰক"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ৰং বিপৰীতকৰণ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ৰং শুধৰণী"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"অতিৰিক্তভাৱে অনুজ্জ্বল"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"এক্সট্ৰা ডিম"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কীসমূহ ধৰি ৰাখক। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অন কৰা হ\'ল।"</string>
<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>
@@ -2055,7 +2086,7 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ৰুটিন ম’ডৰ তথ্য জাননী"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"চ্চাৰ্জ কৰাৰ সচৰাচৰ সময়ৰ আগতেই বেটাৰি শেষ হ’ব পাৰে"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"বেটাৰিৰ খৰচ কমাবলৈ বেটাৰি সঞ্চয়কাৰী অন কৰা হৈছে"</string>
- <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"বেটাৰি সঞ্চয়কাৰী"</string>
+ <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"বেটাৰী সঞ্চয়কাৰী"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"বেটাৰি সঞ্চয়কাৰী অফ কৰা হ’ল"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ফ\'নটোত পর্যাপ্ত পৰিমাণে চার্জ আছে। সুবিধাবোৰ আৰু সীমাবদ্ধ কৰা নাই।"</string>
<string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"টেবলেটটোত পর্যাপ্ত পৰিমাণে চার্জ আছে। সুবিধাবোৰ আৰু সীমাবদ্ধ কৰা নাই।"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"কৰ্মস্থান"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ব্যক্তিগত ভিউ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"কৰ্মস্থানৰ ভিউ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"কৰ্মস্থানৰ এপ্সমূহৰ সৈতে এইটো শ্বেয়াৰ কৰিব নোৱাৰি"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"আপোনাৰ আইটি প্ৰশাসকে আপোনাক আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলত থকা এপ্সমূহৰ সৈতে এই সমলটো শ্বেয়াৰ কৰিবলৈ নিদিয়ে"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"কৰ্মস্থানৰ এপ্সমূহৰ জৰিয়তে এইটো খুলিব কৰিব নোৱাৰি"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"আপোনাৰ আইটি প্ৰশাসকে আপোনাক আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলত থকা এপ্সমূহৰ জৰিয়তে এই সমলটো খুলিবলৈ নিদিয়ে"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"ব্যক্তিগত এপ্সমূহৰ সৈতে এইটো শ্বেয়াৰ কৰিব নোৱাৰি"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"আপোনাৰ আইটি প্ৰশাসকে আপোনাক আপোনাৰ ব্যক্তিগত প্ৰ\'ফাইলত থকা এপ্সমূহৰ সৈতে এই সমলটো শ্বেয়াৰ কৰিবলৈ নিদিয়ে"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"ব্যক্তিগত এপ্সমূহৰ জৰিয়তে এইটো খুলিব কৰিব নোৱাৰি"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"আপোনাৰ আইটি প্ৰশাসকে আপোনাক আপোনাৰ ব্যক্তিগত প্ৰ\'ফাইলত থকা এপ্সমূহৰ জৰিয়তে এই সমলটো খুলিবলৈ নিদিয়ে"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"কৰ্মস্থানৰ প্ৰ\'ফাইলটো পজ কৰা আছে"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"অন কৰক"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"কোনো কর্মস্থানৰ এপে এই সমলটো সমর্থন কৰিব নোৱাৰে"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"কোনো কর্মস্থানৰ এপে এই সমলটো খুলিব নোৱাৰে"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"কোনো ব্যক্তিগত এপে এই সমলটো সমর্থন কৰিব নোৱাৰে"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"কোনো ব্যক্তিগত এপে এই সমলটো খুলিব নোৱাৰে"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"ছিম নেটৱৰ্ক আনলক কৰা পিন"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"ছিম নেটৱৰ্ক আনলক কৰা পিন"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"ছিম কৰ্পৰে\'ট আনলক কৰা পিন"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"আপোনাৰ স্ক্ৰীনখনৰ এটা অংশ বিবৰ্ধন কৰক"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"আপুনি এতিয়া আপোনাৰ পূৰ্ণ স্ক্ৰীন, কোনো নিৰ্দিষ্ট অংশ বিবৰ্ধন কৰিব পাৰে অথবা দুয়োটা বিকল্পৰ মাজত সলনা-সলনি কৰিব পাৰে।"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ছেটিঙত অন কৰক"</string>
<string name="dismiss_action" msgid="1728820550388704784">"অগ্ৰাহ্য কৰক"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"অব্যাহত ৰাখিবলৈ <b><xliff:g id="APP">%s</xliff:g></b>এ আপোনাৰ ডিভাইচৰ মাইক্ৰ’ফ’ন এক্সেছ কৰাৰ আৱশ্যক।"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 948b274..48e83b2 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Tətbiq işləyir"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareyadan istifadə edən tətbiqlər"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Böyütmə"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Əlçatımlılıq güvənlik siyasəti"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> batareyadan istifadə edir"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> tətbiq batareyadan istifadə edir"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya və data istifadəsi haqqında ətraflı məlumat üçün klikləyin"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"fiziki fəaliyyətə daxil olun"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"şəkil çəkin və video yazın"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"yaxınlıqdakı Bluetooth cihazları"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"yaxınlıqdakı Bluetooth cihazlarını aşkarlamaq və onlara qoşulmaq"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Zəng qeydləri"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"telefonun zəng qeydini oxuyun və yazın"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tətbiqə yerli Bluetooth planşetinin konfiqurasiyasını görməyə və cütlənmiş cihazlarla bağlantılar etməyə və qəbul etməyə imkan verir."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Tətbiqə Android TV cihazında Bluetooth konfiqurasiyasına baxmaq, həmçinin qoşulmuş cihazlar ilə bağlantılar yaratmaq və qəbul etmək icazəsi verir."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Tətbiqə Bluetooth və ya telefon konfiqurasiyalarını görməyə və qoşulmuş cihazlarla əlaqə qurmağa və qəbul etməyə icazə verir."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"yaxınlıqdakı Bluetooth cihazlarını aşkarlamaq və birləşdirmək"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Tətbiqə yaxınlıqdakı Bluetooth cihazlarını aşkarlamaq və birləşdirməyə icazə verir"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"birləşdirilmiş Bluetooth cihazlarına qoşulmaq"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Tətbiqə birləşdirilmiş Bluetooth cihazlarına qoşulmağa icazə verir"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Tərcih edilən NFC ödəniş xidməti məlumatı"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Tətbiqə qeydiyyatdan keçmiş yardım və marşrut təyinatı kimi tərcih edilən nfc ödəniş xidməti məlumatını əldə etmək icazəsi verir."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communication\'ı kontrol et"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Doğrulama zamanı xəta baş verdi"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekran kilidindən istifadə edin"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Davam etmək üçün cihazın giriş məlumatlarını daxil edin"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Barmaq izi yarımçıq müəyyən olundu. Lütfən, yenidən cəhd edin."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Barmaq izi tanınmadı. Lütfən, yenidən cəhd edin."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Barmaq izi sensoru çirklidir. Lütfən, təmizləyin və yenidən cəhd edin."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Barmağı çox tez tərpətdiniz. Yenidən edin."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Barmağınızı çox yavaş hərəkət etdirdiniz. Lütfən, yenidən cəhd edin."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Barmaq izi doğrulandı"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Üz doğrulandı"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Üz təsdiq edildi, təsdiq düyməsinə basın"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Barmaq izi üçün avadanlıq yoxdur."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Barmaq izi saxlana bilməz. Lütfən, mövcud barmaq izini silin."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Barmaq izinin vaxtı başa çatdı. Yenidən cəhd edin."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Barmaq izi əməliyyatı ləğv edildi."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Barmaq izi əməliyyatı istifadəçi tərəfindən ləğv edildi."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Üz kilidi"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Üzünüzü yenidən qeydiyyatdan keçirin"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Tanınmanı təkmilləşdirmək üçün üzünüzü yenidən qeydiyyatdan keçirin"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Dəqiq üz datası əldə edilmədi. Yenidən cəhd edin."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Çox işıqlıdır. Daha az işıqlı şəkli sınayın."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Çox qaranlıqdır. Parlaq işıqdan istifadə edin."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Kopyalandı"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> tətbiqindən əlavə edilib"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> mübadilə buferindən əlavə edilib"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Digər"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menyu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"İş"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Şəxsi məzmuna baxış"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"İş məzmununa baxış"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Bunu iş tətbiqləri ilə paylaşmaq mümkün deyil"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"İT admininiz bu məzmunu iş profilinizdəki tətbiqlər ilə paylaşmağa icazə vermir"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Bunu iş tətbiqləri ilə açmaq mümkün deyil"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"İT admininiz bu məzmunu iş profilinizdəki tətbiqlər ilə açmağa icazə vermir"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Bunu şəxsi tətbiqlərlə paylaşmaq mümkün deyil"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"İT admininiz bu məzmunu şəxsi profilinizdəki tətbiqlər ilə paylaşmağa icazə vermir"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Bunu şəxsi tətbiqlər ilə açmaq mümkün deyil"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"İT admininiz bu məzmunu şəxsi profilinizdəki tətbiqlər ilə açmağa icazə vermir"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"İş profilinə fasilə verilib"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Aktiv edin"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Bu məzmunu heç bir iş tətbiqi dəstəkləyə bilmir"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Bu məzmunu heç bir iş tətbiqi ilə açmaq mümkün deyil"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Bu məzmunu heç bir şəxsi tətbiq dəstəkləyə bilmir"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Bu məzmunu heç bir şəxsi tətbiq ilə açmaq mümkün deyil"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM şəbəkəsi kilidaçma PİN\'i"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM Şəbəkəsi Alt Dəstinin kilidaçma PIN\'i"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM korporativ kilidaçma PIN\'i"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Ekranın bir hissəsini böyüdün"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"İndi tam ekranı, müəyyən sahəni böyüdə və ya iki seçim arasında keçid edə bilərsiniz."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ayarlarda aktiv edin"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Qapadın"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Davam etmək üçün <b><xliff:g id="APP">%s</xliff:g></b> tətbiqi cihazın mikrofonuna giriş tələb edir."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 9c18a07..78fce43 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -297,7 +297,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aktivna aplikacija"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Uvećanje"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Bezbednosne smernice za pristupačnost"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikacije (<xliff:g id="NUMBER">%1$d</xliff:g>) koriste bateriju"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o bateriji i potrošnji podataka"</string>
@@ -322,6 +323,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"pristup fizičkim aktivnostima"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"snima slike i video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Bluetooth uređaji u blizini"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"otkrivanje i povezivanje sa Bluetooth uređajima u blizini"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Evidencije poziva"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"čitanje i pisanje evidencije poziva na telefonu"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -535,6 +538,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Dozvoljava aplikaciji da pregleda konfiguraciju Bluetooth-a na tabletu, kao i da uspostavlja i prihvata veze sa uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Dozvoljava aplikaciji da pregleda konfiguraciju Bluetooth-a na Android TV uređaju i da uspostavlja i prihvata veze sa uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Dozvoljava aplikaciji da pregleda konfiguraciju Bluetooth-a na telefonu, kao i da uspostavlja i prihvata veze sa uparenim uređajima."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"otkrivanje i uparivanje sa obližnjim Bluetooth uređ."</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Dozvoljava aplikaciji da otkriva Bluetooth uređaje u blizini i uparuje se sa njima"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"povezivanje sa uparenim Bluetooth uređajima"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Dozvoljava aplikaciji da se povezuje sa uparenim Bluetooth uređajima"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informacije o željenoj NFC usluzi za plaćanje"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Dozvoljava aplikaciji da preuzima informacije o željenoj NFC usluzi za plaćanje, poput registrovanih identifikatora aplikacija i odredišta preusmeravanja."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrola komunikacije u užem polju (Near Field Communication)"</string>
@@ -570,18 +577,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Greška pri potvrdi identiteta"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Koristite zaključavanje ekrana"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Unesite akreditiv za uređaj da biste nastavili"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Otkriven je delimični otisak prsta. Probajte ponovo."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Nije uspela obrada otiska prsta. Probajte ponovo."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Senzor za otiske prstiju je prljav. Očistite ga i pokušajte ponovo."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Prebrzo ste pomerili prst. Probajte ponovo."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Previše sporo ste pomerili prst. Probajte ponovo."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Otisak prsta je potvrđen"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Lice je potvrđeno"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je potvrđeno. Pritisnite Potvrdi"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardver za otiske prstiju nije dostupan."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Nije moguće sačuvati otisak prsta. Uklonite neki od postojećih otisaka prstiju."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Vremensko ograničenje za otisak prsta je isteklo. Probajte ponovo."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Radnja sa otiskom prsta je otkazana."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Korisnik je otkazao radnju sa otiskom prsta."</string>
@@ -606,6 +623,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Otključavanje licem"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Ponovo registrujte lice"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Da biste poboljšali prepoznavanje, ponovo registrujte lice"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Snimanje lica nije uspelo. Probajte ponovo."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Previše je svetlo. Probajte sa slabijim osvetljenjem."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Pretamno je. Probajte sa jačim osvetljenjem."</string>
@@ -1009,6 +1034,12 @@
<string name="copied" msgid="4675902854553014676">"Kopirano je"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Aplikacija<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je nalepila podatke iz aplikacije <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Aplikacija<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> nalepila podatke iz privremene memorije"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Još"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Meni+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2144,20 +2175,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Poslovno"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Lični prikaz"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Prikaz za posao"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Ne možete da delite ovaj sadržaj pomoću aplikacija za posao"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT administrator vam ne dozvoljava da delite ovaj sadržaj pomoću aplikacija na poslovnom profilu"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Ne možete da otvorite ovaj sadržaj pomoću aplikacija za posao"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT administrator vam ne dozvoljava da otvorite ovaj sadržaj pomoću aplikacija na poslovnom profilu"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Ne možete da delite ovaj sadržaj pomoću ličnih aplikacija"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT administrator vam ne dozvoljava da delite ovaj sadržaj pomoću aplikacija na ličnom profilu"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Ne možete da otvorite ovaj sadržaj pomoću ličnih aplikacija"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT administrator vam ne dozvoljava da otvorite ovaj sadržaj pomoću aplikacija na ličnom profilu"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Poslovni profil je pauziran"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Uključi"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Nijedna aplikacija za posao ne podržava ovaj sadržaj"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Nijedna aplikacija za posao ne može da otvori ovaj sadržaj"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Nijedna lična aplikacija ne može da podržava ovaj sadržaj"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Nijedna lična aplikacija ne može da otvori ovaj sadržaj"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN za otključavanje SIM mreže"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN za otključavanje podskupa SIM mreže"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN za otključavanje poslovne SIM kartice"</string>
@@ -2270,8 +2312,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Uvećajte prikaz dela ekrana"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Sada možete da uvećate ceo ekran, određenu oblast ili da prelazite sa jedne opcije na drugu."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Podešavanjima"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"<b><xliff:g id="APP">%s</xliff:g></b> zahteva pristup mikrofonu uređaja radi nastavljanja."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 5175f47..12a9b42 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -300,7 +300,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Праграма працуе"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Праграмы, якія выкарыстоўваюць акумулятар"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Павелічэнне"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Палітыка бяспекі спецыяльных магчымасцей"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> выкарыстоўвае акумулятар"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Наступная колькасць праграм выкарыстоўваюць акумулятар: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Дакраніцеся, каб даведацца пра выкарыстанне трафіка і акумулятара"</string>
@@ -325,6 +326,10 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"доступ да даных фізічнай актыўнасці"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Камера"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"рабіць фатаздымкі і запісваць відэа"</string>
+ <!-- no translation found for permgrouplab_nearby_devices (14428105203684587) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_nearby_devices (1146639974734121820) -->
+ <skip />
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Журналы выклікаў"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"Чытанне і запіс журнала тэлефонных выклікаў"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Тэлефон"</string>
@@ -525,9 +530,9 @@
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"Дазваляе праграме атрымліваць пакеты, адпраўленыя на ўсе прылады ў сетцы Wi-Fi з дапамогай групавых адрасоў, а не толькі на вашу прыладу Android TV. Праз гэта будзе спажывацца больш энергіі, чым у рэжыме нешматадраснай перадачы."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"Дазваляе прыкладанням атрымліваць пакеты, адпраўленыя на ўсе прылады з сеткi Wi-Fi з дапамогай групавых адрасоў, а не толькі на ваш тэлефон. Будзе выкарыстоўвацца больш энергіі, чым у рэжыме нешматадраснай перадачы."</string>
<string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"атрыманне доступу да налад прылады Bluetooth"</string>
- <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"Дазваляе прыкладанням наладжваць лакальны планшэт Bluetooth, выяўляць і падлучаць выдаленыя прылады."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"Дазваляе праграме наладжваць лакальны планшэт Bluetooth, выяўляць і спалучаць выдаленыя прылады."</string>
<string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Дазваляе праграме наладжваць канфігурацыю Bluetooth на прыладзе Android TV, а таксама выяўляць аддаленыя прылады і спалучацца з імі."</string>
- <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"Дазваляе прыкладанням наладжваць лакальны тэлефон Bluetooth, а таксама знаходзіць выдаленыя прылады i падлучацца да ix."</string>
+ <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"Дазваляе праграме наладжваць лакальны тэлефон Bluetooth, а таксама знаходзіць выдаленыя прылады i спалучаць ix."</string>
<string name="permlab_accessWimaxState" msgid="7029563339012437434">"падключаць да WiMAX i адключаць ад яго"</string>
<string name="permdesc_accessWimaxState" msgid="5372734776802067708">"Дазваляе прыкладанню вызначаць, ці ўключаны WiMAX, і інфармацыю пра любую сетку WiMAX, якая спалучана з iншымi."</string>
<string name="permlab_changeWimaxState" msgid="6223305780806267462">"Змяніць стан WiMAX"</string>
@@ -538,6 +543,14 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Дазваляе прыкладанню праглядаць канфігурацыю Bluetooth на планшэце , а таксама здзяйсняць і прымаць злучэнні са спалучанымі прыладамі."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Дазваляе праграме праглядаць канфігурацыю Bluetooth на прыладзе Android TV, а таксама выконваць і дазваляць злучэнні са спалучанымі прыладамі."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Дазваляе прыкладанню праглядаць канфігурацыю Bluetooth на тэлефоне , а таксама здзяйсняць і прымаць злучэнні са спалучанымі прыладамі."</string>
+ <!-- no translation found for permlab_bluetooth_scan (5402587142833124594) -->
+ <skip />
+ <!-- no translation found for permdesc_bluetooth_scan (6540723536925289276) -->
+ <skip />
+ <!-- no translation found for permlab_bluetooth_connect (6657463246355003528) -->
+ <skip />
+ <!-- no translation found for permdesc_bluetooth_connect (4546016548795544617) -->
+ <skip />
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Інфармацыя пра прыярытэтны сэрвіс аплаты NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дазваляе праграме атрымаць доступ да інфармацыі пра прыярытэтны сэрвіс аплаты NFC, напрыклад зарэгістраваныя ідэнтыфікатары праграм і маршруты адпраўкі даных."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"кантроль Near Field Communication"</string>
@@ -573,18 +586,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Памылка аўтэнтыфікацыі"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ужываць блакіроўку экрана"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Каб працягнуць, увядзіце ўліковыя даныя вашай прылады"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Адсканіравана толькі частка адбітка пальца. Паспрабуйце яшчэ раз."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Не атрымалася апрацаваць адбітак пальца. Паспрабуйце яшчэ раз."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Сканер адбіткаў пальцаў брудны. Ачысціце яго і паспрабуйце яшчэ раз."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Вы занадта хутка паднялі палец. Паспрабуйце яшчэ раз."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Палец рухаўся занадта павольна. Паспрабуйце яшчэ раз."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Адбітак пальца распазнаны"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Твар распазнаны"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Твар распазнаны. Націсніце, каб пацвердзіць"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Апаратныя сродкі адбіткаў пальцаў недаступныя."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Адбіткі пальцаў нельга захаваць. Выдаліце існуючы адбітак."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Час чакання выйшаў. Паспрабуйце яшчэ раз."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Аперацыя з адбіткамі пальцаў скасавана."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Аўтэнтыфікацыя па адбітках пальцаў скасавана карыстальнікам."</string>
@@ -609,6 +632,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Распазнаванне твару"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Паўтарыце рэгістрацыю твару"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Каб палепшыць распазнавальнасць, яшчэ раз выканайце рэгістрацыю твару"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Не атрымалася распазнаць твар. Паўтарыце спробу."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Занадта светла. Прыглушыце асвятленне."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Занадта цёмна. Павялічце асвятленне."</string>
@@ -1012,6 +1043,12 @@
<string name="copied" msgid="4675902854553014676">"Скапіравана"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Праграма \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\" была ўстаўлена з праграмы \"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>\""</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Праграма \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\" была ўстаўлена з буфера абмену"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Больш"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Меню+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -1394,7 +1431,7 @@
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Тэставы рэжым уключаны"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Каб выключыць тэставы рэжым, скіньце налады да заводскіх значэнняў."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"Паслядоўная кансоль уключана"</string>
- <string name="console_running_notification_message" msgid="7892751888125174039">"Паказчык эфектыўнасці змяніўся. Каб выключыць кансоль, праверце загрузчык."</string>
+ <string name="console_running_notification_message" msgid="7892751888125174039">"Паказчык прадукцыйнасці змяніўся. Каб выключыць кансоль, праверце загрузчык."</string>
<string name="usb_contaminant_detected_title" msgid="4359048603069159678">"Вадкасць або смецце ў порце USB"</string>
<string name="usb_contaminant_detected_message" msgid="7346100585390795743">"Порт USB аўтаматычна адключаны. Каб даведацца больш, націсніце тут."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"Порт USB можна выкарыстоўваць"</string>
@@ -2178,20 +2215,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Працоўныя"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Прагляд асабістага змесціва"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Прагляд працоўнага змесціва"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Не ўдалося абагуліць гэта змесціва з працоўнымі праграмамі"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Ваш ІТ-адміністратар не дазволіў вам абагульваць гэта змесціва з праграмамі ў вашым працоўным профілі"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Не ўдалося адкрыць гэта змесціва з працоўнымі праграмамі"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Ваш ІТ-адміністратар не дазволіў вам адкрываць гэта змесціва з праграмамі ў вашым працоўным профілі"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Не ўдалося абагуліць гэта змесціва з асабістымі праграмамі"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Ваш ІТ-адміністратар не дазволіў вам абагульваць гэта змесціва з праграмамі ў вашым асабістым профілі"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Не ўдалося адкрыць гэта змесціва з асабістымі праграмамі"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Ваш ІТ-адміністратар не дазволіў вам адкрываць гэта змесціва з праграмамі ў вашым асабістым профілі"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Працоўны профіль прыпынены"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Уключыць"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Няма працоўных праграм, якія могуць падтрымліваць гэта змесціва"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Няма працоўных праграм, якія могуць адкрываць гэта змесціва"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Няма асабістых праграм, якія могуць падтрымліваць гэта змесціва"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Няма асабістых праграм, якія могуць адкрываць гэта змесціва"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-код разблакіроўкі сеткі для SIM-карты"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-код разблакіроўкі падмноства сеткі для SIM-карты"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-код разблакіроўкі карпаратыўнай SIM-карты"</string>
@@ -2304,8 +2352,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Павялічыць частку экрана"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Цяпер можна павялічваць увесь экран, яго пэўную частку ці пераключацца паміж гэтымі двума варыянтамі."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Уключыць у Наладах"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Адхіліць"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Каб працягнуць, дайце праграме <b><xliff:g id="APP">%s</xliff:g></b> доступ да мікрафона прылады."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 0b3e04a..258dad5 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Приложението работи"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, използващи батерията"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увеличение"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Правила за сигурност на услугите за достъпност"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> използва батерията"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> приложения използват батерията"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Докоснете за информация относно използването на батерията и преноса на данни"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"достъп до физическата ви активност"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Камера"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"да прави снимки и записва видео"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Устройства с Bluetooth в близост"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"откриване на устройства с Bluetooth в близост и свързване с тях"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Списъци с обажданията"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"четене и запис на списъка с телефонните обаждания"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Телефон"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Разрешава на приложението да вижда конфигурацията на Bluetooth на таблета и да изгражда и приема връзки със сдвоени устройства."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Дава възможност на приложението да преглежда конфигурацията на Bluetooth на устройството ви с Android TV и да създава и приема връзки със сдвоени устройства."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Разрешава на приложението да вижда конфигурацията на Bluetooth на телефона и да изгражда и приема връзки със сдвоени устройства."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"откриване и сдвояване с у-ва с Bluetooth в близост"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Дава възможност на приложението да открива устройства с Bluetooth в близост и да се сдвоява с тях"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"свързване със сдвоените устройства с Bluetooth"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Дава възможност на приложението да се свързва със сдвоените устройства с Bluetooth"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Информация за предпочитаната услуга за плащане чрез NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дава възможност на приложението да получава информация за предпочитаната услуга за плащане чрез NFC, като например регистрирани помощни средства и местоназначение."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"контролиране на комуникацията в близкото поле"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Грешка при удостоверяването"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ползване на заключв. на екрана"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Въведете идентификационните данни на устройството, за да продължите"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Открит е частичен отпечатък. Моля, опитайте отново."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Отпечатъкът не бе обработен. Моля, опитайте отново."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Сензорът за отпечатъци е мръсен. Моля, почистете го и опитайте отново."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Отместихте пръста си твърде бързо. Моля, опитайте отново."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Преместихте пръста си твърде бавно. Моля, опитайте отново."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Отпечатъкът е удостоверен"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лицето е удостоверено"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицето е удостоверено. Моля, натиснете „Потвърждаване“"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Хардуерът за отпечатъци не е налице."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Отпечатъкът не може да бъде съхранен. Моля, премахнете съществуващ."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Времето за изчакване за отпечатък изтече. Опитайте отново."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Операцията за отпечатък е анулирана."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Операцията за удостоверяване чрез отпечатък бе анулирана от потребителя."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Отключване с лице"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Регистрирайте отново лицето си"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"С цел подобряване на разпознаването регистрирайте отново лицето си"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Лицето не бе заснето точно. Опитайте отново."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Твърде светло е. Опитайте при по-слабо осветление."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Твърде тъмно е. Опитайте при по-силно осветление."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Копирано"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> постави данни от <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> постави данни от буферната памет"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Още"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Меню+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Служебни"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Личен изглед"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Служебен изглед"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Споделянето чрез служебни приложения не е възможно"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Системният ви администратор не разрешава споделянето на това съдържание с приложения в служебния ви потребителски профил"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Отварянето със служебни приложения не е възможно"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Системният ви администратор не разрешава отварянето на това съдържание с приложения в служебния ви потребителски профил"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Споделянето чрез лични приложения не е възможно"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Системният ви администратор не разрешава споделянето на това съдържание с приложения в личния ви потребителски профил"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Отварянето с лични приложения не е възможно"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Системният ви администратор не разрешава отварянето на това съдържание с приложения в личния ви потребителски профил"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Служебният потребителски профил е поставен на пауза"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Включване"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Това съдържание не се поддържа от нито едно служебно приложение"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Това съдържание не може да се отвори от нито едно служебно приложение"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Това съдържание не се поддържа от нито едно лично приложение"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Това съдържание не може да се отвори от нито едно лично приложение"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"ПИН за отключване на мрежата за SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"ПИН за отключване на подмножеството от мрежи за SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"ПИН за отключване на корпоративната SIM карта"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Увеличаване на част от екрана"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Вече можете да увеличавате целия екран или конкретна област от него, както и да превключвате между двете опции."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Включете от настройките"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Отхвърляне"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"За да продължите, <b><xliff:g id="APP">%s</xliff:g></b> се нуждае от достъп до микрофона на устройството ви."</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 678cb21..5582330 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -293,8 +293,9 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB সংযোগ"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"অ্যাপ চলছে"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"কিছু অ্যাপ ব্যাটারি ব্যবহার করছে"</string>
- <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বড় করে দেখুন"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"অ্যাক্সেসিবিলিটি সুরক্ষা নীতি"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বড় করে দেখা"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপটি ব্যাটারি ব্যবহার করছে"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টি অ্যাপ ব্যাটারি ব্যবহার করছে"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ব্যাটারি এবং ডেটার ব্যবহারের বিশদ বিবরণের জন্য ট্যাপ করুন"</string>
@@ -319,6 +320,10 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"শারীরিক অ্যাক্টিভিটি অ্যাক্সেস করা"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"ক্যামেরা"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ছবি তোলা এবং ভিডিও রেকর্ড"</string>
+ <!-- no translation found for permgrouplab_nearby_devices (14428105203684587) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_nearby_devices (1146639974734121820) -->
+ <skip />
<string name="permgrouplab_calllog" msgid="7926834372073550288">"কল লগ"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ফোন কল লগ পড়ে এবং দেখে"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ফোন"</string>
@@ -532,6 +537,14 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ট্যাবলেটের ব্লুটুথ কনফিগারেশন দেখতে, এবং যুক্ত ডিভাইসগুলির সাথে সংযোগ স্থাপন এবং সংযোগের অনুরোধ স্বীকার করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"আপনার Android TV ডিভাইসের ব্লুটুথের কনফিগারেশন দেখার এবং পেয়ার করা ডিভাইসের সাথে কানেক্ট করার বা কানেকশন গ্রহণ করার অনুমতি দেয়।"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ফোনের ব্লুটুথ কনফিগারেশন দেখতে, এবং যুক্ত ডিভাইসগুলির সাথে সংযোগ স্থাপন এবং সংযোগের অনুরোধ স্বীকার করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷"</string>
+ <!-- no translation found for permlab_bluetooth_scan (5402587142833124594) -->
+ <skip />
+ <!-- no translation found for permdesc_bluetooth_scan (6540723536925289276) -->
+ <skip />
+ <!-- no translation found for permlab_bluetooth_connect (6657463246355003528) -->
+ <skip />
+ <!-- no translation found for permdesc_bluetooth_connect (4546016548795544617) -->
+ <skip />
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"পছন্দের NFC পেমেন্ট পরিষেবার তথ্য"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"অ্যাপের মাধ্যমে পছন্দসই এনএফসি পেমেন্ট পরিষেবার তথ্য, যেমন রেজিস্ট্রার করার সহায়তা এবং রুট ডেস্টিনেশন সম্পর্কিত তথ্য অ্যাক্সেস করার অনুমতি দেয়।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"নিয়ার ফিল্ড কমিউনিকেশন নিয়ন্ত্রণ করে"</string>
@@ -567,18 +580,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"যাচাইকরণে সমস্যা হয়েছে"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"স্ক্রিন লক ব্যবহার করুন"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"চালিয়ে যেতে আপনার ডিভাইসের ক্রেডেনশিয়াল ব্যবহার করুন"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"আঙ্গুলের ছাপ আংশিক শনাক্ত করা হয়েছে৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"আঙ্গুলের ছাপ প্রক্রিয়া করা যায়নি৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"আঙ্গুলের ছাপ নেওয়ার সেন্সরটি অপরিস্কার৷ পরিষ্কার করে আবার চেষ্টা করুন৷"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"আঙ্গুল অতি দ্রুত সরানো হয়েছে৷ আবার চেষ্টা করুন৷"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"আঙ্গুল খুব ধীরে সরানো হয়েছে৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"আঙ্গুলের ছাপ যাচাই করা হয়েছে"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ফেস যাচাই করা হয়েছে"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ফেস যাচাই করা হয়েছে, \'কনফার্ম করুন\' বোতাম প্রেস করুন"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার অনুপলব্ধ৷"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"আঙ্গুলের ছাপ সংরক্ষণ করা যাবে না৷ অনুগ্রহ করে একটি বিদ্যমান আঙ্গুলের ছাপ সরান৷"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"আঙ্গুলের ছাপ নেওয়ার সময়সীমা শেষ হযেছে৷ আবার চেষ্টা করুন৷"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"আঙ্গুলের ছাপ অপারেশন বাতিল করা হয়েছে৷"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ব্যবহারকারী আঙ্গুলের ছাপের অপারেশনটি বাতিল করেছেন।"</string>
@@ -603,6 +626,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"মুখের সাহায্যে আনলক"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"আপনার ফেস আবার এনরোল করুন"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"শনাক্তকরণের উন্নতি করতে আপনার ফেস আবার এনরোল করুন"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"মুখের সঠিক ডেটা পাওয়া যায়নি। আবার চেষ্টা করুন।"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"খুব উজ্জ্বল। আলো কমিয়ে চেষ্টা করে দেখুন।"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"খুব অন্ধকার। আরও উজ্জ্বল আলো ব্যবহার করে দেখুন।"</string>
@@ -1006,6 +1037,12 @@
<string name="copied" msgid="4675902854553014676">"কপি করা হয়েছে"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> থেকে কপি করা ডেটা <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-এ পেস্ট করা হয়েছে"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"ক্লিপবোর্ডের ডেটা <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-এ পেস্ট করা হয়েছে"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"আরও"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"মেনু+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2147,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"অফিস"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ব্যক্তিগত ভিউ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"অফিসের ভিউ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"অফিস অ্যাপের মাধ্যমে শেয়ার করা যাবে না"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"আইটি অ্যাডমিন আপনার অফিস প্রোফাইল ব্যবহার করে অ্যাপের মাধ্যমে এই কন্টেন্ট শেয়ার করার অনুমতি দেয় না"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"অফিসের অ্যাপের মাধ্যমে এটি খোলা যাবে না"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"আইটি অ্যাডমিন আপনার অফিস প্রোফাইল ব্যবহার করে অ্যাপের মাধ্যমে এই কন্টেন্ট খোলার অনুমতি দেয় না"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"ব্যক্তিগত অ্যাপের মাধ্যমে শেয়ার করা যাবে না"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"আইটি অ্যাডমিন আপনার ব্যক্তিগত প্রোফাইল ব্যবহার করে অ্যাপের মাধ্যমে এই কন্টেন্ট শেয়ার করার অনুমতি দেয় না"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"ব্যক্তিগত অ্যাপের মাধ্যমে খোলা যাবে না"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"আইটি অ্যাডমিন আপনার ব্যক্তিগত প্রোফাইল ব্যবহার করে অ্যাপের মাধ্যমে এই কন্টেন্ট খোলার অনুমতি দেয় না"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"অফিস প্রোফাইল বন্ধ করা আছে"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"চালু করুন"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"এই ধরনের কন্টেন্ট অফিস অ্যাপের মাধ্যমে খোলা যাবে না"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"এই ধরনের কন্টেন্ট অফিসের অ্যাপের মাধ্যমে খুলে দেখা যাবে না"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"এই ধরনের কন্টেন্ট ব্যক্তিগত অ্যাপের মাধ্যমে খোলা বা দেখা যাবে না"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"এই ধরনের কন্টেন্ট ব্যক্তিগত অ্যাপের মাধ্যমে খোলা যাবে না"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"সিম নেটওয়ার্ক আনলক পিন"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"সিম নেটওয়ার্ক সাবসেট আনলক পিন"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"কর্পোরেট সিম আনলক পিন"</string>
@@ -2236,8 +2284,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"স্ক্রিনের কোনও অংশ বড় করে দেখা"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"এখন আপনি সম্পূর্ণ স্ক্রিন বা এর কোনও অংশ বড় করে দেখতে পারেন অথবা দুটি বিকল্পের মধ্যে পারস্পরিক পরিবর্তন করতে পারেন।"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"সেটিংস থেকে চালু করুন"</string>
<string name="dismiss_action" msgid="1728820550388704784">"বাতিল করুন"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"চালিয়ে যেতে, <b><xliff:g id="APP">%s</xliff:g></b> আপনার ডিভাইসের মাইক্রোফোন অ্যাক্সেস করতে চায়।"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index d6e0f32..b6d478f 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -297,7 +297,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Pokrenuta aplikacija"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Uvećavanje"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Pravila o sigurnosti za pristupačnost"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> troši bateriju"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje troše bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string>
@@ -322,6 +323,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"pristup vašoj fizičkoj aktivnosti"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"snima fotografije i videozapise"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Bluetooth uređaji u blizini"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"otkrivanje Bluetooth uređaja u blizini i povezivanje s njima"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Zapisnici poziva"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"čitanje i pisanje zapisnika telefonskih poziva"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -535,6 +538,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Omogućava aplikaciji prikaz konfiguracije za Bluetooth na tabletu, kao i uspostavljanje i prihvatanje veza sa uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Omogućava aplikaciji da prikaže konfiguraciju Bluetootha na Android TV uređaju te uspostavi i prihvati vezu s uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Omogućava aplikaciji prikaz konfiguracije za Bluetooth na telefonu, kao i uspostavljanje i prihvatanje veza sa uparenim uređajima."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"otkrivanje i upariv. s Bluetooth uređajima u blizini"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Dozvoljava aplikaciji da otkrije Bluetooth uređaje u blizini i upari se s njima"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"povezivanje s uparenim Bluetooth uređajima"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Dozvoljava aplikaciji da se poveže s uparenim Bluetooth uređajima"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informacije o preferiranoj usluzi plaćanja putem NFC-a"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Dozvoljava aplikaciji da dobije informacije o preferiranoj usluzi plaćanja putem NFC-a kao što su registrirana pomagala i odredište rute."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"upravljanje NFC-om"</string>
@@ -570,18 +577,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Greška pri autentifikaciji"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Koristi zaključavanje ekrana"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Unesite akreditiv uređaja da nastavite"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Otkriven je djelimični otisak prsta. Pokušajte ponovo."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Obrada otiska prsta nije uspjela. Pokušajte ponovo."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Senzor za otisak prsta je prljav. Očistite ga i pokušajte ponovo."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Prebrzo ste pomjerili prst. Pokušajte ponovo."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Presporo ste pomjerili prst. Pokušajte ponovo."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Otisak prsta je potvrđen"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Lice je provjereno"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je provjereno, pritisnite dugme za potvrdu"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardver za otisak prsta nije dostupan."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Otisak prsta se ne može pohraniti. Uklonite postojeći otisak prsta."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Vrijeme za prepoznavanje otiska prsta je isteklo. Pokušajte ponovo."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Radnja s otiskom prsta je otkazana."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Korisnik je otkazao radnju s otiskom prsta."</string>
@@ -606,6 +623,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Otključavanje licem"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Ponovo registrirajte lice"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Ponovo registrirajte lice da poboljšate prepoznavanje"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Lice nije snimljeno precizno. Pokušajte ponovo."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Previše svijetlo. Probajte s blažim osvjetljenjem."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Previše je tamno. Pokušajte s jačim osvjetljenjem."</string>
@@ -1009,6 +1034,12 @@
<string name="copied" msgid="4675902854553014676">"Kopirano"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je zalijepljena iz aplikacije <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je zalijepljena iz međumemorije"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Više"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Meni+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1374,7 +1405,7 @@
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Omogućen način rada okvira za testiranje"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Izvršite vraćanje na fabričke postavke da onemogućite način rada okvira za testiranje."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"Serijska konzola omogućena"</string>
- <string name="console_running_notification_message" msgid="7892751888125174039">"Izvedba je otežana. Da onemogućite, provjerite program za učitavanje operativnog sistema."</string>
+ <string name="console_running_notification_message" msgid="7892751888125174039">"Performanse su smanjene. Da onemogućite, provjerite program za učitavanje operativnog sistema."</string>
<string name="usb_contaminant_detected_title" msgid="4359048603069159678">"Tečnost ili nečistoće u USB priključku"</string>
<string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB priključak je automatski onemogućen. Dodirnite da saznate više."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"USB priključak je sada sigurno koristiti"</string>
@@ -1711,7 +1742,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Koristi prečicu"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Ispravka boja"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamnjenje"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamnjeno"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je uključena."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite obje tipke za podešavanje jačine zvuka i držite ih pritisnutim tri sekunde da koristite uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -2144,20 +2175,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Posao"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Prikaz ličnog sadržaja"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Prikaz poslovnog sadržaja"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Nije moguće dijeliti ovo putem poslovnih aplikacija"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Vaš IT administrator ne dozvoljava da dijelite ovaj sadržaj putem aplikacija na svom poslovnom profilu"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Nije moguće otvoriti ovo s poslovnim aplikacijama"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Vaš IT administrator ne dozvoljava da otvorite ovaj sadržaj putem aplikacija na svom poslovnom profilu"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Nije moguće dijeliti ovo putem ličnih aplikacija"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Vaš IT administrator ne dozvoljava da dijelite ovaj sadržaj putem aplikacija na svom ličnom profilu"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Nije moguće otvoriti ovo s ličnim aplikacijama"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Vaš IT administrator ne dozvoljava da otvorite ovaj sadržaj putem aplikacija na svom ličnom profilu"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Radni profil je pauziran"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Uključi"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Nijedna poslovna aplikacija ne može podržati ovaj sadržaj"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Nijedna poslovna aplikacija ne može otvoriti ovaj sadržaj"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Nijedna lična aplikacija ne može podržati ovaj sadržaj"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Nijedna lična aplikacija ne može otvoriti ovaj sadržaj"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN za otključavanje mreže na SIM-u"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN za otključavanje mrežne podgrupe na SIM-u"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN za otključavanje korporativnog SIM-a"</string>
@@ -2270,8 +2312,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Uvećajte dio ekrana"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Sada možete uvećati prikaz preko cijelog ekrana, željeno područje ili prebacivati s jedne opcije na drugu."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Postavkama"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Da nastavite, aplikaciji <b><xliff:g id="APP">%s</xliff:g></b> je potreban pristup mikrofonu vašeg uređaja."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 5f2904c..023ec09 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicació en execució"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacions que consumeixen bateria"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliació"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Política de seguretat de l\'accessibilitat"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> està consumint bateria"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacions estan consumint bateria"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca per obtenir informació sobre l\'ús de dades i de bateria"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"accedir a la teva activitat física"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Càmera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"fer fotos i gravar vídeos"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Dispositius Bluetooth propers"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"detectar i connectar-se a dispositius Bluetooth propers"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Registres de trucades"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"llegir i editar el registre de trucades del telèfon"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telèfon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permet que l\'aplicació visualitzi la configuració del Bluetooth de la tauleta i que estableixi i accepti connexions amb dispositius sincronitzats."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permet que l\'aplicació visualitzi la configuració del Bluetooth del dispositiu Android TV i que estableixi i accepti connexions amb dispositius vinculats."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permet que una aplicació visualitzi la configuració del Bluetooth del telèfon i que estableixi i accepti connexions amb els dispositius sincronitzats."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"detectar i vincular dispositius Bluetooth propers"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permet que l\'aplicació detecti i vinculi dispositius Bluetooth propers"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"connectar-se a dispositius Bluetooth vinculats"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permet que l\'aplicació es connecti a dispositius Bluetooth vinculats"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informació preferent sobre el servei de pagament per NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permet que l\'aplicació obtingui informació preferent sobre el servei de pagament per NFC, com ara complements registrats i destinacions de rutes."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar Comunicació de camp proper (NFC)"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Error en l\'autenticació"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utilitza el bloqueig de pantalla"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Utilitza les credencials del teu dispositiu per continuar"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"S\'ha detectat una empremta digital parcial. Torna-ho a provar."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"No s\'ha pogut processar l\'empremta digital. Torna-ho a provar."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"El sensor d\'empremtes dactilars està brut. Neteja\'l i torna-ho a provar."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"El dit s\'ha mogut massa ràpid. Torna-ho a provar."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"El dit s\'ha mogut massa lentament. Torna-ho a provar."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"L\'empremta digital s\'ha autenticat"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Cara autenticada"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Cara autenticada; prem el botó per confirmar"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"El maquinari d\'empremtes digitals no està disponible."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"L\'empremta digital no es pot desar. Suprimeix-ne una."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"S\'ha cancel·lat l\'operació d\'empremta digital."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"L\'usuari ha cancel·lat l\'operació d\'empremta digital."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Desbloqueig facial"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Torna a registrar la cara"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Per millorar el reconeixement, torna a registrar la cara"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"No es reconeix la teva cara. Torna-ho a provar."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Massa brillant Prova una il·luminació més suau."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Massa fosc. Prova una il·luminació més brillant."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"S\'ha copiat"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha enganxat dades de: <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha enganxat dades del porta-retalls"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Més"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menú+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,7 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilitza la drecera"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversió de colors"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correcció de color"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extratènue"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuació extra"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S\'han mantingut premudes les tecles de volum. S\'ha activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S\'han mantingut premudes les tecles de volum. S\'ha desactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premudes les dues tecles de volum durant 3 segons per fer servir <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Feina"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Visualització personal"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Visualització de treball"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"No es pot compartir amb aplicacions de treball"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"L\'administrador de TI no et permet compartir aquest contingut amb aplicacions del teu perfil de treball"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"No es pot obrir amb aplicacions de treball"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"L\'administrador de TI no et permet obrir aquest contingut amb aplicacions del teu perfil de treball"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"No es pot compartir amb aplicacions personals"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"L\'administrador de TI no et permet compartir aquest contingut amb aplicacions del teu perfil personal"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"No es pot obrir amb aplicacions personals"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"L\'administrador de TI no et permet obrir aquest contingut amb aplicacions del teu perfil personal"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"El perfil de treball està en pausa"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Activa"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"No hi ha cap aplicació de treball compatible amb aquest contingut"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"No hi ha cap aplicació de treball que pugui obrir aquest contingut"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"No hi ha cap aplicació personal compatible amb aquest contingut"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"No hi ha cap aplicació personal que pugui obrir aquest contingut"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN de desbloqueig de la xarxa SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN de desbloqueig de subconjunt de la xarxa SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN de desbloqueig de la SIM corporativa"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Amplia una part de la pantalla"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Ara pots ampliar la pantalla completa o una àrea concreta, o canviar d\'una opció a l\'altra."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activa a Configuració"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Ignora"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Per continuar, <b><xliff:g id="APP">%s</xliff:g></b> necessita accedir al micròfon del dispositiu."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 6732b96..34846ec 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -300,7 +300,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikace je spuštěna"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikace spotřebovávají baterii"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zvětšení"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Zásady zabezpečení přístupnosti"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> využívá baterii"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikace (<xliff:g id="NUMBER">%1$d</xliff:g>) využívají baterii"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o využití baterie a dat"</string>
@@ -325,6 +326,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"přístup k vaší fyzické aktivitě"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Fotoaparát"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"pořizování fotografií a nahrávání videa"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Zařízení Bluetooth v okolí"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"vyhledávat zařízení Bluetooth v okolí a připojovat se k nim"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Seznamy hovorů"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"čtení a zápis do seznamu telefonních hovorů"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -538,6 +541,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Umožňuje aplikaci zobrazit konfiguraci tabletu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Umožňuje aplikaci zobrazit konfiguraci rozhraním Bluetooth na zařízení Android TV a vytvářet a přijímat připojení ke spárovaným zařízením."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Umožňuje aplikaci zobrazit konfiguraci telefonu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"vyhledávat a párovat zařízení Bluetooth v okolí"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Umožňuje aplikaci vyhledávat zařízení Bluetooth v okolí a spárovávat se s nimi"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"připojovat se ke spárovaným zařízením Bluetooth"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Umožňuje aplikaci připojovat se ke spárovaným zařízením Bluetooth"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informace o preferované platební službě NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Umožňuje aplikaci získat informace o preferované platební službě NFC, například o registrovaných pomůckách a cíli směrování."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ovládání technologie NFC"</string>
@@ -573,18 +580,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Při ověřování došlo k chybě"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Použít zámek obrazovky"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Pokračujte zadáním identifikačních úřadů svého zařízení"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Byla zjištěna jen část otisku prstu. Zkuste to znovu."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Zpracování otisku prstu se nezdařilo. Zkuste to znovu."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Senzor otisků prstů je znečištěn. Vyčistěte jej a zkuste to znovu."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Pohyb prstem byl příliš rychlý. Zkuste to znovu."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Pohyb prstem byl příliš pomalý. Zkuste to znovu."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Otisk byl ověřen"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Obličej byl ověřen"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Obličej byl ověřen, stiskněte tlačítko pro potvrzení"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Není k dispozici hardware ke snímání otisků prstů."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Otisk prstu nelze uložit. Odstraňte existující otisk prstu."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Časový limit sejmutí otisku prstu vypršel. Zkuste to znovu."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operace otisku prstu byla zrušena."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Uživatel operaci s otiskem prstu zrušil."</string>
@@ -609,6 +626,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Odemknutí obličejem"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Zaznamenejte obličej znovu"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Chcete-li rozpoznání zdokonalit, zaznamenejte obličej znovu"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Obličej se nepodařilo zachytit. Zkuste to znovu."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Je příliš světlo. Zmírněte osvětlení."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Je moc velká tma. Přejděte na světlo."</string>
@@ -1012,6 +1037,12 @@
<string name="copied" msgid="4675902854553014676">"Zkopírováno"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Aplikace <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> vložila data z aplikace <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Aplikace <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> vložila data ze schránky"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Více"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2178,20 +2209,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Pracovní"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Osobní zobrazení"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Pracovní zobrazení"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Sdílení s pracovními aplikacemi je zakázáno"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Administrátor IT nepovoluje sdílet tento obsah pomocí aplikací z vašeho pracovního profilu"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Otevírání pomocí pracovních aplikací je zakázáno"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Administrátor IT nepovoluje otevírat tento obsah pomocí aplikací z vašeho pracovního profilu"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Sdílení s osobními aplikacemi je zakázáno"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Administrátor IT nepovoluje sdílet tento obsah pomocí aplikací z vašeho osobního profilu"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Otevírání pomocí osobních aplikací je zakázáno"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Administrátor IT nepovoluje otevírat tento obsah pomocí aplikací z vašeho osobního profilu"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Pracovní profil je pozastaven"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Zapnout"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Tento obsah nepodporují žádné pracovní aplikace"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Tento obsah nemohou otevřít žádné pracovní aplikace"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Tento obsah nepodporují žádné osobní aplikace"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Tento obsah nemohou otevřít žádné osobní aplikace"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Kód PIN odblokování sítě pro SIM kartu"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN pro odblokování podskupiny sítí pro SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Kód PIN odblokování podnikové sítě pro SIM kartu"</string>
@@ -2304,8 +2346,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Zvětšit část obrazovky"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Teď můžete zvětšit celou obrazovku, její část nebo přepínat mezi oběma možnostmi."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Zapnout v Nastavení"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Zavřít"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Než budete pokračovat, udělte aplikaci <b><xliff:g id="APP">%s</xliff:g></b> přístup k mikrofonu na zařízení."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9dcb4d5..475b274 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Appen kører"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps, der bruger batteri"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Forstørrelse"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Sikkerhedspolitik for hjælpefunktioner"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruger batteri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps bruger batteri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryk for at se info om batteri- og dataforbrug"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"få adgang til din fysiske aktivitet"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"tage billeder og optage video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Bluetooth-enheder i nærheden"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"registrer og opret forbindelse til Bluetooth-enheder i nærheden"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Opkaldslister"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"læse og redigere opkaldslisten"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -534,6 +537,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tillader, at appen kan læse konfigurationen af Bluetooth på tabletten samt kan oprette og acceptere forbindelser med parrede enheder."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Tillader, at appen kan se konfigurationen af Bluetooth på din Android TV-enhed samt oprette og acceptere forbindelser med parrede enheder."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Tillader, at appen kan læse konfigurationen af Bluetooth på telefonen samt kan oprette og acceptere forbindelser med parrede enheder."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"registrer og par med Bluetooth-enheder i nærheden"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Tillader, at appen registrerer og parrer Bluetooth-enheder i nærheden"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"opret forbindelse til parrede Bluetooth-enheder"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Tillader, at appen opretter forbindelse til parrede Bluetooth-enheder"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Foretrukne oplysninger vedrørende NFC-betalingstjeneste"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Tillader, at appen får foretrukne oplysninger vedrørende NFC-betalingstjeneste, f.eks. registrerede hjælpemidler og rutedestinationer."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"administrere Near Field Communication"</string>
@@ -569,18 +576,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Der opstod fejl i forbindelse med godkendelse"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Brug skærmlås"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Angiv dine loginoplysninger for enheden for at fortsætte"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Der blev registreret et delvist fingeraftryk. Prøv igen."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Fingeraftrykket kunne ikke behandles. Prøv igen."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Fingeraftrykslæseren er beskidt. Tør den af, og prøv igen."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Du bevægede fingeren for hurtigt. Prøv igen."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Du bevægede fingeren for langsomt. Prøv igen."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingeraftrykket blev godkendt"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ansigtet er godkendt"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansigtet er godkendt. Tryk på Bekræft."</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardwaren til fingeraftryk er ikke tilgængelig."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Fingeraftrykket kan ikke gemmes. Fjern et eksisterende fingeraftryk."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Registrering af fingeraftryk fik timeout. Prøv igen."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingeraftrykshandlingen blev annulleret."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingeraftrykshandlingen blev annulleret af brugeren."</string>
@@ -605,6 +622,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Ansigtslås"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Registrer dit ansigt igen"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Registrer dit ansigt igen for at forbedre genkendelsen af det"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Der blev ikke registreret ansigtsdata. Prøv igen."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Der er for lyst. Prøv en mere dæmpet belysning."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"For mørkt. Prøv med mere belysning."</string>
@@ -1008,6 +1033,12 @@
<string name="copied" msgid="4675902854553014676">"Kopieret"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> indsatte indhold fra <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> indsatte indhold fra udklipsholderen"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Mere"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2112,20 +2143,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Arbejde"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Visningen Personligt"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Visningen Arbejde"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Indholdet kan ikke deles med arbejdsapps"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Din it-administrator har ikke givet dig tilladelse til at dele dette indhold med apps fra din arbejdsprofil"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Indholdet kan ikke åbnes med arbejdsapps"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Din it-administrator har ikke givet dig tilladelse til at åbne dette indhold med apps fra din arbejdsprofil"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Indholdet kan ikke deles med personlige apps"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Din it-administrator har ikke givet dig tilladelse til at dele dette indhold med apps fra din personlige profil"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Indholdet kan ikke åbnes med personlige apps"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Din it-administrator har ikke givet dig tilladelse til at åbne dette indhold med apps fra din personlige profil"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Arbejdsprofilen er sat på pause"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Aktivér"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Dette indhold understøttes ikke af arbejdsapps"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Dette indhold kan ikke åbnes af arbejdsapps"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Dette indhold understøttes ikke af personlige apps"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Dette indhold kan ikke åbnes af personlige apps"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Pinkode til oplåsning af SIM-netværket"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Pinkode til oplåsning af delmængde for SIM-netværket"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Pinkode til oplåsning af virksomhedens SIM"</string>
@@ -2238,8 +2280,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Forstør en del af din skærm"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Nu kan du forstørre hele skærmen, en del af skærmen eller skifte mellem begge valgmuligheder."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivér i Indstillinger"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Luk"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"<b><xliff:g id="APP">%s</xliff:g></b> skal have adgang til din enheds mikrofon, før den kan fortsætte."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 60cb51d..f8cb560 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App wird ausgeführt"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Strom verbrauchende Apps"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergrößerung"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Sicherheitsrichtlinien für Bedienungshilfen"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> verbraucht Strom"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> Apps verbrauchen Strom"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Für Details zur Akku- und Datennutzung tippen"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"Zugriff auf körperliche Aktivität"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"Bilder und Videos aufnehmen"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Bluetooth-Geräte in der Nähe"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"Bluetooth-Geräte in der Nähe finden und eine Verbindung zu ihnen herstellen"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Anrufliste"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"Schreib- und Lesezugriff auf Anrufliste"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Ermöglicht der App, die Bluetooth-Konfiguration eines Tablets einzusehen und Verbindungen zu gekoppelten Geräten herzustellen und zu akzeptieren."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Ermöglicht der App, die Bluetooth-Konfiguration des Android TV-Geräts abzurufen und Verbindungen zu gekoppelten Geräten herzustellen und zu akzeptieren."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Ermöglicht der App, die Bluetooth-Konfiguration des Telefons einzusehen und Verbindungen mit gekoppelten Geräten herzustellen und zu akzeptieren."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"Bluetooth-Geräte in der Nähe finden und koppeln"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Erlaubt der App, Bluetooth-Geräte in der Nähe zu finden und zu koppeln"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"Mit gekoppelten Bluetooth-Geräten verbinden"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Erlaubt der App, sich mit gekoppelten Bluetooth-Geräten zu verbinden"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informationen zum bevorzugten NFC-Zahlungsdienst"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Ermöglicht der App, Informationen zum bevorzugten NFC-Zahlungsdienst abzurufen, etwa registrierte Hilfsmittel oder das Routenziel."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Nahfeldkommunikation steuern"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Fehler bei der Authentifizierung"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Displaysperre verwenden"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Zum Fortfahren Anmeldedaten des Geräts eingeben"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Fingerabdruck nur teilweise erkannt. Bitte versuche es noch einmal."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Fingerabdruck konnte nicht verarbeitet werden. Bitte versuche es noch einmal."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Fingerabdrucksensor ist verschmutzt. Reinige ihn und versuche es noch einmal."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Du hast deinen Finger zu schnell bewegt. Bitte versuche es noch einmal."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger zu langsam bewegt. Bitte versuche es noch einmal."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerabdruck wurde authentifiziert"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Gesicht authentifiziert"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gesicht authentifiziert, bitte bestätigen"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerabdruckhardware nicht verfügbar"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Fingerabdruck kann nicht gespeichert werden. Entferne einen vorhandenen Fingerabdruck."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Zeitüberschreitung bei Fingerabdruck. Bitte versuche es noch einmal."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerabdruckvorgang abgebrochen"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Vorgang der Fingerabdruckauthentifizierung vom Nutzer abgebrochen."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Gesicht neu scannen lassen"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Für bessere Erkennung Gesicht neu scannen lassen"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Gesichtsdaten nicht gut erfasst. Erneut versuchen."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Zu hell. Schwächere Beleuchtung ausprobieren."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Zu dunkel. Probier eine hellere Beleuchtung aus."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Kopiert"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> hat etwas von <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> eingefügt"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> hat etwas aus der Zwischenablage eingefügt"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Mehr"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menü+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta-Taste +"</string>
@@ -1689,8 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Verknüpfung verwenden"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Farbumkehr"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Farbkorrektur"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (3222994553174604132) -->
- <skip />
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extradunkel"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist aktiviert."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist deaktiviert."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Halten Sie beide Lautstärketasten drei Sekunden lang gedrückt, um <xliff:g id="SERVICE_NAME">%1$s</xliff:g> zu verwenden"</string>
@@ -2111,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Geschäftlich"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Private Ansicht"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Geschäftliche Ansicht"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Teilen mit geschäftlichen Apps nicht möglich"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Dein IT-Administrator hat festgelegt, dass du diese Inhalte mit den Apps in deinem Arbeitsprofil nicht teilen darfst"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Öffnen mit geschäftlichen Apps nicht möglich"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Dein IT-Administrator hat festgelegt, dass du diese Inhalte mit den Apps in deinem Arbeitsprofil nicht aufrufen darfst"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Teilen mit privaten Apps nicht möglich"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Dein IT-Administrator hat festgelegt, dass du diese Inhalte mit den Apps in deinem privaten Profil nicht teilen darfst"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Öffnen mit privaten Apps nicht möglich"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Dein IT-Administrator hat festgelegt, dass du diese Inhalte mit den Apps in deinem privaten Profil nicht aufrufen darfst"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Arbeitsprofil pausiert"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Aktivieren"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Diese Inhalte werden von geschäftlichen Apps nicht unterstützt"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Diese Inhalte dürfen nicht mit geschäftlichen Apps geöffnet werden"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Diese Inhalte werden von privaten Apps nicht unterstützt"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Diese Inhalte dürfen nicht mit privaten Apps geöffnet werden"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Entsperr-PIN für netzgebundenes Gerät"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Entsperr-PIN für subnetzgebundenes Gerät"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Entsperr-PIN für unternehmensgebundenes Gerät"</string>
@@ -2237,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Einen Teil des Bildschirms vergrößern"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Du kannst jetzt den gesamten Bildschirm oder einen bestimmten Bereich vergrößern und zwischen beiden Optionen wechseln."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"In den Einstellungen aktivieren"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Schließen"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Zum Fortfahren benötigt, <b><xliff:g id="APP">%s</xliff:g></b> Zugriff auf das Mikrofon deines Geräts."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index d2ea1e6..7279634 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Η εφαρμογή εκτελείται"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Εφαρμογές που καταναλώνουν μπαταρία"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Μεγιστοποίηση"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Πολιτική ασφαλείας προσβασιμότητας"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> χρησιμοποιεί μπαταρία"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> εφαρμογές χρησιμοποιούν μπαταρία"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Πατήστε για λεπτομέρειες σχετικά με τη χρήση μπαταρίας και δεδομένων"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"πρόσβαση στη σωματική σας δραστηριότητα"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Κάμερα"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"γίνεται λήψη φωτογραφιών και εγγραφή βίντεο"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Κοντινές συσκευές Bluetooth"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"ανακάλυψη και σύνδεση σε κοντινές συσκευές Bluetooth"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Αρχεία καταγρ. κλήσ."</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ανάγνωση και εγγραφή αρχείου καταγραφής τηλεφωνικών κλήσεων"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Τηλέφωνο"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στο tablet, καθώς και να πραγματοποιεί και να αποδέχεται συνδέσεις με συνδεδεμένες συσκευές."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Επιτρέπει στην εφαρμογή να βλέπει τη διαμόρφωση του Bluetooth στη συσκευή Android TV και να κάνει και να αποδέχεται συνδέσεις με συζευγμένες συσκευές."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στο τηλέφωνο, καθώς και να πραγματοποιεί και να αποδέχεται συνδέσεις με συνδεδεμένες συσκευές."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"ανακάλυψη και σύζευξη κοντινών συσκευών Bluetooth"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Επιτρέπει στην εφαρμογή την ανακάλυψη και τη σύζευξη κοντινών συσκευών Bluetooth"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"σύνδεση σε συζευγμένες συσκευές Bluetooth"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Επιτρέπει στην εφαρμογή τη σύνδεση σε συζευγμένες συσκευές Bluetooth"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Πληροφορίες προτιμώμενης υπηρεσίας πληρωμών NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Επιτρέπει στην εφαρμογή να λαμβάνει πληροφορίες προτιμώμενης υπηρεσίας πληρωμής NFC, όπως καταχωρημένα βοηθήματα και προορισμό διαδρομής."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ελέγχει την Επικοινωνία κοντινού πεδίου (FNC)"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Σφάλμα κατά τον έλεγχο ταυτότητας"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Χρήση κλειδώματος οθόνης"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Εισαγάγετε το διαπιστευτήριο της συσκευής σας για να συνεχίσετε"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Εντοπίστηκε μόνο μέρος του δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Δεν ήταν δυνατή η επεξεργασία του δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Ο αισθητήρας δακτυλικού αποτυπώματος δεν είναι καθαρός. Καθαρίστε τον και δοκιμάστε ξανά."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Κινηθήκατε πολύ γρήγορα. Δοκιμάστε ξανά."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Πολύ αργή κίνηση δαχτύλου. Δοκιμάστε ξανά."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Η ταυτότητα του δακτυλικού αποτυπώματος ελέγχθηκε"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Έγινε έλεγχος ταυτότητας προσώπου"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Έγινε έλεγχος ταυτότητας προσώπου, πατήστε \"Επιβεβαίωση\""</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Ο εξοπλισμός δακτυλικού αποτυπώματος δεν είναι διαθέσιμος."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Δεν είναι δυνατή η αποθήκευση του δακτυλικού αποτυπώματος. Καταργήστε το υπάρχον δακτυλικό αποτύπωμα."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Λήξη χρονικού ορίου δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε από τον χρήστη."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Εγγράψτε ξανά το πρόσωπό σας"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Για να βελτιώσετε την αναγνώριση, εγγράψτε ξανά το πρόσωπό σας"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Αδύνατη λήψη ακριβών δεδομ. προσώπου. Επανάληψη."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Υπερβολικά έντονος φωτισμός. Δοκιμάστε πιο ήπιο."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Πολύ σκοτεινό περιβάλλον. Φροντίστε τον φωτισμό."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Αντιγράφηκε"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Η εφαρμογή <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> έκανε επικόλληση από την εφαρμογή <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Η εφαρμογή <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> έκανε επικόλληση από το πρόχειρο"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Περισσότερα"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Πλήκτρο Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Εργασία"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Προσωπική προβολή"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Προβολή εργασίας"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Δεν είναι δυνατή η κοινοποίηση αυτού του περιεχομένου με εφαρμογές εργασίας"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Ο διαχειριστής IT δεν σας επιτρέπει να κοινοποιήσετε αυτό το περιεχόμενο με εφαρμογές στο προφίλ εργασίας σας."</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Δεν είναι δυνατό το άνοιγμα με εφαρμογές εργασίας"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Ο διαχειριστής IT δεν σας επιτρέπει να ανοίξετε αυτό το περιεχόμενο με εφαρμογές στο προφίλ εργασίας σας."</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Δεν είναι δυνατή η κοινοποίηση αυτού του περιεχομένου με προσωπικές εφαρμογές"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Ο διαχειριστής IT δεν σας επιτρέπει να κοινοποιήσετε αυτό το περιεχόμενο με εφαρμογές στο προσωπικό προφίλ σας."</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Δεν είναι δυνατό το άνοιγμα με προσωπικές εφαρμογές"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Ο διαχειριστής IT δεν σας επιτρέπει να ανοίξετε αυτό το περιεχόμενο με εφαρμογές στο προσωπικό προφίλ σας."</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Το προφίλ εργασίας σας έχει τεθεί σε παύση."</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Ενεργοποίηση"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Καμία εφαρμογή εργασίας δεν μπορεί να υποστηρίξει αυτό το περιεχόμενο."</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Καμία εφαρμογή εργασίας δεν μπορεί να ανοίξει αυτό το περιεχόμενο."</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Καμία προσωπική εφαρμογή δεν μπορεί να υποστηρίξει αυτό το περιεχόμενο."</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Καμία προσωπική εφαρμογή δεν μπορεί να ανοίξει αυτό το περιεχόμενο."</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN ξεκλειδώματος δικτύου κάρτας SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN ξεκλειδώματος υποσυνόλου δικτύου κάρτας SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN ξεκλειδώματος εταιρικής SIM"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Μεγέθυνση μέρους της οθόνης"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Μπορείτε πλέον να κάνετε μεγέθυνση πλήρους οθόνης, συγκεκριμένης περιοχής ή να κάνετε εναλλαγή μεταξύ των δύο επιλογών."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ενεργοποίηση στις Ρυθμίσεις"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Παράβλεψη"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Για να συνεχίσετε, η εφαρμογή <b><xliff:g id="APP">%s</xliff:g></b> χρειάζεται πρόσβαση στο μικρόφωνο της συσκευής σας."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index d5bc66d..9fdd65b 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App running"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Accessibility security policy"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"access your physical activity"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Camera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"take pictures and record video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Nearby Bluetooth devices"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"discover and connect to nearby Bluetooth devices"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Call logs"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"read and write phone call logs"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Phone"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Allows the app to view the configuration of Bluetooth on your Android TV device and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"discover and pair nearby Bluetooth devices"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Allows the app to discover and pair nearby Bluetooth devices"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"connect to paired Bluetooth devices"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Allows the app to connect to paired Bluetooth devices"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferred NFC payment service information"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Error while authenticating"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Enter your device credential to continue"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Partial fingerprint detected. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Couldn\'t process fingerprint. Please try again."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Fingerprint sensor is dirty. Please clean and try again."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Finger moved too fast. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger moved too slow. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerprint hardware not available."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string>
@@ -603,6 +620,10 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Re-enrol your face"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"To improve recognition, please re-enrol your face"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Set up face unlock"</string>
+ <string name="face_setup_notification_content" msgid="5463999831057751676">"Unlock your phone by looking at it"</string>
+ <string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Set up more ways to unlock"</string>
+ <string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tap to add a fingerprint"</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Couldn’t capture accurate face data. Try again."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Too bright. Try gentler lighting."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Too dark. Try brighter lighting."</string>
@@ -1006,6 +1027,9 @@
<string name="copied" msgid="4675902854553014676">"Copied"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted from <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted from clipboard"</string>
+ <string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted text that you copied"</string>
+ <string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted an image that you copied"</string>
+ <string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted content that you copied"</string>
<string name="more_item_label" msgid="7419249600215749115">"More"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2134,19 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Work"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal view"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Work view"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Can’t share this with work apps"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Your IT admin doesn’t allow you to share this content with apps in your work profile"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Can’t open this with work apps"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Your IT admin doesn’t allow you to open this content with apps in your work profile"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Can’t share this with personal apps"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Your IT admin doesn’t allow you to share this content with apps in your personal profile"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Can’t open this with personal apps"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Your IT admin doesn’t allow you to open this content with apps in your personal profile"</string>
+ <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"Blocked by your IT admin"</string>
+ <string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"This content can’t be shared with work apps"</string>
+ <string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"This content can’t be opened with work apps"</string>
+ <string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"This content can’t be shared with personal apps"</string>
+ <string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"This content can’t be opened with personal apps"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Work profile is paused"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Turn on"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"No work apps can support this content"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"No work apps can open this content"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"No personal apps can support this content"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"No personal apps can open this content"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"Tap to turn on"</string>
+ <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"No work apps"</string>
+ <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"No personal apps"</string>
+ <string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Open in <xliff:g id="APP">%s</xliff:g> in personal profile?"</string>
+ <string name="miniresolver_open_in_work" msgid="152208044699347924">"Open in <xliff:g id="APP">%s</xliff:g> in work profile?"</string>
+ <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
+ <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM network unlock PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM network subset unlock PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM corporate unlock PIN"</string>
@@ -2236,8 +2259,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Magnify part of your screen"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"You can now magnify your full screen, a specific area, or switch between both options."</string>
+ <string name="window_magnification_prompt_title" msgid="2876703640772778215">"New magnification settings"</string>
+ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"You can now magnify part of your screen"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Turn on in settings"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Dismiss"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"To continue, <b><xliff:g id="APP">%s</xliff:g></b> needs access to your device microphone."</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 11d1780..2f0a4d2 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App running"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Accessibility security policy"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"access your physical activity"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Camera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"take pictures and record video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Nearby Bluetooth devices"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"discover and connect to nearby Bluetooth devices"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Call logs"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"read and write phone call logs"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Phone"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Allows the app to view the configuration of Bluetooth on your Android TV device and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"discover and pair nearby Bluetooth devices"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Allows the app to discover and pair nearby Bluetooth devices"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"connect to paired Bluetooth devices"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Allows the app to connect to paired Bluetooth devices"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferred NFC payment service information"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Error while authenticating"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Enter your device credential to continue"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Partial fingerprint detected. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Couldn\'t process fingerprint. Please try again."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Fingerprint sensor is dirty. Please clean and try again."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Finger moved too fast. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger moved too slow. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerprint hardware not available."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string>
@@ -603,6 +620,10 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Re-enrol your face"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"To improve recognition, please re-enrol your face"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Set up face unlock"</string>
+ <string name="face_setup_notification_content" msgid="5463999831057751676">"Unlock your phone by looking at it"</string>
+ <string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Set up more ways to unlock"</string>
+ <string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tap to add a fingerprint"</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Couldn’t capture accurate face data. Try again."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Too bright. Try gentler lighting."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Too dark. Try brighter lighting."</string>
@@ -1006,6 +1027,9 @@
<string name="copied" msgid="4675902854553014676">"Copied"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted from <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted from clipboard"</string>
+ <string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted text that you copied"</string>
+ <string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted an image that you copied"</string>
+ <string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted content that you copied"</string>
<string name="more_item_label" msgid="7419249600215749115">"More"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2134,19 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Work"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal view"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Work view"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Can’t share this with work apps"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Your IT admin doesn’t allow you to share this content with apps in your work profile"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Can’t open this with work apps"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Your IT admin doesn’t allow you to open this content with apps in your work profile"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Can’t share this with personal apps"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Your IT admin doesn’t allow you to share this content with apps in your personal profile"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Can’t open this with personal apps"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Your IT admin doesn’t allow you to open this content with apps in your personal profile"</string>
+ <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"Blocked by your IT admin"</string>
+ <string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"This content can’t be shared with work apps"</string>
+ <string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"This content can’t be opened with work apps"</string>
+ <string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"This content can’t be shared with personal apps"</string>
+ <string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"This content can’t be opened with personal apps"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Work profile is paused"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Turn on"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"No work apps can support this content"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"No work apps can open this content"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"No personal apps can support this content"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"No personal apps can open this content"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"Tap to turn on"</string>
+ <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"No work apps"</string>
+ <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"No personal apps"</string>
+ <string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Open in <xliff:g id="APP">%s</xliff:g> in personal profile?"</string>
+ <string name="miniresolver_open_in_work" msgid="152208044699347924">"Open in <xliff:g id="APP">%s</xliff:g> in work profile?"</string>
+ <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
+ <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM network unlock PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM network subset unlock PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM corporate unlock PIN"</string>
@@ -2236,8 +2259,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Magnify part of your screen"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"You can now magnify your full screen, a specific area, or switch between both options."</string>
+ <string name="window_magnification_prompt_title" msgid="2876703640772778215">"New magnification settings"</string>
+ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"You can now magnify part of your screen"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Turn on in settings"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Dismiss"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"To continue, <b><xliff:g id="APP">%s</xliff:g></b> needs access to your device microphone."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 4e15e60..e52ff7d 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App running"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Accessibility security policy"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"access your physical activity"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Camera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"take pictures and record video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Nearby Bluetooth devices"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"discover and connect to nearby Bluetooth devices"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Call logs"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"read and write phone call logs"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Phone"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Allows the app to view the configuration of Bluetooth on your Android TV device and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"discover and pair nearby Bluetooth devices"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Allows the app to discover and pair nearby Bluetooth devices"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"connect to paired Bluetooth devices"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Allows the app to connect to paired Bluetooth devices"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferred NFC payment service information"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Error while authenticating"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Enter your device credential to continue"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Partial fingerprint detected. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Couldn\'t process fingerprint. Please try again."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Fingerprint sensor is dirty. Please clean and try again."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Finger moved too fast. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger moved too slow. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerprint hardware not available."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string>
@@ -603,6 +620,10 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Re-enrol your face"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"To improve recognition, please re-enrol your face"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Set up face unlock"</string>
+ <string name="face_setup_notification_content" msgid="5463999831057751676">"Unlock your phone by looking at it"</string>
+ <string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Set up more ways to unlock"</string>
+ <string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tap to add a fingerprint"</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Couldn’t capture accurate face data. Try again."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Too bright. Try gentler lighting."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Too dark. Try brighter lighting."</string>
@@ -1006,6 +1027,9 @@
<string name="copied" msgid="4675902854553014676">"Copied"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted from <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted from clipboard"</string>
+ <string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted text that you copied"</string>
+ <string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted an image that you copied"</string>
+ <string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted content that you copied"</string>
<string name="more_item_label" msgid="7419249600215749115">"More"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2134,19 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Work"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal view"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Work view"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Can’t share this with work apps"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Your IT admin doesn’t allow you to share this content with apps in your work profile"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Can’t open this with work apps"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Your IT admin doesn’t allow you to open this content with apps in your work profile"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Can’t share this with personal apps"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Your IT admin doesn’t allow you to share this content with apps in your personal profile"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Can’t open this with personal apps"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Your IT admin doesn’t allow you to open this content with apps in your personal profile"</string>
+ <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"Blocked by your IT admin"</string>
+ <string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"This content can’t be shared with work apps"</string>
+ <string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"This content can’t be opened with work apps"</string>
+ <string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"This content can’t be shared with personal apps"</string>
+ <string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"This content can’t be opened with personal apps"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Work profile is paused"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Turn on"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"No work apps can support this content"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"No work apps can open this content"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"No personal apps can support this content"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"No personal apps can open this content"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"Tap to turn on"</string>
+ <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"No work apps"</string>
+ <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"No personal apps"</string>
+ <string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Open in <xliff:g id="APP">%s</xliff:g> in personal profile?"</string>
+ <string name="miniresolver_open_in_work" msgid="152208044699347924">"Open in <xliff:g id="APP">%s</xliff:g> in work profile?"</string>
+ <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
+ <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM network unlock PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM network subset unlock PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM corporate unlock PIN"</string>
@@ -2236,8 +2259,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Magnify part of your screen"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"You can now magnify your full screen, a specific area, or switch between both options."</string>
+ <string name="window_magnification_prompt_title" msgid="2876703640772778215">"New magnification settings"</string>
+ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"You can now magnify part of your screen"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Turn on in settings"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Dismiss"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"To continue, <b><xliff:g id="APP">%s</xliff:g></b> needs access to your device microphone."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 60d743b..a73db00 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App running"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Accessibility security policy"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"access your physical activity"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Camera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"take pictures and record video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Nearby Bluetooth devices"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"discover and connect to nearby Bluetooth devices"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Call logs"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"read and write phone call logs"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Phone"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Allows the app to view the configuration of Bluetooth on your Android TV device and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"discover and pair nearby Bluetooth devices"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Allows the app to discover and pair nearby Bluetooth devices"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"connect to paired Bluetooth devices"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Allows the app to connect to paired Bluetooth devices"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferred NFC payment service information"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Error while authenticating"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Enter your device credential to continue"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Partial fingerprint detected. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Couldn\'t process fingerprint. Please try again."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Fingerprint sensor is dirty. Please clean and try again."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Finger moved too fast. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger moved too slow. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerprint hardware not available."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string>
@@ -603,6 +620,10 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Re-enrol your face"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"To improve recognition, please re-enrol your face"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Set up face unlock"</string>
+ <string name="face_setup_notification_content" msgid="5463999831057751676">"Unlock your phone by looking at it"</string>
+ <string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Set up more ways to unlock"</string>
+ <string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tap to add a fingerprint"</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Couldn’t capture accurate face data. Try again."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Too bright. Try gentler lighting."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Too dark. Try brighter lighting."</string>
@@ -1006,6 +1027,9 @@
<string name="copied" msgid="4675902854553014676">"Copied"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted from <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted from clipboard"</string>
+ <string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted text that you copied"</string>
+ <string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted an image that you copied"</string>
+ <string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted content that you copied"</string>
<string name="more_item_label" msgid="7419249600215749115">"More"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2134,19 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Work"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal view"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Work view"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Can’t share this with work apps"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Your IT admin doesn’t allow you to share this content with apps in your work profile"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Can’t open this with work apps"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Your IT admin doesn’t allow you to open this content with apps in your work profile"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Can’t share this with personal apps"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Your IT admin doesn’t allow you to share this content with apps in your personal profile"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Can’t open this with personal apps"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Your IT admin doesn’t allow you to open this content with apps in your personal profile"</string>
+ <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"Blocked by your IT admin"</string>
+ <string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"This content can’t be shared with work apps"</string>
+ <string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"This content can’t be opened with work apps"</string>
+ <string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"This content can’t be shared with personal apps"</string>
+ <string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"This content can’t be opened with personal apps"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Work profile is paused"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Turn on"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"No work apps can support this content"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"No work apps can open this content"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"No personal apps can support this content"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"No personal apps can open this content"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"Tap to turn on"</string>
+ <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"No work apps"</string>
+ <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"No personal apps"</string>
+ <string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Open in <xliff:g id="APP">%s</xliff:g> in personal profile?"</string>
+ <string name="miniresolver_open_in_work" msgid="152208044699347924">"Open in <xliff:g id="APP">%s</xliff:g> in work profile?"</string>
+ <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
+ <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM network unlock PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM network subset unlock PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM corporate unlock PIN"</string>
@@ -2236,8 +2259,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Magnify part of your screen"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"You can now magnify your full screen, a specific area, or switch between both options."</string>
+ <string name="window_magnification_prompt_title" msgid="2876703640772778215">"New magnification settings"</string>
+ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"You can now magnify part of your screen"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Turn on in settings"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Dismiss"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"To continue, <b><xliff:g id="APP">%s</xliff:g></b> needs access to your device microphone."</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index a4bf0c3..12bc978 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App running"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Accessibility security policy"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"access your physical activity"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Camera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"take pictures and record video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Nearby Bluetooth Devices"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"discover and connect to nearby Bluetooth devices"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Call logs"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"read and write phone call log"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Phone"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Allows the app to view the configuration of Bluetooth on the tablet, and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Allows the app to view the configuration of Bluetooth on your Android TV device, and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Allows the app to view the configuration of the Bluetooth on the phone, and to make and accept connections with paired devices."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"discover and pair nearby Bluetooth devices"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Allows the app to discover and pair nearby Bluetooth devices"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"connect to paired Bluetooth devices"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Allows the app to connect to paired Bluetooth devices"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferred NFC Payment Service Information"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred nfc payment service information like registered aids and route destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"control Near Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Error authenticating"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Enter your device credential to continue"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Partial fingerprint detected. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Couldn\'t process fingerprint. Please try again."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Fingerprint sensor is dirty. Please clean and try again."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Finger moved too fast. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger moved too slow. Please try again."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated, please press confirm"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerprint hardware not available."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Fingerprint time out reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation canceled."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation canceled by user."</string>
@@ -603,6 +620,10 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Re-enroll your face"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"To improve recognition, please re-enroll your face"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Set up face unlock"</string>
+ <string name="face_setup_notification_content" msgid="5463999831057751676">"Unlock your phone by looking at it"</string>
+ <string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Set up more ways to unlock"</string>
+ <string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tap to add a fingerprint"</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Couldn’t capture accurate face data. Try again."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Too bright. Try gentler lighting."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Too dark. Try brighter lighting."</string>
@@ -1006,6 +1027,9 @@
<string name="copied" msgid="4675902854553014676">"Copied"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted from <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted from clipboard"</string>
+ <string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted text you copied"</string>
+ <string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted an image you copied"</string>
+ <string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pasted content you copied"</string>
<string name="more_item_label" msgid="7419249600215749115">"More"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2134,19 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Work"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal view"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Work view"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Can’t share this with work apps"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Your IT admin doesn’t allow you to share this content with apps in your work profile"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Can’t open this with work apps"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Your IT admin doesn’t allow you to open this content with apps in your work profile"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Can’t share this with personal apps"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Your IT admin doesn’t allow you to share this content with apps in your personal profile"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Can’t open this with personal apps"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Your IT admin doesn’t allow you to open this content with apps in your personal profile"</string>
+ <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"Blocked by your IT admin"</string>
+ <string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"This content can’t be shared with work apps"</string>
+ <string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"This content can’t be opened with work apps"</string>
+ <string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"This content can’t be shared with personal apps"</string>
+ <string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"This content can’t be opened with personal apps"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Work profile is paused"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Turn on"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"No work apps can support this content"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"No work apps can open this content"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"No personal apps can support this content"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"No personal apps can open this content"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"Tap to turn on"</string>
+ <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"No work apps"</string>
+ <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"No personal apps"</string>
+ <string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Open in <xliff:g id="APP">%s</xliff:g> in personal profile?"</string>
+ <string name="miniresolver_open_in_work" msgid="152208044699347924">"Open in <xliff:g id="APP">%s</xliff:g> in work profile?"</string>
+ <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
+ <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM network unlock PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM network subset unlock PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM corporate unlock PIN"</string>
@@ -2236,8 +2259,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Magnify part of your screen"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"You can now magnify your full screen, a specific area, or switch between both options."</string>
+ <string name="window_magnification_prompt_title" msgid="2876703640772778215">"New magnification settings"</string>
+ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"You can now magnify part of your screen"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Turn on in Settings"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Dismiss"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"To continue, <b><xliff:g id="APP">%s</xliff:g></b> needs access to your device microphone."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index da9292a..475fe5f 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App en ejecución"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que consumen batería"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Política de seguridad de accesibilidad"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está consumiendo batería"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps están consumiendo batería"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Presiona para obtener información sobre el uso de datos y de la batería"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"acceder a tu actividad física"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Cámara"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"tomar fotografías y grabar videos"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Dispositivos Bluetooth cercanos"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"Descubre dispositivos Bluetooth cercanos y conéctate a ellos"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Llamadas"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"leer y escribir el registro de llamadas telefónicas"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Teléfono"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que la aplicación vea la configuración de Bluetooth de la tablet y que cree y acepte conexiones con los dispositivos vinculados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que la app vea la configuración de Bluetooth del dispositivo Android TV, así como que cree y acepte conexiones con los dispositivos vinculados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que la aplicación vea la configuración de Bluetooth del dispositivo y que cree y acepte conexiones con los dispositivos vinculados."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"descubrir y vincular disp. Bluetooth cercanos"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permite que la app descubra dispositivos Bluetooth cercanos y se conecte a ellos"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"conectarse a dispositivos Bluetooth vinculados"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permite que la app se conecte a dispositivos Bluetooth vinculados"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Información sobre servicio de pago NFC preferido"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que la app reciba información del servicio de pago NFC preferido, como el servicio de asistencia registrado y el destino de la ruta."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar la Transmisión de datos en proximidad"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Error de autenticación"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueo de pantalla"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Ingresa las credenciales de tu dispositivo para continuar"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Se detectó parcialmente la huella dactilar. Vuelve a intentarlo."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"No se pudo procesar la huella dactilar. Vuelve a intentarlo."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"El sensor de huellas dactilares está sucio. Limpia el sensor y vuelve a intentarlo."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Moviste el dedo muy rápido. Vuelve a intentarlo."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Moviste el dedo muy lento. Vuelve a intentarlo."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Se autenticó la huella dactilar"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Se autenticó el rostro"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Se autenticó el rostro; presiona Confirmar"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"El hardware para detectar huellas dactilares no está disponible."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"No se puede almacenar la huella dactilar. Elimina una de las existentes."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Finalizó el tiempo de espera para la huella dactilar. Vuelve a intentarlo."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Se canceló la operación de huella dactilar."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"El usuario canceló la operación de huella dactilar."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Desbloqueo facial"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Vuelve a registrar tu rostro"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Para mejorar el reconocimiento, vuelve a registrar tu rostro"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Datos faciales imprecisos. Vuelve a intentarlo."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Demasiado brillante. Prueba con menos iluminación."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Demasiado oscuro. Prueba con más iluminación."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Copiado"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pegó contenido de <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pegó contenido del portapapeles"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Más"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menú+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Trabajo"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Vista personal"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Vista de trabajo"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"No se puede compartir con las apps de trabajo"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Tu administrador de TI no te permite compartir este contenido con apps de tu perfil de trabajo"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"No se puede abrir con apps de trabajo"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Tu administrador de TI no te permite abrir este contenido con apps de tu perfil de trabajo"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"No se puede compartir con las apps personales"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Tu administrador de TI no te permite compartir este contenido con apps de tu perfil personal"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"No se puede abrir con apps personales"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Tu administrador de TI no te permite abrir este contenido con apps de tu perfil personal"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"El perfil de trabajo está en pausa"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Activar"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Las apps de trabajo no pueden admitir este contenido"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Las apps de trabajo no pueden abrir este contenido"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Las apps personales no pueden admitir este contenido"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Las apps personales no pueden abrir este contenido"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN de desbloqueo del dispositivo para la red de tarjeta SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN de desbloqueo del dispositivo para el subconjunto de redes de tarjeta SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN de desbloqueo corporativo del dispositivo para tarjeta SIM"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Cómo ampliar una parte de la pantalla"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Ahora puedes ampliar toda la pantalla o parte de ella, o bien alternar entre ambas opciones."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Configuración"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Descartar"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Para continuar, <b><xliff:g id="APP">%s</xliff:g></b&gt necesita acceso al micrófono del dispositivo."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index ce2ee37..3aefd2b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicación en ejecución"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicaciones que consumen batería"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Política de seguridad de accesibilidad"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando la batería"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicaciones están usando la batería"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para ver información detallada sobre el uso de datos y de la batería"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"acceder a tu actividad física"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Cámara"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"hacer fotos y grabar vídeos"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Dispositivos Bluetooth cercanos"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"detecta y conéctate a dispositivos Bluetooth cercanos"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Registros de llamadas"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"leer y escribir en el registro de llamadas del teléfono"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Teléfono"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que la aplicación acceda a la configuración de Bluetooth del tablet y que establezca y acepte conexiones con los dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que la aplicación vea la configuración de Bluetooth de tu dispositivo Android TV y que cree y acepte conexiones con los dispositivos vinculados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que la aplicación acceda a la configuración de Bluetooth del teléfono y que establezca y acepte conexiones con los dispositivos sincronizados."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"detectar y vincular dispositivos Bluetooth cercanos"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permite que la aplicación detecte y vincule dispositivos Bluetooth cercanos"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"conectarse a dispositivos Bluetooth vinculados"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permite que la aplicación se conecte a dispositivos Bluetooth vinculados"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Información sobre el servicio de pago por NFC preferido"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que la aplicación obtenga información sobre el servicio de pago por NFC preferido, como identificadores de aplicación registrados y destinos de rutas."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar Comunicación de campo cercano (NFC)"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"No se ha podido autenticar"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueo de pantalla"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Introduce las credenciales del dispositivo para continuar"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Se ha detectado una huella digital parcial. Vuelve a intentarlo."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"No se ha podido procesar la huella digital. Vuelve a intentarlo."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"El sensor de huellas digitales está sucio. Límpialo y vuelve a intentarlo."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Has quitado el dedo demasiado rápido. Vuelve a intentarlo."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Has movido el dedo demasiado despacio. Vuelve a intentarlo."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Se ha autenticado la huella digital"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Cara autenticada"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Se ha autenticado la cara, pulsa para confirmar"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"El hardware de huella digital no está disponible."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"No se puede almacenar la huella digital. Elimina una ya creada."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Se ha alcanzado el tiempo de espera de la huella digital. Vuelve a intentarlo."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Se ha cancelado la operación de huella digital."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"El usuario ha cancelado la operación de huella digital."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Desbloqueo facial"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Volver a registrar la cara"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Para mejorar el reconocimiento, vuelve a registrar tu cara"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Datos faciales no reconocidos. Vuelve a intentarlo."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Hay demasiada luz. Busca un sitio menos iluminado."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Demasiado oscuro. Prueba en un lugar con más luz."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Copiado"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha pegado contenido de <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha pegado contenido del portapapeles"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Más"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"MENU+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Trabajo"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Ver contenido personal"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Ver contenido de trabajo"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"No se puede compartir con aplicaciones de trabajo"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Tu administrador de TI no te permite compartir este contenido con aplicaciones de tu perfil de trabajo"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"No se puede abrir con una aplicación de trabajo"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Tu administrador de TI no te permite abrir este contenido con aplicaciones de tu perfil de trabajo"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"No se puede compartir con una aplicación personal"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Tu administrador de TI no te permite compartir este contenido con ninguna aplicación de tu perfil personal"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"No se puede abrir con una aplicación personal"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Tu administrador de TI no te permite abrir este contenido con ninguna aplicación de tu perfil personal"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"El perfil de trabajo está en pausa"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Activar"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Ninguna aplicación de trabajo es compatible con este contenido"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Ninguna aplicación de trabajo puede abrir este contenido"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Ninguna aplicación personal es compatible con este contenido"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Ninguna aplicación personal puede abrir este contenido"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN de desbloqueo de red de tarjeta SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN de desbloqueo de subconjunto de red SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN de desbloqueo corporativo de SIM"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Ampliar parte de la pantalla"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Ahora puedes ampliar toda la pantalla o una parte concreta, o cambiar entre ambas opciones."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Ajustes"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Cerrar"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Para continuar, <b><xliff:g id="APP">%s</xliff:g></b> necesita tener acceso al micrófono del dispositivo."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 04ab1f3..d45e917 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Rakendus töötab"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Rakendused kasutavad akutoidet"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Suurendus"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Juurdepääsufunktsioonide turvaeeskirjad"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> kasutab akutoidet"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> rakendust kasutab akutoidet"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Aku ja andmekasutuse üksikasjade nägemiseks puudutage"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"juurdepääs teie füüsilisele tegevusele"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kaamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"pildistamine ja video salvestamine"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Lähedalasuvad Bluetooth-seadmed"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"lähedalasuvate Bluetooth-seadmete avastamine ja nendega ühenduse loomine"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Kõnelogid"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"telefoni kõnelogi lugemine ja kirjutamine"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Võimaldab rakendusel vaadata tahvelarvuti Bluetooth-konfiguratsiooni ning luua ja heaks kiita ühendusi seotud seadmetega."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Võimaldab rakendusel vaadata Android TV seadme Bluetoothi seadistust ning luua ja vastu võtta ühendusi seotud seadmetega."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Võimaldab rakendusel vaadata telefoni Bluetooth-konfiguratsiooni ning luua ja heaks kiita ühendusi seotud seadmetega."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"lähedalasuvate Bluetooth-seadmete avastamine ja nendega sidumine"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Lubab rakendusel avastada lähedalasuvaid Bluetooth-seadmeid ja nendega siduda"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"seotud Bluetooth-seadmetega ühenduse loomine"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Lubab rakendusel luua ühenduse seotud Bluetooth-seadmetega"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Eelistatud NFC-makseteenuse teave"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Võimaldab rakendusel hankida eelistatud NFC-makseteenuse teavet (nt registreeritud abi ja marsruudi sihtkoht)."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"lähiväljaside juhtimine"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Viga autentimisel"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekraaniluku kasutamine"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Jätkamiseks sisestage seadme mandaat"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Tuvastati osaline sõrmejälg. Proovige uuesti."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Sõrmejälge ei õnnestunud töödelda. Proovige uuesti."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Sõrmejäljeandur on must. Puhastage see ja proovige uuesti."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Sõrm liikus liiga kiiresti. Proovige uuesti."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Sõrm liikus liiga aeglaselt. Proovige uuesti."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Sõrmejälg autenditi"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Nägu on autenditud"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Nägu on autenditud, vajutage käsku Kinnita"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Sõrmejälje riistvara pole saadaval."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Sõrmejälge ei saa salvestada. Eemaldage olemasolev sõrmejälg."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Sõrmejälje riistvara taimeri ajalõpp. Proovige uuesti."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Sõrmejälje toiming tühistati."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Kasutaja tühistas sõrmejälje kasutamise."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Registreerige oma nägu uuesti"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Tuvastamise parandamiseks registreerige oma nägu uuesti"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Näoandmeid ei saanud jäädvustada. Proovige uuesti."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Liiga ere. Proovige hämaramat valgust."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Liiga pime. Proovige parema valgustusega kohas."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Kopeeritud"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kleepis rakendusest <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kleepis lõikelaualt"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Rohkem"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menüü+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Töö"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Isiklik vaade"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Töövaade"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Seda ei saa töörakendustega jagada"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Teie IT-administraator ei luba seda sisu teie tööprofiilil olevate rakendustega jagada"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Seda ei saa töörakendustega avada"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Teie IT-administraator ei luba seda sisu teie tööprofiilil olevate rakendustega avada"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Seda ei saa isiklike rakendustega jagada"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Teie IT-administraator ei luba seda sisu teie isiklikul profiilil olevate rakendustega jagada"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Seda ei saa isiklike rakendustega avada"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Teie IT-administraator ei luba seda sisu teie isiklikul profiilil olevate rakendustega avada"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Tööprofiil on peatatud"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Lülita sisse"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Töörakendused ei toeta seda sisu"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Seda sisu ei saa töörakendustega avada"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Isiklikud rakendused ei toeta seda sisu"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Seda sisu ei saa isiklike rakendustega avada"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM-kaardi võrgu avamise PIN-kood"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM-kaardi võrgu alamhulga avamise PIN-kood"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM-kaardi ettevõtte avamise PIN-kood"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Ekraanikuva teatud osa suurendamine"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Nüüd on teil võimalik suurendada täisekraani, konkreetset ala või mõlema võimaluse vahel vahetada."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Lülitage sisse menüüs Seaded"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Loobu"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Jätkamiseks vajab rakendus <b><xliff:g id="APP">%s</xliff:g></b> juurdepääsu teie seadme mikrofonile."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2677dfd..a4dad80 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikazio bat abian da"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Bateria kontsumitzen ari diren aplikazioak"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Lupa"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Irisgarritasunari buruzko segurtasun-gidalerroak"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ari da bateria erabiltzen"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikazio ari dira bateria erabiltzen"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"jarduera fisikoa atzitu"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"atera argazkiak eta grabatu bideoak"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Inguruko Bluetooth bidezko gailuak"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"inguruko Bluetooth bidezko gailuak hauteman eta haietara konektatu"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Deien erregistroa"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"irakurri telefonoko deien erregistroa eta idatzi bertan"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefonoa"</string>
@@ -346,7 +349,7 @@
<string name="permlab_expandStatusBar" msgid="1184232794782141698">"zabaldu/tolestu egoera-barra"</string>
<string name="permdesc_expandStatusBar" msgid="7180756900448498536">"Egoera-barra zabaltzeko edo tolesteko aukera ematen die aplikazioei."</string>
<string name="permlab_fullScreenIntent" msgid="4310888199502509104">"blokeatutako gailu batean jakinarazpenak pantaila osoko jarduera gisa bistaratzea"</string>
- <string name="permdesc_fullScreenIntent" msgid="1100721419406643997">"Blokeatutako gailu batean jakinarazpenak pantaila osoko jarduera gisa bistaratzeko baimena ematen dio aplikazioari"</string>
+ <string name="permdesc_fullScreenIntent" msgid="1100721419406643997">"Blokeatutako gailu batean jakinarazpenak pantaila osoko jarduera gisa bistaratzeko baimena ematen die aplikazioei"</string>
<string name="permlab_install_shortcut" msgid="7451554307502256221">"instalatu lasterbideak"</string>
<string name="permdesc_install_shortcut" msgid="4476328467240212503">"Erabiltzaileak ezer egin gabe hasierako pantailan lasterbideak gehitzeko aukera ematen die aplikazioei."</string>
<string name="permlab_uninstall_shortcut" msgid="295263654781900390">"desinstalatu lasterbideak"</string>
@@ -360,7 +363,7 @@
<string name="permlab_receiveMms" msgid="4000650116674380275">"jaso testu-mezuak (MMSak)"</string>
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"desbideratu sare mugikor bidezko igorpen-mezuak"</string>
- <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sare mugikor bidezko igorpen-modulura lotzeko baimena ematen dio aplikazioari, sare mugikor bidezko igorpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko igorpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-igorpenak jasotzean, asmo txarreko aplikazioek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string>
+ <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sare mugikor bidezko igorpen-modulura lotzeko baimena ematen die aplikazioei, sare mugikor bidezko igorpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko igorpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-igorpenak jasotzean, asmo txarreko aplikazioek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string>
<string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Kudeatu abian dauden deiak"</string>
<string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Gailuak jasotzen dituen deiei buruzko xehetasunak ikusteko eta dei horiek kontrolatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"irakurri sare mugikor bidezko igorpen-mezuak"</string>
@@ -410,13 +413,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Igorpen iraunkorrak egiteko baimena ematen die aplikazioei. Igorpena amaitu ondoren ere igortzen jarraitzen dute igorpen iraunkorrek. Gehiegi erabiliz gero, Android TV gailua motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Igorpen iraunkorrak emateko baimena ematen die; horiek igorpena amaitu ondoren mantentzen dira. Gehiegi erabiliz gero, telefonoa motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"irakurri kontaktuak"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Tabletan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten tabletako kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
- <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Android TV gailuan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten Android TV gailuko kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
- <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Telefonoan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten telefonoko kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Tabletan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen die aplikazioei. Kontaktuak sortu dituzten tabletako kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Android TV gailuan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen die aplikazioei. Kontaktuak sortu dituzten Android TV gailuko kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Telefonoan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen die aplikazioei. Kontaktuak sortu dituzten telefonoko kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"aldatu kontaktuak"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Tabletan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Android TV gailuan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
- <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Telefonoan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Tabletan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Android TV gailuan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Telefonoan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"irakurri deien erregistroa"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Aplikazioak deien historia irakur dezake."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"idatzi deien erregistroan"</string>
@@ -461,7 +464,7 @@
<string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"Kamera ireki edo itxi dela (eta zer aplikaziorekin) dioten jakinarazpenak jaso ditzake aplikazio honek."</string>
<string name="permlab_vibrate" msgid="8596800035791962017">"kontrolatu dardara"</string>
<string name="permdesc_vibrate" msgid="8733343234582083721">"Bibragailua kontrolatzeko aukera ematen die aplikazioei."</string>
- <string name="permdesc_vibrator_state" msgid="7050024956594170724">"Dardara-egoera atzitzeko baimena ematen dio aplikazioari."</string>
+ <string name="permdesc_vibrator_state" msgid="7050024956594170724">"Dardara-egoera atzitzeko baimena ematen die aplikazioei."</string>
<string name="permlab_callPhone" msgid="1798582257194643320">"deitu zuzenean telefono-zenbakietara"</string>
<string name="permdesc_callPhone" msgid="5439809516131609109">"Telefono-zenbakietara zuk esku hartu gabe deitzeko baimena ematen die aplikazioei. Horrela, ustekabeko gastuak edo deiak eragin daitezke. Asmo txarreko aplikazioek erabil dezakete zuk berretsi gabeko deiak eginda gastuak eragiteko."</string>
<string name="permlab_accessImsCallService" msgid="442192920714863782">"atzitu IMS dei-zerbitzua"</string>
@@ -471,7 +474,7 @@
<string name="permlab_manageOwnCalls" msgid="9033349060307561370">"bideratu deiak sistemaren bidez"</string>
<string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"Deiak sistemaren bidez bideratzea baimentzen die aplikazioei, deien zerbitzua ahal bezain ona izan dadin."</string>
<string name="permlab_callCompanionApp" msgid="3654373653014126884">"ikusi eta kontrolatu deiak sistemaren bidez."</string>
- <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"Gailuan abian diren deiak eta deion informazioa ikusi eta kontrolatzeko baimena ematen dio aplikazioari; besteak beste, deien zenbakiak eta deien egoera."</string>
+ <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"Gailuan abian diren deiak eta deion informazioa ikusi eta kontrolatzeko baimena ematen die aplikazioei; besteak beste, deien zenbakiak eta deien egoera."</string>
<string name="permlab_exemptFromAudioRecordRestrictions" msgid="1164725468350759486">"salbuetsi audioa grabatzeko murriztapenen aurrean"</string>
<string name="permdesc_exemptFromAudioRecordRestrictions" msgid="2425117015896871976">"Salbuetsi aplikazioa audioa grabatzeko murriztapenen aurrean."</string>
<string name="permlab_acceptHandover" msgid="2925523073573116523">"jarraitu beste aplikazio batean hasitako deia"</string>
@@ -482,7 +485,7 @@
<string name="permlab_wakeLock" product="tablet" msgid="1527660973931694000">"eragotzi tableta inaktibo ezartzea"</string>
<string name="permlab_wakeLock" product="tv" msgid="2856941418123343518">"Android TV gailua inaktibo ezar dadin eragotzi"</string>
<string name="permlab_wakeLock" product="default" msgid="569409726861695115">"eragotzi telefonoa inaktibo ezartzea"</string>
- <string name="permdesc_wakeLock" product="automotive" msgid="5995045369683254571">"Autoko pantaila piztuta mantentzeko baimena ematen dio aplikazioari."</string>
+ <string name="permdesc_wakeLock" product="automotive" msgid="5995045369683254571">"Autoko pantaila piztuta mantentzeko baimena ematen die aplikazioei."</string>
<string name="permdesc_wakeLock" product="tablet" msgid="2441742939101526277">"Tableta inaktibo ezartzea galaraztea baimentzen die aplikazioei."</string>
<string name="permdesc_wakeLock" product="tv" msgid="2329298966735118796">"Android TV gailua inaktibo ezartzea eragozteko baimena ematen die aplikazioei."</string>
<string name="permdesc_wakeLock" product="default" msgid="3689523792074007163">"Telefonoa inaktibo ezartzea galaraztea baimentzen die aplikazioei."</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tabletaren Bluetooth konfigurazioa ikusteko eta parekatutako gailuekin konexioak egiteko eta onartzeko baimena ematen die aplikazioei."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV gailuaren Bluetooth bidezko konexioaren konfigurazioa ikusteko eta parekatutako gailuekin konexioak sortzeko eta onartzeko baimena ematen die aplikazioei."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Telefonoaren Bluetooth konfigurazioa ikusteko eta parekatutako gailuekin konexioak egiteko eta onartzeko baimena ematen die aplikazioei."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"inguruko Bluetooth bidezko gailuak hauteman eta haiekin parekatu"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Inguruko Bluetooth bidezko gailuak hautemateko eta haiekin parekatzeko baimena ematen die aplikazioei"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"parekatutako Bluetooth bidezko gailuetara konektatu"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Parekatutako Bluetooth bidezko gailuetara konektatzeko baimena ematen die aplikazioei"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Aplikazioari baimena ematen dio NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa jasotzeko, hala nola erregistratutako laguntzaileak eta ibilbidearen helmuga."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrolatu Near Field Communication komunikazioa"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Errorea autentifikatzean"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Erabili pantailaren blokeoa"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Aurrera egiteko, idatzi gailuaren kredentzialak"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Hatz-marka ez da osorik hauteman. Saiatu berriro."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Ezin izan da prozesatu hatz-marka. Saiatu berriro."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Hatz-marken sentsorea zikina dago. Garbi ezazu, eta saiatu berriro."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Hatza azkarregi mugitu duzu. Saiatu berriro."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Mantsoegi mugitu duzu hatza. Saiatu berriro."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Autentifikatu da hatz-marka"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Autentifikatu da aurpegia"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Autentifikatu da aurpegia; sakatu Berretsi"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hatz-marken hardwarea ez dago erabilgarri."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Ezin da gorde hatz-marka digitala. Kendu lehendik gordeta duzunetako bat."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Hatz-markak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Hatz-markaren eragiketa bertan behera utzi da."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Erabiltzaileak bertan behera utzi du hatz-marka bidezko eragiketa."</string>
@@ -599,10 +616,18 @@
<string name="permlab_manageFace" msgid="4569549381889283282">"kudeatu aurpegiaren bidez desblokeatzeko hardwarea"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Aurpegi-txantiloiak gehitu eta ezabatzeko metodoei dei egitea baimentzen dio aplikazioari."</string>
<string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"erabili aurpegiaren bidez desblokeatzeko hardwarea"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Autentifikazioa egiteko aurpegiaren bidez desblokeatzeko hardwarea erabiltzeko baimena ematen dio aplikazioari"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Autentifikaziorako aurpegiaren bidez desblokeatzeko hardwarea erabiltzeko baimena ematen die aplikazioei"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Aurpegiaren bidez desblokeatzeko eginbidea"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Erregistratu aurpegia berriro"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Ezagutzea hobetzeko, erregistratu aurpegia berriro"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Ezin izan dira bildu argazkiaren datu zehatzak. Saiatu berriro."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Argi gehiegi dago. Joan toki ilunago batera."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Ilunegi dago. Erabili argi gehiago."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Kopiatu da"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> aplikaziotik itsatsi da <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Arbeletik itsatsi da <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Gehiago"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menua+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -1242,7 +1273,7 @@
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> abian da"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Sakatu jokora itzultzeko"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Aukeratu joko bat"</string>
- <string name="heavy_weight_switcher_text" msgid="6814316627367160126">"Funtzionamendu hobea izateko, joko hauetako bat baino ezin da egon irekita aldi berean."</string>
+ <string name="heavy_weight_switcher_text" msgid="6814316627367160126">"Errendimendu hobea izateko, joko hauetako bat baino ezin da egon irekita aldi berean."</string>
<string name="old_app_action" msgid="725331621042848590">"Itzuli <xliff:g id="OLD_APP">%1$s</xliff:g> aplikaziora"</string>
<string name="new_app_action" msgid="547772182913269801">"Ireki <xliff:g id="NEW_APP">%1$s</xliff:g>"</string>
<string name="new_app_description" msgid="1958903080400806644">"Gorde gabe itxiko da <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
@@ -1354,7 +1385,7 @@
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Proba-materialeko modua gaitu da"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Proba-materialaren modua desgaitzeko, berrezarri jatorrizko datuak."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"Serie-kontsola gaituta"</string>
- <string name="console_running_notification_message" msgid="7892751888125174039">"Funtzionamenduari eragiten dio. Desgaitzeko, joan abiarazlera."</string>
+ <string name="console_running_notification_message" msgid="7892751888125174039">"Errendimenduari eragiten dio. Desgaitzeko, joan abiarazlera."</string>
<string name="usb_contaminant_detected_title" msgid="4359048603069159678">"Likidoa edo zikinkeriak daude USB atakan"</string>
<string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB ataka automatikoki desgaitu da. Informazio gehiago lortzeko, sakatu hau."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"Erabiltzeko moduan dago USB ataka"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Lanekoa"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Ikuspegi pertsonala"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Laneko ikuspegia"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Ezin da partekatu laneko aplikazioekin"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IKT saileko administratzaileak ez dizu ematen baimenik eduki hau zure laneko profileko aplikazioekin partekatzeko"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Ezin da ireki laneko aplikazioekin"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IKT saileko administratzaileak ez dizu ematen baimenik eduki hau zure laneko profileko aplikazioekin irekitzeko"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Ezin da partekatu aplikazio pertsonalekin"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IKT saileko administratzaileak ez dizu ematen baimenik eduki hau zure profil pertsonaleko aplikazioekin partekatzeko"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Ezin da ireki aplikazio pertsonalekin"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IKT saileko administratzaileak ez dizu ematen baimenik eduki hau zure profil pertsonaleko aplikazioekin irekitzeko"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Laneko profila pausatuta dago"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Aktibatu"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Ez dago eduki honekin bateragarria den laneko aplikaziorik"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Ez dago eduki hau ireki dezakeen laneko aplikaziorik"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Ez dago eduki honekin bateragarria den aplikazio pertsonalik"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Ez dago eduki hau ireki dezakeen aplikazio pertsonalik"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIMaren sarearen bidez desblokeatzeko PIN kodea"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIMaren sareko azpimultzoaren bidez desblokeatzeko PIN kodea"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Enpresaren SIMaren bidez desblokeatzeko PIN kodea"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Handitu pantailaren zati bat"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Orain, pantaila osoa edo eremu zehatz bat handi dezakezu, edo bi aukeren artean aldatu."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktibatu ezarpenetan"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Baztertu"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Aurrera egiteko, gailuaren mikrofonoa atzitzeko baimena behar du <b><xliff:g id="APP">%s</xliff:g></b> aplikazioak."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 19d6256..7ce6cf0 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"برنامه درحال اجرا"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"برنامههای مصرفکننده باتری"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"درشتنمایی"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"خطمشی امنیتی دسترسپذیری"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحال استفاده کردن از باتری است"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> برنامه درحال استفاده کردن از باتری هستند"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"برای جزئیات مربوط به مصرف باتری و داده، ضربه بزنید"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"دسترسی به فعالیت فیزیکی شما"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"دوربین"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"عکس گرفتن و فیلمبرداری"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"دستگاههای بلوتوث اطراف"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"پیدا کردن دستگاههای بلوتوث اطراف و اتصال به آنها"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"گزارشهای تماس"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"خواندن و نوشتن گزارش تماس تلفنی"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"تلفن"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"به برنامه اجازه میدهد تا پیکربندی بلوتوث در رایانهٔ لوحی را مشاهده کند و اتصال با دستگاههای مرتبط را برقرار کرده و بپذیرد."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"به برنامه اجازه میدهد پیکربندی بلوتوث را در دستگاه Android TV شما ببیند، و اتصالات با دستگاههای مرتبطشده را بپذیرد یا این اتصالات را برقرار کند."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"به برنامه اجازه میدهد تا پیکربندی بلوتوث در تلفن را مشاهده کند، و اتصالات دستگاههای مرتبط را برقرار کرده و بپذیرد."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"یافتن دستگاههای بلوتوث اطراف و مرتبط شدن با آنها"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"به برنامه اجازه میدهد دستگاههای بلوتوث اطراف را پیدا کند و با آنها مرتبط شود"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"اتصال به دستگاههای بلوتوث مرتبطشده"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"به برنامه اجازه میدهد به دستگاههای بلوتوث مرتبطشده متصل شود"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"اطلاعات ترجیحی سرویس پولی «ارتباط میدان نزدیک» (NFC)"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"به برنامه اجازه میدهد اطلاعات ترجیحی سرویس پولی «ارتباط میدان نزدیک» (NFC)، مانند کمکهای ثبتشده و مقصد مسیر را دریافت کند."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"کنترل ارتباط راه نزدیک"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"خطا هنگام اصالتسنجی"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"از قفل صفحه استفاده کنید"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"برای ادامه، اطلاعات کاربری دستگاهتان را وارد کنید"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"بخشی از اثر انگشت شناسایی شد. لطفاً دوباره امتحان کنید."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"اثرانگشت پردازش نشد. لطفاً دوباره امتحان کنید."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"حسگر اثر انگشت کثیف است. لطفاً آن را تمیز کنید و دوباره امتحان نمایید."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"حرکت انگشت خیلی سریع بود. لطفاً دوباره امتحان کنید."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"حرکت انگشت خیلی آهسته بود. لطفاً دوباره امتحان کنید."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"اثر انگشت اصالتسنجی شد"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"چهره اصالتسنجی شد"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"چهره اصالتسنجی شد، لطفاً تأیید را فشار دهید"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"سختافزار اثرانگشت در دسترس نیست."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ذخیره اثر انگشت ممکن نیست. لطفاً یک اثر انگشت موجود را حذف کنید."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"درنگ ثبت اثر انگشت به پایان رسید. دوباره امتحان کنید."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"عملکرد اثر انگشت لغو شد."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"کاربر عملیات اثر انگشت را لغو کرد"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"بازگشایی با چهره"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ثبت مجدد چهره"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"برای بهبود تشخیص، لطفاً چهرهتان را دوباره ثبت کنید"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"دادههای دقیق چهره ضبط نشد. دوباره امتحان کنید."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"خیلی روشن است. روشناییاش را ملایمتر کنید."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"خیلی تاریک است. تصویر را روشنتر کنید."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"کپی شد"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> از <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> جایگذاری کرد"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> از بریدهدان جایگذاری کرد"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"بیشتر"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"منو+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"کاری"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"نمای شخصی"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"نمای کاری"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"این محتوا با برنامههای کاری همرسانی نمیشود"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"سرپرست فناوری اطلاعات اجازه نمیدهد این محتوا را با برنامههای موجود در نمایه کاری همرسانی کنید"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"این محتوا با برنامههای کاری باز نمیشود"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"سرپرست فناوری اطلاعات اجازه نمیدهد این محتوا را با برنامههای موجود در نمایه کاری باز کنید"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"این محتوا با برنامههای شخصی همرسانی نمیشود"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"سرپرست فناوری اطلاعات اجازه نمیدهد این محتوا را با برنامههای موجود در نمایه شخصی همرسانی کنید"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"این محتوا با برنامههای شخصی باز نمیشود"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"سرپرست فناوری اطلاعات اجازه نمیدهد این محتوا را با برنامههای موجود در نمایه شخصی باز کنید"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"نمایه کاری موقتاً متوقف شده است"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"روشن کردن"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"هیچکدام از برنامههای کاری نمیتوانند از این محتوا پشتیبانی کنند"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"هیچکدام از برنامههای کاری نمیتوانند این محتوا را باز کنند"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"هیچکدام از برنامههای شخصی نمیتوانند از این محتوا پشتیبانی کنند"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"هیچکدام از برنامههای شخصی نمیتوانند این محتوا را باز کنند"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"پین باز کردن قفل شبکه سیمکارت"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"پین باز کردن قفل زیرمجموعه شبکه سیمکارت"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"پین باز کردن قفل شرکت سیمکارت"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"درشتنمایی بخشی از صفحهنمایش"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"اکنون میتوانید بخش مشخصی صفحه یا کل آن را درشتنمایی کنید، یا بیت دو گزینه جابهجا شوید."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"روشن کردن در «تنظیمات»"</string>
<string name="dismiss_action" msgid="1728820550388704784">"رد شدن"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"برای ادامه دادن، <b><xliff:g id="APP">%s</xliff:g></b> باید به میکروفون دستگاه دسترسی داشته باشد."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index d78dffc..7320df7 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Sovellus käynnissä"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkua kuluttavat sovellukset"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Suurennus"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Esteettömyyden tietoturvakäytäntö"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> käyttää akkua."</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> sovellusta käyttää akkua."</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Katso lisätietoja akun ja datan käytöstä napauttamalla."</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"nähdä liikkumistietosi"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ottaa kuvia ja videoita"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Lähellä olevat Bluetooth-laitteet"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"löytää lähellä olevia Bluetooth-laitteita ja yhdistää niihin"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Puhelulokit"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"lukea puhelulokia ja kirjoittaa siihen"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Puhelin"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Antaa sovelluksen tarkastella tablet-laitteen Bluetooth-asetuksia sekä muodostaa ja hyväksyä laitepariyhteyksiä."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Antaa sovelluksen nähdä Android TV ‑laitteen Bluetooth-asetukset sekä muodostaa ja hyväksyä laitepariyhteyksiä."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Antaa sovelluksen tarkastella puhelimen Bluetooth-asetuksia sekä muodostaa ja hyväksyä laitepariyhteyksiä muihin laitteisiin."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"löytää Bluetooth-laitteita ja tehdä laitepareja"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Sallii sovelluksen löytää lähellä olevia Bluetooth-laitteita ja muodostaa niistä laitepareja"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"yhdistää pariliitettyihin Bluetooth-laitteisiin"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Sallii sovelluksen muodostaa yhteyden pariliitettyihin Bluetooth-laitteisiin"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Ensisijaiset NFC-maksupalvelutiedot"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Sallii sovelluksen noutaa tietoja rekisteröidyistä sovellustunnuksista, maksureitin kohteesta ja muita ensisijaisia NFC-maksupalvelutietoja."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"hallitse Near Field Communication -tunnistusta"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Virhe todennuksessa"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Käytä näytön lukitusta"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Jatka lisäämällä laitteesi kirjautumistiedot"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Sormenjälki havaittiin vain osittain. Yritä uudelleen."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Sormenjäljen prosessointi epäonnistui. Yritä uudelleen."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Sormenjälkitunnistin on likainen. Puhdista tunnistin ja yritä uudelleen."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Liikutit sormea liian nopeasti. Yritä uudelleen."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Liikutit sormea liian hitaasti. Yritä uudelleen."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Sormenjälki tunnistettu"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Kasvot tunnistettu"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Kasvot tunnistettu, valitse Vahvista"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Sormenjälkilaitteisto ei ole käytettävissä."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Sormenjälkeä ei voida tallentaa. Poista aiemmin lisätty sormenjälki."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Sormenjälkitunnistimen toiminta aikakatkaistiin. Yritä uudelleen."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Sormenjälkitoiminto peruutettiin."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Käyttäjä peruutti sormenjälkitoiminnon."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Lisää kasvot uudelleen"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Lisää kasvosi uudelleen tunnistamisen parantamiseksi"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Tarkan kasvodatan tallennus epäonnistui. Yritä uudelleen."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Liian kirkasta. Kokeile pehmeämpää valaistusta."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Liian pimeää. Kokeile kirkkaampaa valaistusta."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Kopioitu"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> liitetty täältä: <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> liitetty leikepöydältä"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Lisää"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Valikko+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Työ"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Henkilökohtainen näkymä"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Työnäkymä"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Tätä ei voi jakaa työsovelluksilla"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT-järjestelmänvalvoja ei anna sinun jakaa tätä sisältöä työprofiilisi sovelluksilla"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Tätä ei voi avata työsovelluksilla"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT-järjestelmänvalvoja ei anna sinun avata tätä sisältöä työprofiilisi sovelluksilla"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Tätä ei voi jakaa henkilökohtaisilla sovelluksilla"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT-järjestelmänvalvoja ei anna sinun jakaa tätä sisältöä henkilökohtaisen profiilisi sovelluksilla"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Tätä ei voi avata henkilökohtaisilla sovelluksilla"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT-järjestelmänvalvoja ei anna sinun avata tätä sisältöä henkilökohtaisen profiilisi sovelluksilla"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Työprofiilin käyttö on keskeytetty"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Laita päälle"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Työsovellukset eivät voi tukea tätä sisältöä"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Työsovelluksilla ei voi avata tätä sisältöä"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Henkilökohtaiset sovellukset eivät voi tukea tätä sisältöä"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Henkilökohtaisilla sovelluksilla ei voi avata tätä sisältöä"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM-kortin verkkoversion lukituksen avaamisen PIN-koodi"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM-kortin verkkoversion alijoukon lukituksen avaamisen PIN-koodi"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM-kortin yritysversion lukituksen avaamisen PIN-koodi"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Suurenna näytön osa"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Voit nyt suurentaa koko näytön tai tietyn alueen tai vaihtaa yhdestä näistä vaihtoehdoista toiseen."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Laita päälle asetuksista"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Hylkää"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Jotta voit jatkaa, <b><xliff:g id="APP">%s</xliff:g></b> tarvitsee pääsyn laitteesi mikrofoniin."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 3f18daf..a6c8195 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Application en cours d\'exécution"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications qui sollicitent la pile"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Agrandissement"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Politique de sécurité relative aux fonctionnalités d\'accessibilité"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sollicite la pile"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications sollicitent la pile"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Touchez pour afficher des détails sur l\'utilisation de la pile et des données"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"accéder à vos activités physiques"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Appareil photo"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"prendre des photos et filmer des vidéos"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Appareils Bluetooth à proximité"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"découvrir les appareils Bluetooth à proximité et s\'y connecter"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Journaux d\'appels"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"lire et écrire le journal des appels téléphoniques"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Téléphone"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur la tablette, et d\'établir et accepter des connexions avec les appareils associés."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permet à l\'application d\'afficher la configuration du Bluetooth sur votre appareil Android TV, de se connecter à des appareils associés et d\'accepter leur connexion."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur le téléphone, et d\'établir et accepter des connexions avec les appareils associés."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"découvrir des appareils Bluetooth et s\'y connecter"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permet à l\'application de découvrir les appareils Bluetooth à proximité et de s\'y connecter"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"se connecter aux appareils Bluetooth associés"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permet à l\'application de se connecter aux appareils Bluetooth associés"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Information sur le service préféré de paiement NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permet à l\'application d\'obtenir de l\'information sur le service préféré de paiement NFC comme les aides enregistrées et la route de destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"gérer la communication en champ proche"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Erreur d\'authentification"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utiliser le verrouillage de l\'écran"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Entrez votre authentifiant d\'appareil pour continuer"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Empreinte digitale partielle détectée. Veuillez réessayer."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Impossible de reconnaître l\'empreinte digitale. Veuillez réessayer."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Le capteur d\'empreintes digitales est sale. Veuillez le nettoyer et réessayer."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Vous avez déplacé votre doigt trop rapidement. Veuillez réessayer."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Vous avez déplacé votre doigt trop lentement. Veuillez réessayer."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Empreinte digitale authentifiée"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Visage authentifié"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Visage authentifié, veuillez appuyer sur le bouton Confirmer"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Matériel d\'empreinte digitale numérique indisponible."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"L\'empreinte digitale ne peut pas être enregistrée. Veuillez supprimer une empreinte existante."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Le temps attribué pour lire l\'empreinte digitale est écoulé. Veuillez réessayer."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Opération d\'empreinte digitale numérique annulée."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"L\'opération d\'empreinte digitale a été annulée par l\'utilisateur."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Déverrouillage par reconnaissance faciale"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Inscrivez votre visage à nouveau"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Pour améliorer la reconnaissance, veuillez enregistrer à nouveau votre visage"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Imposs. capt. données visage précises. Réessayez."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Trop lumineux. Essayez un éclairage plus faible."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Trop sombre. Essayez avec un éclairage plus fort."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Copié"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> collé à partir de <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> collé à partir du presse-papiers"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Plus"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Méta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Professionnel"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Affichage personnel"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Affichage professionnel"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Partage impossible avec les applications professionnelles"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Votre administrateur informatique ne vous permet pas de partager ce contenu à l\'aide des applications qui figurent dans votre profil professionnel"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Ouverture impossible avec les applications professionnelles"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Votre administrateur informatique ne vous permet pas d\'ouvrir ce contenu à l\'aide des applications qui figurent dans votre profil professionnel"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Partage impossible avec les applications personnelles"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Votre administrateur informatique ne vous permet pas de partager ce contenu à l\'aide des applications qui figurent dans votre profil personnel"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Ouverture impossible avec les applications personnelles"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Votre administrateur informatique ne vous permet pas d\'ouvrir ce contenu à l\'aide des applications qui figurent dans votre profil personnel"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Le profil professionnel est interrompu"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Activer"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Aucune de vos applications professionnelles ne prend en charge ce contenu"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Aucune de vos applications professionnelles ne peut ouvrir ce contenu"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Aucune de vos applications personnelles ne prend en charge ce contenu"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Aucune de vos applications personnelles ne peut ouvrir ce contenu"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"NIP de déverrouillage du réseau associé au module SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"NIP de déverrouillage du sous-ensemble du réseau associé au module SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"NIP de déverrouillage du module SIM professionnel"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Agrandir une partie de votre écran"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Vous pouvez maintenant agrandir la totalité de votre écran, une région précise ou passer d\'une option à l\'autre."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activer dans les paramètres"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Fermer"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Pour continuer, vous devez accorder l\'accès au microphone de votre appareil à l\'application <b><xliff:g id="APP">%s</xliff:g></b>."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 10a3bad..48b3f26 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Application en cours d\'exécution"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications utilisant la batterie"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Agrandissement"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Règlement sur la sécurité de l\'accessibilité"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise la batterie"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications utilisent la batterie"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Appuyer pour obtenir des informations sur l\'utilisation de la batterie et des données"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"accéder aux données d\'activité physique"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Appareil photo"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"prendre des photos et enregistrer des vidéos"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Appareils Bluetooth à proximité"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"détecter les appareils Bluetooth à proximité et s\'y connecter"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Journaux d\'appels"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"Consulter et modifier les journaux d\'appels du téléphone"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Téléphone"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur la tablette, et d\'établir et accepter des connexions avec les appareils associés."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permet à l\'application d\'afficher la configuration du Bluetooth sur votre appareil Android TV, de se connecter à des appareils associés et d\'accepter leur connexion."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur le téléphone, et d\'établir et accepter des connexions avec les appareils associés."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"détecter/associer appareils Bluetooth à proximité"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Autorise l\'appli à détecter et à associer les appareils Bluetooth à proximité"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"se connecter aux appareils Bluetooth associés"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Autorise l\'appli à se connecter à des appareils Bluetooth associés"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informations sur le service de paiement NFC préféré"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permet à l\'application d\'obtenir des informations sur le service de paiement NFC préféré, y compris les ID d\'applications et les destinations de routage enregistrés."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"contrôler la communication en champ proche"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Erreur d\'authentification"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utiliser verrouillage écran"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Saisissez l\'identifiant de l\'appareil pour continuer"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Empreinte digitale partiellement détectée. Veuillez réessayer."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Impossible de reconnaître l\'empreinte digitale. Veuillez réessayer."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Le lecteur d\'empreinte digitale est sale. Veuillez le nettoyer, puis réessayer."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Vous avez déplacé votre doigt trop rapidement. Veuillez réessayer."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Vous avez déplacé votre doigt trop lentement. Veuillez réessayer."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Empreinte digitale authentifiée"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Visage authentifié"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Visage authentifié, veuillez appuyer sur \"Confirmer\""</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Matériel d\'empreinte digitale indisponible."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Impossible d\'enregistrer l\'empreinte digitale. Veuillez en supprimer une autre."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Délai de détection de l\'empreinte digitale expiré. Veuillez réessayer."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Opération d\'empreinte digitale annulée."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Opération d\'authentification par empreinte digitale annulée par l\'utilisateur."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Enregistrer à nouveau votre visage"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Pour améliorer la reconnaissance, veuillez enregistrer à nouveau votre visage"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Capture du visage impossible. Réessayez."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Trop lumineux. Essayez de baisser la lumière."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Trop sombre. Essayez une éclairage plus lumineux."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Copie effectuée"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> collé depuis <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> collé depuis le presse-papiers"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Plus"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Méta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Professionnel"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Vue personnelle"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Vue professionnelle"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Impossible de partager ce contenu avec les applications professionnelles"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Votre administrateur informatique ne vous autorise pas à partager ce contenu avec les applications de votre profil professionnel"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Impossible d\'ouvrir ce contenu avec les applications professionnelles"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Votre administrateur informatique ne vous autorise pas à ouvrir ce contenu avec les applications de votre profil professionnel"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Impossible de partager ce contenu avec les applications personnelles"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Votre administrateur informatique ne vous autorise pas à partager ce contenu avec les applications de votre profil personnel"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Impossible d\'ouvrir ce contenu avec les applications personnelles"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Votre administrateur informatique ne vous autorise pas à ouvrir ce contenu avec les applications de votre profil personnel"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Profil professionnel en pause"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Activer"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Aucune application professionnelle ne prend en charge ce contenu"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Aucune application professionnelle ne peut ouvrir ce contenu"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Aucune application personnelle ne prend en charge ce contenu"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Aucune application personnelle ne peut ouvrir ce contenu"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Code PIN de déblocage du réseau SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Code PIN de déblocage du sous-ensemble du réseau SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Code PIN de déblocage de la carte SIM d\'entreprise"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Agrandissez une partie de l\'écran"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Vous pouvez agrandir tout ou partie de l\'écran, ou basculer entre ces deux options."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activer dans les paramètres"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Fermer"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Pour continuer, <b><xliff:g id="APP">%s</xliff:g></b> a besoin d\'accéder au micro de votre appareil."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 0aac641..69ab060 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Estase executando a aplicación"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacións que consomen batería"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Política de seguranza relativa á accesibilidade"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo batería"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacións están consumindo batería"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para obter información sobre o uso de datos e a batería"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"acceder á túa actividade física"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Cámara"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"tirar fotos e gravar vídeos"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Dispositivos Bluetooth próximos"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"detectar dispositivos Bluetooth próximos e conectarse a eles"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Rexistros de chamadas"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ler e editar o rexistro de chamadas do teléfono"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Teléfono"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite á aplicación ver a configuración do Bluetooth na tableta e efectuar e aceptar conexións con dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que a aplicación consulte a configuración do Bluetooth no dispositivo Android TV, e efectúe e acepte conexións con dispositivos vinculados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite á aplicación ver a configuración do Bluetooth no teléfono e efectuar e aceptar conexións con dispositivos sincronizados."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"detectar e vincular dispositivos Bluetooth"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permite que a aplicación detecte dispositivos Bluetooth próximos e se vincule a eles"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"conectarse a dispositivos Bluetooth vinculados"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permite que a aplicación se conecte aos dispositivos Bluetooth vinculados"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Información do servizo de pago de NFC preferido"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que a aplicación obteña información do servizo de pago de NFC preferido, como as axudas rexistradas e o destino da ruta."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar Near Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Produciuse un erro ao realizar a autenticación"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar credencial do dispositivo"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Para continuar, mete a credencial do dispositivo"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Detectouse unha impresión dixital parcial. Téntao de novo."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Non se puido procesar a impresión dixital. Téntao de novo."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"O sensor de impresión dixital está sucio. Límpao e téntao de novo."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Moviches o dedo demasiado rápido. Téntao de novo."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"O dedo moveuse demasiado lento. Téntao de novo."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Autenticouse a impresión dixital"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Autenticouse a cara"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Autenticouse a cara, preme Confirmar"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware de impresión dixital non dispoñible."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Non se pode almacenar a impresión dixital. Elimina unha impresión dixital existente."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Esgotouse o tempo de espera da impresión dixital. Téntao de novo."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Cancelouse a operación da impresión dixital."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"O usuario cancelou a operación da impresión dixital."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Desbloqueo facial"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Volve inscribir a túa cara"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Para mellorar o recoñecemento, inscribe de novo a túa cara"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Sen datos faciais exactos. Téntao de novo."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Hai demasiada iluminación. Proba cunha máis suave."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Hai demasiada escuridade. Proba con máis luz."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Copiuse"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pegou contido procedente de <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> pegou contido procedente do portapapeis"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Máis"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menú+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -1689,8 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atallo"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de cor"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Corrección de cor"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (3222994553174604132) -->
- <skip />
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuación extra"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume premidas. Activouse o servizo <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Desactivouse <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premidas as teclas do volume durante tres segudos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -2111,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Traballo"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Vista persoal"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Vista de traballo"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Non se pode compartir este contido coas aplicacións do traballo"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"O teu administrador de TI non permite compartir este contido coas aplicacións do teu perfil de traballo"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Non se pode abrir este contido coas aplicacións do traballo"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"O teu administrador de TI non permite abrir este contido coas aplicacións do teu perfil de traballo"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Non se pode compartir este contido coas aplicacións persoais"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"O teu administrador de TI non permite compartir este contido coas aplicacións do teu perfil persoal"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Non se pode abrir este contido coas aplicacións persoais"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"O teu administrador de TI non permite abrir este contido coas aplicacións do teu perfil persoal"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"O perfil de traballo está en pausa"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Activar"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Ningunha aplicación do traballo admite este contido"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Ningunha aplicación do traballo pode abrir este contido"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Ningunha aplicación persoal admite este contido"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Ningunha aplicación persoal pode abrir este contido"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN de desbloqueo da rede SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN de desbloqueo do subconxunto da rede SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN de desbloqueo corporativo da SIM"</string>
@@ -2237,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Amplía parte da pantalla"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Xa podes ampliar a pantalla completa ou unha área específica, ou ben alternar entre ambas as dúas opcións."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Configuración"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Ignorar"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Para continuar, <b><xliff:g id="APP">%s</xliff:g></b> precisa acceder ao micrófono do dispositivo."</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 40af808..60d95a3 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ઍપ ચાલી રહ્યું છે"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ઍપ બૅટરીનો વપરાશ કરી રહ્યાં છે"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"મોટું કરવાની સુવિધા"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"ઍક્સેસિબિલિટી સુરક્ષા પૉલિસી"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> બૅટરીનો ઉપયોગ કરી રહ્યું છે"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ઍપ બૅટરીનો ઉપયોગ કરી રહ્યાં છે"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"બૅટરી અને ડેટા વપરાશ વિશેની વિગતો માટે ટૅપ કરો"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"તમારી શારીરિક પ્રવૃત્તિને ઍક્સેસ કરવી"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"કૅમેરા"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ચિત્રો લેવાની અને વીડિઓ રેકોર્ડ કરવાની"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"આસપાસના બ્લૂટૂથ ડિવાઇસ"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"આસપાસના બ્લૂટૂથ ડિવાઇસ શોધો અને તેમની સાથે કનેક્ટ કરો"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"કૉલ લૉગ"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ફોન કૉલ લૉગ વાંચો અને લખો"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ફોન"</string>
@@ -364,7 +367,7 @@
<string name="permlab_manageOngoingCalls" msgid="281244770664231782">"ચાલી રહેલા કૉલ મેનેજ કરો"</string>
<string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"ઍપને તમારા ડિવાઇસ પર ચાલુ કૉલ વિશેની વિગતો જોવાની અને આ કૉલને નિયંત્રિત કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"સેલ બ્રોડકાસ્ટ સંદેશા વાંચો"</string>
- <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"એપ્લિકેશનને તમારા ઉપકરણ દ્વારા પ્રાપ્ત થયેલ સેલ બ્રોડકાસ્ટ સંદેશાને વાંચવાની મંજૂરી આપે છે. સેલ બ્રોડકાસ્ટ ચેતવણીઓ તમને કટોકટીની સ્થિતિઓ અંગે ચેતવવા માટે કેટલાક સ્થાનોમાં વિતરિત થાય છે. જ્યારે કટોકટીનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય ત્યારે દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારા ઉપકરણના પ્રદર્શન અથવા ઓપરેશનમાં હસ્તક્ષેપ કરી શકે છે."</string>
+ <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ઍપ તમારા ડિવાઇસ દ્વારા પ્રાપ્ત થયેલ સેલ બ્રોડકાસ્ટ સંદેશાને વાંચવાની મંજૂરી આપે છે. સેલ બ્રોડકાસ્ટ ચેતવણીઓ તમને ઇમર્જન્સીની સ્થિતિઓ અંગે ચેતવવા માટે કેટલાક સ્થાનોમાં વિતરિત થાય છે. જ્યારે ઇમર્જન્સીનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય ત્યારે દુર્ભાવનાપૂર્ણ ઍપ તમારા ડિવાઇસના કાર્યપ્રદર્શન અથવા ઓપરેશનમાં હસ્તક્ષેપ કરી શકે છે."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"સબ્સ્ક્રાઇબ કરેલ ફીડ્સ વાંચો"</string>
<string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"એપ્લિકેશનને હાલમાં સમન્વયિત ફીડ્સ વિશે વિગતો મેળવવાની મંજૂરી આપે છે."</string>
<string name="permlab_sendSms" msgid="7757368721742014252">"SMS સંદેશા મોકલો અને જુઓ"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"એપ્લિકેશનને ટેબ્લેટ પર બ્લૂટૂથ ની ગોઠવણી જોવાની અને જોડી કરેલ ઉપકરણો સાથે કનેક્શન્સ કરવાની અને સ્વીકારવાની મંજૂરી આપે છે."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ઍપને તમારા Android TV ડિવાઇસ પર બ્લૂટૂથની ગોઠવણી જોવાની અને જોડાણ કરેલા ડિવાઇસની સાથે કનેક્શન કરવાની અને સ્વીકારવાની મંજૂરી આપે છે."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"એપ્લિકેશનને ફોન પર બ્લૂટૂથ ની ગોઠવણી જોવાની અને જોડી કરેલ ઉપકરણો સાથે કનેક્શન્સ કરવાની અને સ્વીકારવાની મંજૂરી આપે છે."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"આસપાસના બ્લૂટૂથ ડિવાઇસ શોધો અને તેની સાથે જોડી કરો"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"ઍપને આસપાસના બ્લૂટૂથ ડિવાઇસ શોધવાની અને તેની સાથે જોડી કરવાની મંજૂરી આપે છે"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"જોડી કરેલા બ્લૂટૂથ ડિવાઇસ સાથે કનેક્ટ કરો"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"ઍપને જોડી કરેલા બ્લૂટૂથ ડિવાઇસ સાથે કનેક્ટ કરવાની મંજૂરી આપે છે"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"પસંદગીની NFC ચુકવણીની સેવા વિશે માહિતી"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"આ મંજૂરીને આપવાથી, ઍપ તમારી પસંદગીની NFC ચુકવણીની સેવા વિશે માહિતી મેળવી શકે છે, જેમ કે રજિસ્ટર થયેલી સહાય અને નિર્ધારિત સ્થાન."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"નિઅર ફીલ્ડ કમ્યુનિકેશન નિયંત્રિત કરો"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"પ્રમાણિત કરવામાં ભૂલ આવી"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"સ્ક્રીન લૉકનો ઉપયોગ કરો"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"ચાલુ રાખવા માટે તમારા ડિવાઇસની લૉગ ઇન વિગત દાખલ કરો"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"આંશિક ફિંગરપ્રિન્ટ મળી. કૃપા કરીને ફરી પ્રયાસ કરો."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ફિંગરપ્રિન્ટ પ્રક્રિયા કરી શકાઈ નથી. કૃપા કરીને ફરી પ્રયાસ કરો."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"ફિંગરપ્રિન્ટ સેન્સર ગંદું છે. કૃપા કરીને સાફ કરો અને ફરી પ્રયાસ કરો."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"આંગળી બહુ ઝડપથી ખસેડી. કૃપા કરીને ફરી પ્રયાસ કરો."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"આંગળી બહુ જ ધીમેથી ખસેડી. કૃપા કરીને ફરી પ્રયાસ કરો."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"ફિંગરપ્રિન્ટ પ્રમાણિત કરી"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ચહેરા પ્રમાણિત"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ચહેરા પ્રમાણિત, કૃપા કરીને કન્ફર્મ કરો"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ફિંગરપ્રિન્ટ હાર્ડવેર ઉપલબ્ધ નથી."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ફિંગરપ્રિન્ટ સંગ્રહિત કરી શકાતી નથી. કૃપા કરીને અસ્તિત્વમાંની ફિંગરપ્રિન્ટ દૂર કરો."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"ફિંગરપ્રિન્ટનો સમય બાહ્ય થયો. ફરી પ્રયાસ કરો."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ફિંગરપ્રિન્ટ ઓપરેશન રદ કર્યું."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ફિંગરપ્રિન્ટ ચકાસવાની પ્રક્રિયા વપરાશકર્તાએ રદ કરી."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ફેસ અનલૉક"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"તમારા ચહેરાની ફરી નોંધણી કરાવો"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ઓળખવાની પ્રક્રિયાને બહેતર બનાવવા માટે કૃપા કરીને તમારા ચહેરાની ફરી નોંધણી કરાવો"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"ચહેરાનો સચોટ ડેટા કૅપ્ચર ન થયો. ફરી પ્રયાસ કરો."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"અતિશય પ્રકાશિત. થોડો હળવો પ્રકાશ અજમાવી જુઓ."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"અતિશય ઘેરી. વધુ ઝળહળતો પ્રકાશ અજમાવો"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"કૉપિ કરેલ"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>માંથી કૉપિ કરાયેલો ડેટા <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>માં પેસ્ટ કરવામાં આવ્યો"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"ક્લિપબોર્ડ ડેટાને <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>માં પેસ્ટ કર્યો"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"વધુ"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"મેનૂ+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,8 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"શૉર્ટકટનો ઉપયોગ કરો"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"વિપરીત રંગમાં બદલવું"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"રંગ સુધારણા"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (3222994553174604132) -->
- <skip />
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"એક્સ્ટ્રા ડિમ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ચાલુ કરી."</string>
<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>
@@ -2111,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"ઑફિસ"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"વ્યક્તિગત વ્યૂ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"ઑફિસ વ્યૂ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"આને ઑફિસ માટેના ઍપ સાથે શેર કરી શકતાં નથી"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"તમારા IT વ્યવસ્થાપક તમને તમારી કાર્યાલયની પ્રોફાઇલમાંની ઍપ વડે આ કન્ટેન્ટ શેર કરવાની મંજૂરી આપતા નથી"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"ઑફિસ માટેની ઍપ વડે આને ખોલી શકતાં નથી"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"તમારા IT વ્યવસ્થાપક તમને તમારી ઑફિસની પ્રોફાઇલમાંની ઍપ વડે આ કન્ટેન્ટ ખોલવાની મંજૂરી આપતા નથી"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"આને વ્યક્તિગત ઍપ સાથે શેર કરી શકતાં નથી"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"તમારા IT વ્યવસ્થાપક તમને તમારી વ્યક્તિગત પ્રોફાઇલમાંની ઍપ વડે આ કન્ટેન્ટ શેર કરવાની મંજૂરી આપતા નથી"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"વ્યક્તિગત ઍપ વડે આને ખોલી શકતાં નથી"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"તમારા IT વ્યવસ્થાપક તમને તમારી વ્યક્તિગત પ્રોફાઇલમાંની ઍપ વડે આ કન્ટેન્ટ ખોલવાની મંજૂરી આપતા નથી"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"ઑફિસની પ્રોફાઇલ થોભાવી છે"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ચાલુ કરો"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"કોઈ ઑફિસ માટેની ઍપ આ કન્ટેન્ટને સપોર્ટ કરી શકતી નથી"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"કોઈ ઑફિસ માટેની ઍપ આ કન્ટેન્ટ ખોલી શકતી નથી"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"કોઈ વ્યક્તિગત ઍપ આ કન્ટેન્ટને સપોર્ટ કરી શકતી નથી"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"કોઈ વ્યક્તિગત ઍપ આ કન્ટેન્ટ ખોલી શકતી નથી"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"સિમ નેટવર્કને અનલૉક કરવાનો પિન"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"સિમ નેટવર્ક સબસેટને અનલૉક કરવાનો પિન"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"સિમ કૉર્પોરેટ કાર્ડના લૉકને અનલૉક કરવાનો પિન"</string>
@@ -2237,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"તમારી સ્ક્રીનનો અમુક ભાગ મોટો કરો"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"હવે તમે તમારી પૂર્ણ સ્ક્રીનને કે સ્ક્રીનના અમુક ચોક્કસ ભાગને મોટો કરી શકો છો અથવા બંને વિકલ્પો વચ્ચે સ્વિચ કરી શકો છો."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"સેટિંગમાં ચાલુ કરો"</string>
<string name="dismiss_action" msgid="1728820550388704784">"છોડી દો"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"ચાલુ રાખવા માટે, <b><xliff:g id="APP">%s</xliff:g></b>ને તમારા ડિવાઇસના માઇક્રોફોનના ઍક્સેસની જરૂર છે."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 20f703a..ba237ce 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ऐप अभी इस्तेमाल हो रहा है"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"बैटरी की खपत करने वाले ऐप"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ज़ूम करने की सुविधा"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"सुलभता सुविधाओं से जुड़ी सुरक्षा नीति"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बैटरी का इस्तेमाल कर रहा है"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ऐप बैटरी का इस्तेमाल कर रहे हैं"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बैटरी और डेटा खर्च की जानकारी के लिए छूएं"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"शारीरिक गतिविधि की जानकारी पा सकता है"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"कैमरा"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"चित्र लेने और वीडियो रिकॉर्ड करने"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"आस-पास मौजूद ब्लूटूथ डिवाइस"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"आस-पास मौजूद ब्लूटूथ डिवाइसों को खोजें और उनसे कनेक्ट करें"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"कॉल लॉग"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"कॉल लॉग की जानकारी देखना और उसमें बदलाव करना"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"फ़ोन"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ऐप्स को टैबलेट पर ब्लूटूथ का कॉन्फ़िगरेशन देखने, और युग्मित डिवाइस के साथ कनेक्शन बनाने और स्वीकार करने देता है."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"यह ऐप्लिकेशन को आपके Android TV डिवाइस पर ब्लूटूथ कॉन्फ़िगरेशन देखने की अनुमति देता है. साथ ही, यह ब्लूटूथ कनेक्शन से दूसरे डिवाइस को जोड़ने की सुविधा भी देता है."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ऐप्स को फ़ोन पर ब्लूटूथ का कॉन्फ़िगरेशन देखने, और युग्मित डिवाइस के साथ कनेक्शन बनाने और स्वीकार करने देता है."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"आस-पास मौजूद ब्लूटूथ डिवाइस खोजें और जोड़ें"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"अनुमति देने पर, ऐप्लिकेशन, आस-पास मौजूद ब्लूटूथ डिवाइसों को खोज पाएगा और उनसे जुड़ पाएगा"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"जोड़े गए ब्लूटूथ डिवाइसों से कनेक्ट करें"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"अनुमति देने पर, ऐप्लिकेशन, जोड़े गए ब्लूटूथ डिवाइसों से कनेक्ट कर पाएगा"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"NFC का इस्तेमाल करने वाली पैसे चुकाने की पसंदीदा सेवा की जानकारी"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"अगर ऐप्लिकेशन को अनुमति दी जाती है, तो वह पैसे चुकाने की आपकी उस पसंदीदा सेवा के बारे में जानकारी पा सकता है जो NFC का इस्तेमाल करती है. इसमें रजिस्टर किए गए डिवाइस और उनके आउटपुट के रूट जैसी जानकारी शामिल होती है."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"नियर फ़ील्ड कम्यूनिकेशन नियंत्रित करें"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"गड़बड़ी की पुष्टि की जा रही है"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"स्क्रीन लॉक का क्रेडेंशियल इस्तेमाल करें"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"जारी रखने के लिए, अपने डिवाइस का क्रेडेंशियल डालें"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"अधूरा फ़िंगरप्रिंट प्रोसेस हो सका. कृपया फिर से कोशिश करें."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"फ़िंगरप्रिंट प्रोसेस नहीं हो सका. कृपया दोबारा कोशिश करें."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"फ़िंगरप्रिंट सेंसर गंदा है. कृपया साफ़ करें और फिर कोशिश करें."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"उंगली बहुत तेज़ी से चलाई गई. कृपया फिर से कोशिश करें."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"उंगली बहुत धीरे चलाई गई. कृपया फिर से कोशिश करें."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"फ़िंगरप्रिंट की पुष्टि हो गई"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"चेहरे की पहचान की गई"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"चेहरे की पहचान की गई, कृपया पुष्टि बटन दबाएं"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"फ़िंगरप्रिंट हार्डवेयर उपलब्ध नहीं है."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"फ़िंगरप्रिंट को स्टोर नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट हटाएं."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"फ़िंगरप्रिंट का समय खत्म हो गया. फिर से कोशिश करें."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"फ़िंगरप्रिंट ऑपरेशन रोक दिया गया."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"उपयोगकर्ता ने फिंगरप्रिंट की पुष्टि की कार्रवाई रद्द कर दी है."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"मालिक का चेहरा पहचानकर अनलॉक"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"अपना चेहरा फिर से दर्ज करें"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"कृपया अपना चेहरा फिर से दर्ज करें ताकि आपको बेहतर तरीके से पहचाना जा सके"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"चेहरे से जुड़ा सटीक डेटा कैप्चर नहीं किया जा सका. फिर से कोशिश करें."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"बहुत रोशनी है. हल्की रोशनी आज़माएं."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"बहुत अंधेरा है. बेहतर रोशनी में आज़माएं."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"कॉपी किया गया"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> से कॉपी किए गए डेटा को <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> में चिपकाया गया है"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"क्लिपबोर्ड के डेटा को <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> में चिपकाया गया है"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"और"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"मेन्यू+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"वर्क प्रोफ़ाइल"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"निजी व्यू"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"वर्क व्यू"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"इस सामग्री को ऑफ़िस के काम से जुड़े ऐप्लिकेशन का इस्तेमाल करके शेयर नहीं किया जा सकता"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"आपके आईटी एडमिन ने आपको आपकी वर्क प्रोफ़ाइल में शामिल ऐप्लिकेशन का इस्तेमाल करके, इस सामग्री को शेयर करने की अनुमति नहीं दी है"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"इस सामग्री को ऑफ़िस के काम से जुड़े ऐप्लिकेशन इस्तेमाल करके खोला नहीं जा सकता"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"आपके आईटी एडमिन ने आपको आपकी वर्क प्रोफ़ाइल में शामिल ऐप्लिकेशन का इस्तेमाल करके, इस सामग्री को खोलने की अनुमति नहीं दी है"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"इस सामग्री को निजी ऐप्लिकेशन का इस्तेमाल करके शेयर नहीं किया जा सकता"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"आपके आईटी एडमिन ने आपको आपकी निजी प्रोफ़ाइल में शामिल ऐप्लिकेशन का इस्तेमाल करके, इस सामग्री को शेयर करने की अनुमति नहीं दी है"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"इस सामग्री को निजी ऐप्लिकेशन का इस्तेमाल करके खोला नहीं जा सकता"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"आपके आईटी एडमिन ने आपको आपकी निजी प्रोफ़ाइल में शामिल ऐप्लिकेशन का इस्तेमाल करके, इस सामग्री को खोलने की अनुमति नहीं दी है"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"वर्क प्रोफ़ाइल रोक दी गई है"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"चालू करें"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"इस सामग्री का इस्तेमाल, ऑफ़िस के काम से जुड़े किसी भी ऐप्लिकेशन पर नहीं किया जा सकता"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ऑफ़िस के काम से जुड़े किसी भी ऐप्लिकेशन का इस्तेमाल करके, इस सामग्री को खोला नहीं जा सकता"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"इस सामग्री का इस्तेमाल, किसी भी निजी ऐप्लिकेशन पर नहीं किया जा सकता"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"किसी भी निजी ऐप्लिकेशन का इस्तेमाल करके, इस सामग्री को खोला नहीं जा सकता"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"सिम नेटवर्क को अनलॉक करने का पिन"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"सिम नेटवर्क के सबसेट को अनलॉक करने का पिन"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"कारोबार के लिए इस्तेमाल होने वाले सिम को अनलॉक करने का पिन"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"अपनी स्क्रीन के कुछ हिस्से को ज़ूम करें"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"अब आप अपनी फ़ुल स्क्रीन या स्क्रीन के किसी खास हिस्से को ज़ूम करके देख सकते हैं. इसके अलावा, आप इन दोनों विकल्पों के बीच स्विच भी कर सकते हैं."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिंग में जाकर, इस सुविधा को चालू करें"</string>
<string name="dismiss_action" msgid="1728820550388704784">"खारिज करें"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"जारी रखने के लिए, <b><xliff:g id="APP">%s</xliff:g></b> को आपके डिवाइस का माइक्रोफ़ोन ऐक्सेस करने की ज़रूरत है."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 25db5e6..b7db308 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -71,7 +71,7 @@
<string name="ThreeWCMmi" msgid="2436550866139999411">"Trostrani poziv"</string>
<string name="RuacMmi" msgid="1876047385848991110">"Odbijanje neželjenih i neugodnih poziva"</string>
<string name="CndMmi" msgid="185136449405618437">"Isporuka pozivnog broja"</string>
- <string name="DndMmi" msgid="8797375819689129800">"Ne ometaj"</string>
+ <string name="DndMmi" msgid="8797375819689129800">"Ne uznemiravaj"</string>
<string name="CLIRDefaultOnNextCallOn" msgid="4511621022859867988">"Zadana postavka ID-a pozivatelja ima ograničenje. Sljedeći poziv: Ograničen"</string>
<string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"Zadana postavka ID-a pozivatelja ima ograničenje. Sljedeći poziv: Nije ograničen"</string>
<string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"Zadana postavka ID-a pozivatelja nema ograničenje. Sljedeći poziv: Ograničen"</string>
@@ -297,7 +297,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Izvodi se aplikacija"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije troše bateriju"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Povećavanje"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Pravila o sigurnosti za pristupačnost"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje koriste bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite da biste vidjeli pojedinosti o potrošnji baterije i podatkovnom prometu"</string>
@@ -322,6 +323,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"pristupiti vašoj tjelesnoj aktivnosti"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Fotoaparat"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"snimati fotografije i videozapise"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Bluetooth uređaji u blizini"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"otkriti Bluetooth uređaje u blizini i povezati se s njima"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Zapisnici poziva"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"čitati i pisati zapisnik poziva telefona"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -535,6 +538,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na tabletnom računalu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na Android TV uređaju te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na telefonu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"otkriti i upariti Bluetooth uređaje u blizini"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Aplikaciji omogućuje otkrivanje i uparivanje Bluetooth uređaja u blizini"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"povezati se s uparenim Bluetooth uređajima"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Aplikaciji omogućuje povezivanje s uparenim Bluetooth uređajima"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informacije o preferiranoj usluzi plaćanja NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Omogućuje aplikaciji primanje informacija o preferiranoj usluzi plaćanja NFC kao što su registrirana pomagala i odredište."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"upravljanje beskontaktnom komunikacijom (NFC)"</string>
@@ -570,18 +577,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Pogreška prilikom autentifikacije"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Upotreba zaključavanja zaslona"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Unesite vjerodajnicu uređaja da biste nastavili"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Otkriven je djelomični otisak prsta. Pokušajte ponovo."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Obrada otiska prsta nije uspjela. Pokušajte ponovo."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Senzor otiska prsta nije čist. Očistite ga i pokušajte ponovo."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Prebrzo ste pomaknuli prst. Pokušajte ponovo."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Presporo pomicanje prsta. Pokušajte ponovo."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Autentificirano otiskom prsta"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Lice je autentificirano"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je autentificirano, pritisnite Potvrdi"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardver za otisak prsta nije dostupan."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Otisak prsta nije pohranjen. Uklonite postojeći otisak prsta."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Isteklo je vrijeme čekanja za otisak prsta. Pokušajte ponovo."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Radnja otiska prsta otkazana je."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Radnju s otiskom prsta otkazao je korisnik."</string>
@@ -606,6 +623,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Otključavanje licem"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Ponovo registrirajte svoje lice"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Za poboljšanje prepoznavanja ponovo registrirajte svoje lice"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Podaci o licu nisu točni. Pokušajte ponovo."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Presvijetlo je. Pokušajte sa slabijim svjetlom."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Pretamno je. Pokušajte s jačim osvjetljenjem."</string>
@@ -701,8 +726,8 @@
<string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Omogućuje nositelju povezivanje sa sučeljem najviše razine usluge mobilnog operatera za slanje poruka. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
<string name="permlab_bindCarrierServices" msgid="2395596978626237474">"povezivanje s uslugama mobilnog operatera"</string>
<string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Nositelju omogućuje povezivanje s uslugama mobilnog operatera. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
- <string name="permlab_access_notification_policy" msgid="5524112842876975537">"pristupi opciji Ne ometaj"</string>
- <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Omogućuje aplikaciji čitanje i pisanje konfiguracije opcije Ne ometaj."</string>
+ <string name="permlab_access_notification_policy" msgid="5524112842876975537">"pristupi opciji Ne uznemiravaj"</string>
+ <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Omogućuje aplikaciji čitanje i pisanje konfiguracije opcije Ne uznemiravaj."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"pokrenuti upotrebu dopuštenja za pregled"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Dopušta nositelju pokretanje upotrebe dopuštenja za aplikaciju. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pristup podacima senzora pri višoj brzini uzorkovanja"</string>
@@ -1009,6 +1034,12 @@
<string name="copied" msgid="4675902854553014676">"Kopirano"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"U aplikaciji <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> zalijepljen je sadržaj aplikacije <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"U aplikaciji <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> zalijepljen je sadržaj međuspremnika"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Više"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Izbornik+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1711,7 +1742,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Upotrijebi prečac"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Korekcija boje"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno tamno"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamnjenje"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za glasnoću. Uključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za glasnoću. Isključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite tipke za glasnoću na tri sekunde da biste koristili uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1904,10 +1935,10 @@
<string name="zen_mode_until" msgid="2250286190237669079">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="7046911727540499275">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (sljedeći alarm)"</string>
<string name="zen_mode_forever" msgid="740585666364912448">"Dok ne isključite"</string>
- <string name="zen_mode_forever_dnd" msgid="3423201955704180067">"Dok ne isključite \"Ne ometaj\""</string>
+ <string name="zen_mode_forever_dnd" msgid="3423201955704180067">"Dok ne isključite \"Ne uznemiravaj\""</string>
<string name="zen_mode_rule_name_combination" msgid="7174598364351313725">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
<string name="toolbar_collapse_description" msgid="8009920446193610996">"Sažmi"</string>
- <string name="zen_mode_feature_name" msgid="3785547207263754500">"Ne ometaj"</string>
+ <string name="zen_mode_feature_name" msgid="3785547207263754500">"Ne uznemiravaj"</string>
<string name="zen_mode_downtime_feature_name" msgid="5886005761431427128">"Prekid rada"</string>
<string name="zen_mode_default_weeknights_name" msgid="7902108149994062847">"Noć radnog dana"</string>
<string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Vikend"</string>
@@ -2144,20 +2175,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Posao"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Osobni prikaz"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Poslovni prikaz"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Nije moguće dijeljenje s poslovnim aplikacijama"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Vaš IT administrator ne dopušta vam dijeljenje tog sadržaja s aplikacijama na vašem poslovnom profilu"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Nije moguće otvaranje pomoću poslovnih aplikacija"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Vaš IT administrator ne dopušta vam otvaranje tog sadržaja pomoću aplikacija na vašem poslovnom profilu"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"To se ne može dijeliti pomoću osobnih aplikacija"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Vaš IT administrator ne dopušta vam dijeljenje tog sadržaja pomoću aplikacija s vašeg osobnog profila"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Nije moguće otvaranje pomoću osobnih aplikacija"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Vaš IT administrator ne dopušta vam otvaranje tog sadržaja pomoću aplikacija na vašem osobnom profilu"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Poslovni je profil pauziran"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Uključi"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Nijedna poslovna aplikacija ne može podržati taj sadržaj"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Nijedna poslovna aplikacija ne može otvoriti taj sadržaj"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Nijedna osobna aplikacija ne može podržati taj sadržaj"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Nijedna osobna aplikacija ne može otvoriti taj sadržaj"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN za otključavanje SIM mreže."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN za otključavanje podskupa SIM mreže"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN za otključavanje poslovnog SIM-a"</string>
@@ -2270,8 +2312,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Povećavanje dijela zaslona"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Sad možete povećati cijeli zaslon ili određeno područje ili izmjenjivati obje opcije."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Postavkama"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Da bi nastavila s radom, aplikacija <b><xliff:g id="APP">%s</xliff:g></b> treba pristupiti mikrofonu vašeg uređaja."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index c25e691..ceefe4f 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Jelenleg futó alkalmazás"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkumulátort használó alkalmazások"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Nagyítás"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Kisegítő lehetőségek biztonsági házirendje"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás használja az akkumulátort"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> alkalmazás használja az akkumulátort"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Koppintson az akkumulátor- és adathasználat részleteinek megtekintéséhez"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"hozzáférés a testmozgási adatokhoz"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"fotók és videók készítése"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Közeli Bluetooth-eszközök"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"közeli Bluetooth-eszközök felfedezése és csatlakozás hozzájuk"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Hívásnaplók"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"hívásnapló olvasása és írása"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Lehetővé teszi az alkalmazás számára a táblagépen lévő Bluetooth beállításainak megtekintését, valamint kapcsolatok kezdeményezését és fogadását a párosított eszközökkel."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Lehetővé teszi az alkalmazás számára az Android TV eszköz Bluetooth-konfigurációjának megtekintését, valamint párosított eszközökkel való kapcsolatok kezdeményezését és fogadását."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Lehetővé teszi az alkalmazás számára a telefonon lévő Bluetooth beállításainak megtekintését, valamint kapcsolatok kezdeményezését és fogadását a párosított eszközökkel."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"közeli Bluetooth-eszközök felfedezése és párosítás"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Lehetővé teszi az alkalmazás számára a közeli Bluetooth-eszközök felfedezését és a velük való párosítást."</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"csatlakozás párosított Bluetooth-eszközökhöz"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Lehetővé teszi az alkalmazás számára a párosított Bluetooth-eszközökhöz való csatlakozást."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferált NFC fizetési szolgáltatási információk"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Lehetővé teszi az alkalmazás számára preferált NFC fizetési szolgáltatási információk (pl. regisztrált alkalmazásazonosítók és útvonali cél) lekérését."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFC technológia vezérlése"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Hiba történt a hitelesítés közben"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Képernyőzár használata"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"A folytatáshoz adja meg az eszköz hitelesítési adatait"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"A rendszer az ujjlenyomatnak csak egy részletét érzékelte. Próbálkozzon újra."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Nem sikerült feldolgozni az ujjlenyomatot. Próbálkozzon újra."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Az ujjlenyomat-olvasó koszos. Tisztítsa meg, majd próbálkozzon újra."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Túl hamar vette el az ujját. Próbálkozzon újra."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Túl lassan húzta az ujját. Próbálkozzon újra."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Ujjlenyomat hitelesítve"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Arc hitelesítve"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Arc hitelesítve; nyomja meg a Megerősítés lehetőséget"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Az ujjlenyomathoz szükséges hardver nem érhető el."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Az ujjlenyomat nem tárolható. Távolítson el egy meglévő ujjlenyomatot."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Az ujjlenyomat-beolvasási műveletkor időtúllépés történt. Próbálkozzon újra."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Ujjlenyomattal kapcsolatos művelet megszakítva"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Az ujjlenyomattal kapcsolatos műveletet a felhasználó megszakította."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Arcalapú feloldás"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Rögzítsen újra képet az arcáról"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"A felismerés javítása érdekében rögzítsen újra az arcáról készített képet"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Sikertelen az arc pontos rögzítése. Próbálja újra."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Túl világos. Próbálja kevésbé erős világítással."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Túl sötét. Próbálja jobb megvilágítás mellett."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Átmásolva"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"A(z) <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> tartalmat másolt vágólapra a(z) <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> appból"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"A(z) <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> beillesztette a vágólapon lévő tartalmat"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Egyebek"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menü+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1825,7 +1856,7 @@
<string name="managed_profile_label_badge" msgid="6762559569999499495">"Munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-kód kérése a rögzítés feloldásához"</string>
+ <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-kód kérése a kitűzés feloldásához"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Feloldási minta kérése a rögzítés feloldásához"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Jelszó kérése a rögzítés feloldásához"</string>
<string name="package_installed_device_owner" msgid="7035926868974878525">"A rendszergazda által telepítve"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Munka"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Személyes nézet"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Munkanézet"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Ez a tartalom nem osztható meg munkahelyi alkalmazásokkal"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Rendszergazdája nem engedélyezi, hogy ezt a tartalmat a munkaprofiljában lévő alkalmazásokkal ossza meg"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Ez a tartalom nem nyitható meg munkahelyi alkalmazásokkal"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Rendszergazdája nem engedélyezi, hogy ezt a tartalmat a munkaprofiljában lévő alkalmazásokkal nyissa meg"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Ez a tartalom nem osztható meg személyes alkalmazásokkal"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Rendszergazdája nem engedélyezi, hogy ezt a tartalmat a személyes profiljában lévő alkalmazásokkal ossza meg"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Ez a tartalom nem nyitható meg személyes alkalmazásokkal"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Rendszergazdája nem engedélyezi, hogy ezt a tartalmat a személyes profiljában lévő alkalmazásokkal nyissa meg"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"A munkaprofil használata szünetel"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Bekapcsolás"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"A munkahelyi alkalmazások nem támogatják ezt a tartalmat"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Munkahelyi alkalmazásokkal nem nyitható meg ez a tartalom"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"A személyes alkalmazások nem támogatják ezt a tartalmat"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Személyes alkalmazásokkal nem nyitható meg ez a tartalom"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Hálózati SIM feloldó PIN-kódja"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Hálózati SIM alkészletének feloldó PIN-kódja"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Vállalati SIM feloldó PIN-kódja"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"A képernyő egy részének felnagyítása"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Mostantól felnagyíthatja a teljes képernyőt vagy a kívánt területet, valamint válthat a két lehetőség között."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Bekapcsolás a Beállításokban"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Elvetés"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"A folytatáshoz a(z) <b><xliff:g id="APP">%s</xliff:g></b> alkalmazásnak hozzáférésre van szüksége az eszköze mikrofonjához."</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 594b029..0ac8e92 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Հավելվածն աշխատում է"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Մարտկոցի լիցքը ծախսող հավելվածներ"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Խոշորացում"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Հատուկ գործառույթների անվտանգության քաղաքականություն"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"«<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածը ծախսում է մարտկոցի լիցքը"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> հավելված ծախսում է մարտկոցի լիցքը"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Հպեք՝ մարտկոցի և թրաֆիկի մանրամասները տեսնելու համար"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"հասանելիություն ֆիզիկական ակտիվությանը"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Տեսախցիկ"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"լուսանկարել և տեսագրել"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Մոտակա Bluetooth սարքեր"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"հայտնաբերել մոտակա Bluetooth սարքերը և միանալ դրանց"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Զանգերի մատյան"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"հեռախոսազանգերի մատյանի դիտում և գրանցում"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Հեռախոս"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Թույլ է տալիս հավելվածին տեսնել Bluetooth-ի կարգավորումը պլանշետի վրա և կապվել ու կապեր ընդունել զուգակցված սարքերի հետ:"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Թույլ է տալիս հավելվածին տեսնել Bluetooth-ի կազմաձևումը Android TV սարքի վրա և կապվել ու թույլ տալ կապակցումները զուգակցված սարքերի հետ:"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Թույլ է տալիս հավելվածին տեսնել Bluetooth-ի կարգավորումը հեռախոսի վրա և կապվել ու կապեր ընդունել զուգակցված սարքերի հետ:"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"հայտնաբերել և զուգակցել մոտակա Bluetooth սարքերը"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Թույլ է տալիս հավելվածին հայտնաբերել և զուգակցել մոտակա Bluetooth սարքերը"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"միանալ զուգակցված Bluetooth սարքերի"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Թույլ է տալիս հավելվածին միանալ զուգակցված Bluetooth սարքերի"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Տեղեկություններ NFC վճարային ծառայության մասին"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Թույլ է տալիս հավելվածին ստանալ նախընտրելի NFC վճարային ծառայության մասին տեղեկություններ (օր․՝ գրանցված լրացուցիչ սարքերի և երթուղու նպատակակետի մասին տվյալներ)։"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"վերահսկել Մոտ Տարածությամբ Հաղորդակցումը"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Չհաջողվեց նույնականացնել"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Էկրանի կողպում"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Շարունակելու համար մուտքագրեք սարքի նույնականացման տվյալները"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Մատնահետքն ամբողջությամբ չի սկանավորվել: Փորձեք նորից:"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Չհաջողվեց մշակել մատնահետքը: Նորից փորձեք:"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Մատնահետքերի սենսորն աղտոտված է: Մաքրեք այն և փորձեք նորից:"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Շատ արագ անցկացրիք մատը: Փորձեք նորից:"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Շատ դանդաղ անցկացրիք մատը: Փորձեք նորից:"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Մատնահետքը նույնականացվեց"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Դեմքը ճանաչվեց"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Դեմքը ճանաչվեց: Սեղմեք «Հաստատել»:"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Մատնահետքի սարքն անհասանելի է:"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Հնարավոր չէ պահել մատնահետքը: Հեռացրեք առկա մատնահետքը:"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Մատնահետքի գրանցման ժամանակը սպառվել է: Փորձեք նորից:"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Իսկորոշումը մատնահետքի միջոցով չեղարկվեց:"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Մատնահետքով նույնականացման գործողությունը չեղարկվել է օգտատիրոջ կողմից:"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Դեմքով ապակողպում"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Նորից գրանցեք ձեր դեմքը"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Ճանաչումը լավացնելու համար նորից գրանցեք ձեր դեմքը"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Չհաջողվեց գրանցել դեմքի ճշգրիտ տվյալները։ Կրկնեք։"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Շատ լուսավոր է։ Փորձեք ավելի թեթև լուսավորություն։"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Շատ մութ է։ Փորձեք ավելի պայծառ լուսավորություն։"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Պատճենվեց"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> հավելվածը տվյալներ տեղադրեց <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> հավելվածից"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> հավելվածը տվյալներ տեղադրեց սեղմատախտակից"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Ավելին"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Ցանկ+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Աշխատանքային"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Անձնական"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Աշխատանքային"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Հնարավոր չէ հասանելի դարձնել աշխատանքային հավելվածներին"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"ՏՏ ադմինիստրատորն արգելել է այս բովանդակությունը հասանելի դարձնել ձեր աշխատանքային պրոֆիլի հավելվածներին"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Հնարավոր չէ բացել աշխատանքային հավելվածներով"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"ՏՏ ադմինիստրատորն արգելել է այս բովանդակությունը բացել ձեր աշխատանքային պրոֆիլի հավելվածներով"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Հնարավոր չէ հասանելի դարձնել անձնական հավելվածներին"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"ՏՏ ադմինիստրատորն արգելել է այս բովանդակությունը հասանելի դարձնել ձեր անձնական պրոֆիլի հավելվածներին"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Հնարավոր չէ բացել անձնական հավելվածներով"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"ՏՏ ադմինիստրատորն արգելել է այս բովանդակությունը բացել ձեր անձնական պրոֆիլի հավելվածներով"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Աշխատանքային պրոֆիլի ծառայությունը դադարեցված է"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Միացնել"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Աշխատանքային հավելվածները չեն կարող աջակցել այս բովանդակությունը"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Աշխատանքային հավելվածները չեն կարող բացել այս բովանդակությունը"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Անձնական հավելվածները չեն կարող աջակցել այս բովանդակությունը"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Անձնական հավելվածները չեն կարող բացել այս բովանդակությունը"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM Network քարտի ապակողպման PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM Network Subset քարտի ապակողպման PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM Corporate քարտի ապակողպման PIN"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Խոշորացրեք էկրանի մի հատվածը"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Այժմ կարող եք խոշորացնել ամբողջ էկրանը կամ էկրանի որոշակի հատված, ինչպես նաև փոխել ռեժիմները։"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Միացնել կարգավորումներում"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Փակել"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Շարունակելու համար <b><xliff:g id="APP">%s</xliff:g></b> հավելվածին անհրաժեշտ է սարքի խոսափողի օգտագործման թույլտվություն։"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 00c8b5b..0b8bae6 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikasi berjalan"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikasi yang menggunakan baterai"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pembesaran"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Kebijakan keamanan aksesibilitas"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan baterai"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikasi sedang meggunakan baterai"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketuk untuk melihat detail penggunaan baterai dan data"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"mengakses aktivitas fisik Anda"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"mengambil gambar dan merekam video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Perangkat Bluetooth di Sekitar"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"temukan dan hubungkan ke perangkat Bluetooth di sekitar"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Log panggilan"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"membaca dan menulis log panggilan telepon"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telepon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di tablet, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Mengizinkan aplikasi melihat konfigurasi Bluetooth di perangkat Android TV, serta melakukan dan menerima sambungan dengan perangkat yang tersambung."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di ponsel, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"temukan & sambungkan perangkat Bluetooth di sekitar"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Mengizinkan aplikasi menemukan dan menyambungkan perangkat Bluetooth di sekitar"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"hubungkan ke perangkat Bluetooth yang disambungkan"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Mengizinkan aplikasi terhubung ke perangkat Bluetooth yang disambungkan"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informasi Layanan Pembayaran NFC Pilihan"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Mengizinkan aplikasi untuk mendapatkan informasi layanan pembayaran NFC pilihan seperti bantuan terdaftar dan tujuan rute."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrol NFC"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Error saat mengautentikasi"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gunakan kunci layar"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Masukkan kredensial perangkat untuk melanjutkan"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Sebagian sidik jari terdeteksi. Coba lagi."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Tidak dapat memproses sidik jari. Coba lagi."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Sensor sidik jari kotor. Bersihkan dan coba lagi."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Jari digerakkan terlalu cepat. Coba lagi."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Jari digerakkan terlalu lambat. Coba lagi."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Sidik jari diautentikasi"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Wajah diautentikasi"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Wajah diautentikasi, silakan tekan konfirmasi"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware sidik jari tidak tersedia."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Sidik jari tidak dapat disimpan. Hapus sidik jari yang ada."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Waktu sidik jari habis. Coba lagi."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operasi sidik jari dibatalkan."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operasi sidik jari dibatalkan oleh pengguna."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Daftarkan kembali wajah Anda"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Untuk menyempurnakan pengenalan wajah, daftarkan kembali wajah Anda"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Tidak bisa mengambil data wajah akurat. Coba lagi."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Terlalu terang. Coba cahaya yang lebih lembut."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Terlalu gelap. Coba pencahayaan yang lebih cerah."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Disalin"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ditempelkan dari <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ditempelkan dari papan klip"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Lainnya"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1949,10 +1980,10 @@
<string name="profile_encrypted_message" msgid="1128512616293157802">"Ketuk untuk membuka kunci profil kerja"</string>
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Terhubung ke <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Ketuk untuk melihat file"</string>
- <string name="pin_target" msgid="8036028973110156895">"Pasang pin"</string>
- <string name="pin_specific_target" msgid="7824671240625957415">"Pasang pin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="pin_target" msgid="8036028973110156895">"Sematkan"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Sematkan <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Lepas pin"</string>
- <string name="unpin_specific_target" msgid="3859828252160908146">"Lepas pin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Lepas sematan <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Info aplikasi"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Memulai demo..."</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Kerja"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Tampilan pribadi"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Tampilan kerja"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Tidak dapat membagikan konten ini dengan aplikasi kerja"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Admin IT tidak mengizinkan Anda membagikan konten ini dengan aplikasi di profil kerja Anda"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Tidak dapat membuka konten ini dengan aplikasi kerja"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Admin IT tidak mengizinkan Anda membuka konten ini dengan aplikasi di profil kerja Anda"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Tidak dapat membagikan konten ini dengan aplikasi pribadi"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Admin IT tidak mengizinkan Anda membagikan konten ini dengan aplikasi di profil pribadi Anda"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Tidak dapat membuka konten ini dengan aplikasi pribadi"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Admin IT tidak mengizinkan Anda membuka konten ini dengan aplikasi di profil pribadi Anda"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Profil kerja dijeda"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Aktifkan"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Tidak ada aplikasi kerja yang dapat mendukung konten ini"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Tidak ada aplikasi kerja yang dapat membuka konten ini"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Tidak ada aplikasi pribadi yang dapat mendukung konten ini"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Tidak ada aplikasi pribadi yang dapat membuka konten ini"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN pembuka kunci SIM network"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN pembuka kunci SIM network subset"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN pembuka kunci SIM corporate"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Memperbesar tampilan sebagian layar"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Anda kini dapat memperbesar layar penuh, area tertentu, atau beralih antara kedua opsi tersebut."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktifkan di Setelan"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Tutup"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Untuk melanjutkan, <b><xliff:g id="APP">%s</xliff:g></b> memerlukan akses ke mikrofon perangkat."</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 1c5809f..c37c52c 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Forrit er í gangi"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Forrit sem nota rafhlöðuorku"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Stækkun"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Öryggisregla aðgengis"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> notar rafhlöðuorku"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> forrit nota rafhlöðuorku"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ýttu til að fá upplýsingar um rafhlöðu- og gagnanotkun"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"fá aðgang að hreyfingu þinni"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Myndavél"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"taka myndir og taka upp myndskeið"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Nálæg Bluetooth-tæki"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"finna og tengjast nálægum Bluetooth-tækjum"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Símtalaskrár"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"lesa og skrifa símtalaskrá síma"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Sími"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Leyfir forriti að skoða grunnstillingu Bluetooth í spjaldtölvunni og koma á og samþykkja tengingar við pöruð tæki."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Leyfir forriti að skoða stillingu Bluetooth í Android TV og tengjast og samþykkja tengingar við pöruð tæki."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Leyfir forriti að skoða grunnstillingu Bluetooth í símanum og koma á og samþykkja tengingar við pöruð tæki."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"finna og parast við nálæg Bluetooth-tæki"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Leyfir forritinu að finna nálæg Bluetooth-tæki og parast við þau"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"tengjast pöruðum Bluetooth-tækjum"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Leyfir forritinu að tengjast pöruðum Bluetooth-tækjum"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Upplýsingar um valda NFC-greiðsluþjónustu"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Gerir forritinu kleift að fá valda NFC-greiðsluþjónustu, svo sem skráða aðstoð og áfangastað leiðar."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"stjórna nándarsamskiptum (NFC)"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Villa við auðkenningu"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Nota skjálás"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Færðu inn skilríki tækisins til að halda áfram"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Hluti fingrafars greindist. Reyndu aftur."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Ekki var hægt að vinna úr fingrafarinu. Reyndu aftur."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Fingrafaraskynjarinn er óhreinn. Hreinsaðu hann og reyndu aftur."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Fingurinn hreyfðist of hratt. Reyndu aftur."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Fingurinn hreyfðist of hægt. Reyndu aftur."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingrafar staðfest"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Andlit staðfest"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Andlit staðfest, ýttu til að staðfesta"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingrafarsvélbúnaður ekki til staðar."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Ekki er hægt að vista fingrafarið. Fjarlægðu eitthvert af fingraförunum sem fyrir eru."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Tímamörk runnu út fyrir fingrafar. Reyndu aftur."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Hætt við fingrafarsaðgerð."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Notandi hætti við að nota fingrafar."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Andlitsopnun"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Skráðu andlitið þitt aftur"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Skráðu andlitið þitt til að bæta kennsl"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Nákvæm andlitsgögn fengust ekki. Reyndu aftur."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Of bjart. Prófaðu mýkri lýsingu."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Of dimmt. Prófaðu sterkari lýsingu."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Afritað"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> límt úr <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> límt af klippiborði."</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Meira"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Valmynd+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Vinna"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Persónulegt yfirlit"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Vinnuyfirlit"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Ekki er hægt að deila þessu með vinnuforritum"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Kerfisstjórinn þinn leyfir þér ekki að deila þessu efni með forritum á vinnusniðinu"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Ekki er hægt að opna þetta með vinnuforritum"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Kerfisstjórinn þinn leyfir þér ekki að opna þetta efni með forritum á vinnusniðinu"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Ekki er hægt að deila þessu með forritum til einkanota"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Kerfisstjórinn þinn leyfir þér ekki að deila þessu efni með forritum á eigin sniði"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Ekki er hægt að opna þetta með forritum til einkanota"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Kerfisstjórinn þinn leyfir þér ekki að opna þetta efni með forritum á eigin sniði"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Hlé gert á vinnusniði"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Kveikja"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Engin vinnuforrit styðja þetta efni"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Engin vinnuforrit geta opnað þetta efni"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Engin forrit til einkanota styðja þetta efni"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Engin forrit til einkanota geta opnað þetta efni"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-númer fyrir opnun á SIM-korti netkerfis"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-númer fyrir opnun á SIM-korti netkerfishlutmengis"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-númer fyrir opnun á SIM-korti fyrirtækis"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Stækka hluta af skjánum"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Nú geturðu stækkað allan skjáinn, tiltekið svæði eða skipt á milli þessara valkosta."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Kveikja á í stillingum"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Hunsa"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Til að halda áfram þarf <b><xliff:g id="APP">%s</xliff:g></b> aðgang að hljóðnema tækisins."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 4e342b6..27ee7ce 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App in esecuzione"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"App che consumano la batteria"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ingrandimento"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Criteri di sicurezza dell\'accessibilità"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> sta consumando la batteria"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> app stanno consumando la batteria"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tocca per conoscere i dettagli sull\'utilizzo dei dati e della batteria"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"Consente di accedere all\'attività fisica"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Fotocamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"scattare foto e registrare video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Dispositivi Bluetooth nelle vicinanze"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"Rilevamento e connessione a dispositivi Bluetooth nelle vicinanze"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Registri chiamate"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"leggere e modificare il registro chiamate del telefono"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefono"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Consente all\'applicazione di visualizzare la configurazione del Bluetooth sul tablet e di stabilire e accettare connessioni con dispositivi accoppiati."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Consente all\'app di visualizzare la configurazione del Bluetooth del dispositivo Android TV, nonché di stabilire e accettare connessioni con dispositivi accoppiati."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Consente all\'applicazione di visualizzare la configurazione del Bluetooth sul telefono e di stabilire e accettare connessioni con dispositivi accoppiati."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"Rilevamento/accopp. dispositivi Bluetooth vicini"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Consente all\'app di rilevare e accoppiare dispositivi Bluetooth nelle vicinanze"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"Connessione a dispositivi Bluetooth accoppiati"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Consente all\'app di connettersi ai dispositivi Bluetooth accoppiati"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informazioni del servizio di pagamento NFC preferito"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Consente all\'app di recuperare informazioni del servizio di pagamento NFC preferito, quali destinazione della route e identificatori applicazione registrati."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controllo Near Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Errore durante l\'autenticazione"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usa il blocco schermo"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Inserisci la credenziale del dispositivo per continuare"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Rilevata impronta parziale. Riprova."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Impossibile elaborare l\'impronta. Riprova."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Il sensore di impronte è sporco. Puliscilo e riprova."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Movimento del dito troppo rapido. Riprova."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Movimento del dito troppo lento. Riprova."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Impronta autenticata"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Volto autenticato"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Volto autenticato, premi Conferma"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware per l\'impronta non disponibile."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Impossibile memorizzare l\'impronta. Rimuovi un\'impronta esistente."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Timeout impronta. Riprova."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operazione associata all\'impronta annullata."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operazione di autenticazione dell\'impronta annullata dall\'utente."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Sblocco con il volto"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Registra di nuovo il volto"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Per migliorare il riconoscimento, registra di nuovo il tuo volto"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Impossibile acquisire dati viso accurati. Riprova."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Troppa luce. Prova con una luce più soft."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Troppo buio. Prova con più luce."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Copia eseguita"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Dati dell\'app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> incollati dall\'app <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Dati dell\'app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> incollati dagli appunti"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Altro"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"META +"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Lavoro"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Visualizzazione personale"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Visualizzazione di lavoro"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Impossibile condividere questi contenuti con le app di lavoro"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"L\'amministratore IT non ti consente di condividere questi contenuti con le app nel tuo profilo di lavoro"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Impossibile aprire questi contenuti con le app di lavoro"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"L\'amministratore IT non ti consente di aprire questi contenuti con le app nel tuo profilo di lavoro"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Impossibile condividere questi contenuti con app personali"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"L\'amministratore IT non ti consente di condividere questi contenuti con app nel tuo profilo personale"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Impossibile aprire questi contenuti con app personali"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"L\'amministratore IT non ti consente di aprire questi contenuti con app nel tuo profilo personale"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Profilo di lavoro in pausa"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Attiva"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Nessuna app di lavoro supporta questi contenuti"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Nessuna app di lavoro può aprire questi contenuti"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Nessuna app personale supporta questi contenuti"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Nessuna app personale può aprire questi contenuti"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN di sblocco rete SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN di sblocco sottoinsieme rete SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN sblocco aziendale SIM"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Ingrandisci parte dello schermo"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Ora puoi ingrandire l\'intero schermo, un\'area specifica o passare da un\'opzione all\'altra."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Attiva nelle Impostazioni"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Ignora"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Per continuare, l\'app <b><xliff:g id="APP">%s</xliff:g></b> deve accedere al microfono del dispositivo."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index f2f6138..7e4b8ad 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -47,9 +47,9 @@
<string name="mismatchPin" msgid="2929611853228707473">"קודי הגישה שהקלדת לא תואמים."</string>
<string name="invalidPin" msgid="7542498253319440408">"יש להקליד קוד אימות שאורכו 4 עד 8 ספרות."</string>
<string name="invalidPuk" msgid="8831151490931907083">"הקלד PUK באורך 8 מספרים או יותר."</string>
- <string name="needPuk" msgid="7321876090152422918">"כרטיס ה-SIM נעול באמצעות PUK. הקלד את קוד PUK כדי לבטל את נעילתו."</string>
- <string name="needPuk2" msgid="7032612093451537186">"הקלד PUK2 כדי לבטל את חסימת כרטיס ה-SIM."</string>
- <string name="enablePin" msgid="2543771964137091212">"לא הצלחת. הפעל נעילת SIM/RUIM."</string>
+ <string name="needPuk" msgid="7321876090152422918">"כרטיס ה-SIM נעול באמצעות PUK. יש להקליד את קוד ה-PUK כדי לבטל את הנעילה."</string>
+ <string name="needPuk2" msgid="7032612093451537186">"יש להקליד PUK2 כדי לבטל את חסימת כרטיס ה-SIM."</string>
+ <string name="enablePin" msgid="2543771964137091212">"לא הצלחת. יש להפעיל נעילת SIM/RUIM."</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
<item quantity="two">נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות לפני נעילת כרטיס ה-SIM.</item>
<item quantity="many">נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות לפני נעילת כרטיס ה-SIM.</item>
@@ -70,12 +70,12 @@
<string name="CnipMmi" msgid="4897531155968151160">"מספר מתקשר נמצא"</string>
<string name="CnirMmi" msgid="885292039284503036">"מספר מתקשר חסוי"</string>
<string name="ThreeWCMmi" msgid="2436550866139999411">"שיחה עם שלושה משתתפים"</string>
- <string name="RuacMmi" msgid="1876047385848991110">"דחייה של שיחות מטרידות לא רצויות"</string>
- <string name="CndMmi" msgid="185136449405618437">"מסירת מספר מתקשר"</string>
+ <string name="RuacMmi" msgid="1876047385848991110">"דחיית שיחות מטרידות ולא רצויות"</string>
+ <string name="CndMmi" msgid="185136449405618437">"שליחת מספר מתקשר"</string>
<string name="DndMmi" msgid="8797375819689129800">"נא לא להפריע"</string>
- <string name="CLIRDefaultOnNextCallOn" msgid="4511621022859867988">"זיהוי מתקשר עובר כברירת מחדל למצב מוגבל. השיחה הבאה: מוגבלת"</string>
+ <string name="CLIRDefaultOnNextCallOn" msgid="4511621022859867988">"השירות \'שיחה מזוהה\' עובר כברירת מחדל למצב מוגבל. השיחה הבאה: מוגבלת"</string>
<string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"זיהוי מתקשר עובר כברירת מחדל למצב מוגבל. השיחה הבאה: לא מוגבלת"</string>
- <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"זיהוי מתקשר עובר כברירת מחדל למצב לא מוגבל. השיחה הבאה: מוגבלת"</string>
+ <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"שירות \'שיחה מזוהה\' עובר כברירת מחדל למצב לא מוגבל. השיחה הבאה: מוגבלת"</string>
<string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"זיהוי מתקשר עובר כברירת מחדל למצב לא מוגבל. השיחה הבאה: לא מוגבלת"</string>
<string name="serviceNotProvisioned" msgid="8289333510236766193">"השירות לא הוקצה."</string>
<string name="CLIRPermanent" msgid="166443681876381118">"אינך יכול לשנות את הגדרת זיהוי המתקשר."</string>
@@ -84,7 +84,7 @@
<string name="RestrictedOnNormalTitle" msgid="7009474589746551737">"אין אפשרות לבצע שיחות רגילות"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="3982069078579103087">"אין שירות קולי או שיחות חירום"</string>
<string name="RestrictedStateContent" msgid="7693575344608618926">"הושבת באופן זמני על ידי הספק"</string>
- <string name="RestrictedStateContentMsimTemplate" msgid="5228235722511044687">"הושבת באופן זמני על ידי הספק עבור SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
+ <string name="RestrictedStateContentMsimTemplate" msgid="5228235722511044687">"השירות הושבת באופן זמני על ידי הספק עבור SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"לא ניתן להתחבר לרשת הסלולרית"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"אפשר לנסות לשנות את הרשת המועדפת. יש להקיש כדי לשנות אותה."</string>
<string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"שיחות חירום לא זמינות"</string>
@@ -123,10 +123,10 @@
<string name="roamingText10" msgid="7434767033595769499">"נדידה - פונקציונליות חלקית של שירות"</string>
<string name="roamingText11" msgid="5245687407203281407">"מודעת באנר נודדת מופעלת"</string>
<string name="roamingText12" msgid="673537506362152640">"מודעת באנר נודדת כבויה"</string>
- <string name="roamingTextSearching" msgid="5323235489657753486">"מחפש שירות"</string>
+ <string name="roamingTextSearching" msgid="5323235489657753486">"המערכת מחפשת שירות"</string>
<string name="wfcRegErrorTitle" msgid="3193072971584858020">"לא ניתן היה להגדיר את התכונה \'שיחות Wi-Fi\'"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="468830943567116703">"כדי להתקשר ולשלוח הודעות ברשת Wi-Fi, תחילה יש לבקש מהספק להגדיר את השירות. לאחר מכן, יש להפעיל שוב שיחות Wi-Fi ב\'הגדרות\'. (קוד שגיאה: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="468830943567116703">"כדי להתקשר ולשלוח הודעות ברשת Wi-Fi, תחילה יש לבקש מהספק להגדיר את השירות. לאחר מכן, צריך להפעיל שוב שיחות Wi-Fi ב\'הגדרות\'. (קוד שגיאה: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="4795145070505729156">"אירעה בעיה ברישום שיחות Wi-Fi אצל הספק שלך: <xliff:g id="CODE">%1$s</xliff:g>"</item>
@@ -153,24 +153,24 @@
<string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"אמצעי גיבוי להתקשרות באמצעות <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ללא העברה"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
- <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> כעבור <xliff:g id="TIME_DELAY">{2}</xliff:g> שניות"</string>
+ <string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> אחרי <xliff:g id="TIME_DELAY">{2}</xliff:g> שניות"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ללא העברה"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ללא העברה"</string>
<string name="fcComplete" msgid="1080909484660507044">"קוד תכונה הושלם."</string>
<string name="fcError" msgid="5325116502080221346">"בעיה בחיבור או קוד תכונה לא תקין."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"אישור"</string>
<string name="httpError" msgid="3406003584150566720">"אירעה שגיאת רשת."</string>
- <string name="httpErrorLookup" msgid="3099834738227549349">"לא ניתן למצוא את כתובת האתר."</string>
+ <string name="httpErrorLookup" msgid="3099834738227549349">"לא ניתן למצוא את כתובת ה-URL."</string>
<string name="httpErrorUnsupportedAuthScheme" msgid="3976195595501606787">"סכימת אימות האתר אינה נתמכת."</string>
<string name="httpErrorAuth" msgid="469553140922938968">"האימות נכשל."</string>
<string name="httpErrorProxyAuth" msgid="7229662162030113406">"האימות דרך שרת ה-Proxy נכשל."</string>
<string name="httpErrorConnect" msgid="3295081579893205617">"לא ניתן להתחבר לשרת."</string>
- <string name="httpErrorIO" msgid="3860318696166314490">"לא ניתן לתקשר עם השרת. נסה שוב מאוחר יותר."</string>
+ <string name="httpErrorIO" msgid="3860318696166314490">"לא ניתן לתקשר עם השרת. אפשר לנסות שוב מאוחר יותר."</string>
<string name="httpErrorTimeout" msgid="7446272815190334204">"חלף הזמן הקצוב של החיבור לשרת."</string>
<string name="httpErrorRedirectLoop" msgid="8455757777509512098">"הדף מכיל יותר מדי כתובות אתר להפניה מחדש של השרת."</string>
<string name="httpErrorUnsupportedScheme" msgid="2664108769858966374">"הפרוטוקול אינו נתמך."</string>
<string name="httpErrorFailedSslHandshake" msgid="546319061228876290">"לא ניתן ליצור חיבור מאובטח."</string>
- <string name="httpErrorBadUrl" msgid="754447723314832538">"אין אפשרות לפתוח את הדף מכיוון שכתובת האתר אינה חוקית."</string>
+ <string name="httpErrorBadUrl" msgid="754447723314832538">"אין אפשרות לפתוח את הדף מכיוון שכתובת ה-URL אינה חוקית."</string>
<string name="httpErrorFile" msgid="3400658466057744084">"לא ניתן לגשת לקובץ."</string>
<string name="httpErrorFileNotFound" msgid="5191433324871147386">"הקובץ המבוקש לא נמצא."</string>
<string name="httpErrorTooManyRequests" msgid="2149677715552037198">"בקשות רבות מדי מעובדות. נסה שוב מאוחר יותר."</string>
@@ -178,10 +178,10 @@
<string name="contentServiceSync" msgid="2341041749565687871">"סנכרון"</string>
<string name="contentServiceSyncNotificationTitle" msgid="5766411446676388623">"לא ניתן לסנכרן"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="4562226280528716090">"נעשה ניסיון למחוק יותר מדי <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
- <string name="low_memory" product="tablet" msgid="5557552311566179924">"שטח האחסון של הטאבלט מלא. מחק קבצים כדי לפנות מקום."</string>
+ <string name="low_memory" product="tablet" msgid="5557552311566179924">"נפח האחסון של הטאבלט מלא. צריך למחוק קבצים כדי לפנות מקום."</string>
<string name="low_memory" product="watch" msgid="3479447988234030194">"שטח האחסון של השעון מלא. מחק כמה קבצים כדי לפנות שטח."</string>
<string name="low_memory" product="tv" msgid="6663680413790323318">"האחסון של מכשיר ה-Android TV מלא. יש למחוק חלק מהקבצים כדי לפנות מקום."</string>
- <string name="low_memory" product="default" msgid="2539532364144025569">"שטח האחסון של הטלפון מלא. מחק חלק מהקבצים כדי לפנות שטח."</string>
+ <string name="low_memory" product="default" msgid="2539532364144025569">"מקום האחסון של הטלפון מלא. אפשר למחוק חלק מהקבצים כדי לפנות מקום."</string>
<plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
<item quantity="two">רשויות אישורים הותקנו</item>
<item quantity="many">רשויות אישורים הותקנו</item>
@@ -195,9 +195,9 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"אפליקציית הניהול של פרופיל העבודה חסרה או פגומה. כתוצאה מכך, פרופיל העבודה שלך נמחק, כולל כל הנתונים הקשורים אליו. לקבלת עזרה, פנה למנהל המערכת."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"פרופיל העבודה שלך אינו זמין עוד במכשיר הזה"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"בוצעו ניסיונות רבים מדי להזנת סיסמה"</string>
- <string name="device_ownership_relinquished" msgid="4080886992183195724">"מנהל המערכת ביטל את המכשיר לצורכי שימוש אישי"</string>
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"מנהל המערכת ביטל את האפשרות לשימוש במכשיר לצרכים אישיים"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"המכשיר מנוהל"</string>
- <string name="network_logging_notification_text" msgid="1327373071132562512">"הארגון שלך מנהל מכשיר זה ועשוי לנטר את התנועה ברשת. הקש לקבלת פרטים."</string>
+ <string name="network_logging_notification_text" msgid="1327373071132562512">"הארגון שלך מנהל את המכשיר הזה והוא עשוי לנטר את התנועה ברשת. יש להקיש לקבלת פרטים."</string>
<string name="location_changed_notification_title" msgid="3620158742816699316">"לאפליקציות יש הרשאת גישה למיקום שלך"</string>
<string name="location_changed_notification_text" msgid="7158423339982706912">"יש לפנות למנהל ה-IT כדי לקבל מידע נוסף"</string>
<string name="geofencing_service" msgid="3826902410740315456">"שירות להגדרת גבולות וירטואליים"</string>
@@ -205,7 +205,7 @@
<string name="location_service" msgid="2439187616018455546">"שירות מיקום"</string>
<string name="gnss_service" msgid="8907781262179951385">"שירות GNSS"</string>
<string name="sensor_notification_service" msgid="7474531979178682676">"שירות להתראות מחיישנים"</string>
- <string name="twilight_service" msgid="8964898045693187224">"שירות דמדומים"</string>
+ <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string>
<string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"מזהה אזור זמן (ללא צורך בקישוריות)"</string>
<string name="gnss_time_update_service" msgid="9039489496037616095">"שירות עדכון הזמן של GNSS"</string>
<string name="music_recognition_manager_service" msgid="7481956037950276359">"השירות של מנהל זיהוי המוזיקה"</string>
@@ -214,7 +214,7 @@
<string name="printing_disabled_by" msgid="3517499806528864633">"ההדפסה הושבתה על ידי <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="personal_apps_suspension_title" msgid="7561416677884286600">"הפעלה של פרופיל העבודה שלך"</string>
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"האפליקציות שלך לשימוש אישי יהיו חסומות עד להפעלת פרופיל העבודה"</string>
- <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"אפליקציות לשימוש אישי ייחסמו ב-<xliff:g id="DATE">%1$s</xliff:g> בשעה <xliff:g id="TIME">%2$s</xliff:g>. מנהל ה-IT לא מתיר השבתה של יותר מ-<xliff:g id="NUMBER">%3$d</xliff:g> ימים של פרופיל העבודה."</string>
+ <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"אפליקציות לשימוש אישי ייחסמו ב-<xliff:g id="DATE">%1$s</xliff:g> בשעה <xliff:g id="TIME">%2$s</xliff:g>. מנהל ה-IT לא מתיר השבתה של פרופיל העבודה ליותר מ-<xliff:g id="NUMBER">%3$d</xliff:g> ימים."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"הפעלה"</string>
<string name="me" msgid="6207584824693813140">"אני"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"אפשרויות טאבלט"</string>
@@ -222,7 +222,7 @@
<string name="power_dialog" product="default" msgid="1107775420270203046">"אפשרויות טלפון"</string>
<string name="silent_mode" msgid="8796112363642579333">"מצב שקט"</string>
<string name="turn_on_radio" msgid="2961717788170634233">"הפעל חיבור אלחוטי"</string>
- <string name="turn_off_radio" msgid="7222573978109933360">"כבה אלחוטי"</string>
+ <string name="turn_off_radio" msgid="7222573978109933360">"כיבוי אלחוטי"</string>
<string name="screen_lock" msgid="2072642720826409809">"נעילת מסך"</string>
<string name="power_off" msgid="4111692782492232778">"כיבוי"</string>
<string name="silent_mode_silent" msgid="5079789070221150912">"צלצול כבוי"</string>
@@ -231,17 +231,17 @@
<string name="reboot_to_update_title" msgid="2125818841916373708">"עדכון מערכת Android"</string>
<string name="reboot_to_update_prepare" msgid="6978842143587422365">"מתכונן לעדכון…"</string>
<string name="reboot_to_update_package" msgid="4644104795527534811">"מעבד את חבילת העדכון…"</string>
- <string name="reboot_to_update_reboot" msgid="4474726009984452312">"מאתחל…"</string>
+ <string name="reboot_to_update_reboot" msgid="4474726009984452312">"מתבצע אתחול…"</string>
<string name="reboot_to_reset_title" msgid="2226229680017882787">"איפוס לנתוני היצרן"</string>
- <string name="reboot_to_reset_message" msgid="3347690497972074356">"מאתחל…"</string>
- <string name="shutdown_progress" msgid="5017145516412657345">"מכבה..."</string>
- <string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"הטאבלט שלך יכבה."</string>
+ <string name="reboot_to_reset_message" msgid="3347690497972074356">"מתבצע אתחול…"</string>
+ <string name="shutdown_progress" msgid="5017145516412657345">"בתהליך כיבוי..."</string>
+ <string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"הטאבלט שלך ייכבה."</string>
<string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"מכשיר ה-Android TV יכבה."</string>
<string name="shutdown_confirm" product="watch" msgid="2977299851200240146">"השעון יכבה."</string>
<string name="shutdown_confirm" product="default" msgid="136816458966692315">"הטלפון שלך יכובה."</string>
<string name="shutdown_confirm_question" msgid="796151167261608447">"האם ברצונך לבצע כיבוי?"</string>
- <string name="reboot_safemode_title" msgid="5853949122655346734">"אתחל למצב בטוח"</string>
- <string name="reboot_safemode_confirm" msgid="1658357874737219624">"האם ברצונך לאתחל ולעבור למצב בטוח? פעולה זו תשבית את כל יישומי צד שלישי שהתקנת. הם ישוחזרו לאחר הפעלה מחדש של המכשיר."</string>
+ <string name="reboot_safemode_title" msgid="5853949122655346734">"אתחול למצב בטוח"</string>
+ <string name="reboot_safemode_confirm" msgid="1658357874737219624">"האם לבצע אתחול ולעבור למצב בטוח? הפעולה הזו תשבית את כל האפליקציות של צד שלישי שהתקנת. הן ישוחזרו לאחר הפעלה מחדש של המכשיר."</string>
<string name="recent_tasks_title" msgid="8183172372995396653">"נוצרו לאחרונה"</string>
<string name="no_recent_tasks" msgid="9063946524312275906">"אין אפליקציות אחרונות"</string>
<string name="global_actions" product="tablet" msgid="4412132498517933867">"אפשרויות טאבלט"</string>
@@ -258,7 +258,7 @@
<string name="bugreport_title" msgid="8549990811777373050">"דיווח על באג"</string>
<string name="bugreport_message" msgid="5212529146119624326">"הפעולה הזו תאסוף מידע על מצב המכשיר הנוכחי שלך כדי לשלוח אותו כהודעת אימייל. היא תימשך זמן קצר מרגע פתיחת הדיווח על הבאג ועד לשליחת ההודעה בפועל. יש להמתין בסבלנות."</string>
<string name="bugreport_option_interactive_title" msgid="7968287837902871289">"דוח אינטראקטיבי"</string>
- <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"השתמש באפשרות זו ברוב המקרים. היא מאפשרת לך לעקוב אחר התקדמות הדוח, להזין פרטים נוספים על הבעיה וליצור צילומי מסך. היא עשויה להשמיט כמה קטעים שנמצאים פחות בשימוש ואשר יצירת הדיווח עליהם נמשכת זמן רב."</string>
+ <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"כדאי להשתמש באפשרות הזו ברוב המקרים. היא מאפשרת לך לעקוב אחר התקדמות הדוח, להזין פרטים נוספים על הבעיה ולצלם את המסך. היא עשויה להשמיט כמה קטעים שנמצאים פחות בשימוש ושיצירת הדיווח עליהם נמשכת זמן רב."</string>
<string name="bugreport_option_full_title" msgid="7681035745950045690">"דוח מלא"</string>
<string name="bugreport_option_full_summary" msgid="1975130009258435885">"השתמש באפשרות זו כדי שההפרעה למערכת תהיה מזערית, כשהמכשיר אינו מגיב או איטי מדי, או כשאתה זקוק לכל קטעי הדוח. לא ניתן להזין פרטים נוספים או ליצור צילומי מסך נוספים."</string>
<plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
@@ -277,7 +277,7 @@
<string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"מצב טיסה כבוי"</string>
<string name="global_action_settings" msgid="4671878836947494217">"הגדרות"</string>
<string name="global_action_assist" msgid="2517047220311505805">"סיוע"</string>
- <string name="global_action_voice_assist" msgid="6655788068555086695">"Voice Assist"</string>
+ <string name="global_action_voice_assist" msgid="6655788068555086695">"האסיסטנט"</string>
<string name="global_action_lockdown" msgid="2475471405907902963">"נעילה"</string>
<string name="status_bar_notification_info_overflow" msgid="3330152558746563475">"999+"</string>
<string name="notification_hidden_text" msgid="2835519769868187223">"התראה חדשה"</string>
@@ -300,7 +300,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"אפליקציה פועלת"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"אפליקציות שמרוקנות את הסוללה"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"הגדלה"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"מדיניות בנושא אבטחת נגישות"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> משתמשת בסוללה"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> אפליקציות משתמשות בסוללה"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"הקש לקבלת פרטים על צריכה של נתונים וסוללה"</string>
@@ -325,6 +326,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"גישה לפעילות הגופנית שלך"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"מצלמה"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"צילום תמונות והקלטת וידאו"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"מכשירי Bluetooth בקרבת מקום"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"גילוי מכשירי Bluetooth בקרבת מקום והתחברות אליהם"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"יומני שיחות"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"קריאה וכתיבה של יומן השיחות של הטלפון"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"טלפון"</string>
@@ -332,7 +335,7 @@
<string name="permgrouplab_sensors" msgid="9134046949784064495">"חיישנים לבישים"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"גישה אל נתוני חיישנים של הסימנים החיוניים שלך"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"אחזור תוכן של חלון"</string>
- <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"בדוק את התוכן של חלון שאיתו אתה מבצע אינטראקציה."</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"בדיקת התוכן של חלון שאיתו מתבצעת אינטראקציה."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"הפעלה של \'גילוי באמצעות מגע\'"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"פריטים שעליהם תקיש יוקראו בקול, ותוכל לנווט במסך באמצעות תנועות."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"הצגת טקסט בזמן הקלדה"</string>
@@ -345,18 +348,18 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"אפשרות לזהות תנועות בזמן נגיעה בחיישן טביעות האצבע של המכשיר."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"צילום המסך"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ניתן לצלם צילום מסך של התצוגה."</string>
- <string name="permlab_statusBar" msgid="8798267849526214017">"השבת או שנה את שורת המצב"</string>
- <string name="permdesc_statusBar" msgid="5809162768651019642">"מאפשר לאפליקציה להשבית את שורת המצב או להוסיף ולהסיר סמלי מערכת."</string>
+ <string name="permlab_statusBar" msgid="8798267849526214017">"השבתה או שינוי של שורת הסטטוס"</string>
+ <string name="permdesc_statusBar" msgid="5809162768651019642">"מאפשרת לאפליקציה להשבית את שורת הסטטוס או להוסיף ולהסיר סמלי מערכת."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"להיות שורת הסטטוס"</string>
- <string name="permdesc_statusBarService" msgid="6652917399085712557">"מאפשר לאפליקציה להופיע בשורת המצב."</string>
+ <string name="permdesc_statusBarService" msgid="6652917399085712557">"מאפשרת לאפליקציה להופיע בשורת הסטטוס."</string>
<string name="permlab_expandStatusBar" msgid="1184232794782141698">"הרחב/כווץ את שורת המצב"</string>
<string name="permdesc_expandStatusBar" msgid="7180756900448498536">"מאפשר לאפליקציה להרחיב או לכווץ את שורת המצב."</string>
<string name="permlab_fullScreenIntent" msgid="4310888199502509104">"הצגת התראות כפעילויות במסך מלא במכשיר נעול"</string>
<string name="permdesc_fullScreenIntent" msgid="1100721419406643997">"מאפשרת לאפליקציה להציג התראות כפעילויות במסך מלא במכשיר נעול"</string>
<string name="permlab_install_shortcut" msgid="7451554307502256221">"התקן קיצורי דרך"</string>
- <string name="permdesc_install_shortcut" msgid="4476328467240212503">"מאפשר לאפליקציה להוסיף קיצורי דרך במסך דף הבית ללא התערבות המשתמש."</string>
- <string name="permlab_uninstall_shortcut" msgid="295263654781900390">"להסרת התקנה של קיצורי דרך"</string>
- <string name="permdesc_uninstall_shortcut" msgid="1924735350988629188">"מאפשר לאפליקציה להסיר קיצורי דרך במסך דף הבית ללא התערבות המשתמש."</string>
+ <string name="permdesc_install_shortcut" msgid="4476328467240212503">"מאפשרת לאפליקציה להוסיף קיצורי דרך במסך דף הבית ללא התערבות המשתמש."</string>
+ <string name="permlab_uninstall_shortcut" msgid="295263654781900390">"הסרת התקנה של קיצורי דרך"</string>
+ <string name="permdesc_uninstall_shortcut" msgid="1924735350988629188">"מאפשרת לאפליקציה להסיר קיצורי דרך במסך דף הבית ללא התערבות המשתמש."</string>
<string name="permlab_processOutgoingCalls" msgid="4075056020714266558">"ניתוב מחדש של שיחות יוצאות"</string>
<string name="permdesc_processOutgoingCalls" msgid="7833149750590606334">"מאפשרת לאפליקציה לראות את המספר המחויג במהלך ביצוע שיחה יוצאת, עם האפשרות להפנות את השיחה למספר אחר או לבטל את השיחה לחלוטין."</string>
<string name="permlab_answerPhoneCalls" msgid="4131324833663725855">"מענה לשיחות טלפון"</string>
@@ -380,7 +383,7 @@
<string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"האפליקציה הזו יכולה לקרוא את כל הודעות הטקסט (SMS) המאוחסנות במכשיר ה-Android TV."</string>
<string name="permdesc_readSms" product="default" msgid="774753371111699782">"אפליקציה זו יכולה לקרוא את כל הודעות הטקסט (SMS) המאוחסנות בטלפון."</string>
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"קבלת הודעות טקסט (WAP)"</string>
- <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"מאפשר לאפליקציה לקבל ולעבד הודעות WAP. אישור זה כולל את היכולת לעקוב אחר הודעות שנשלחו אליך ולמחוק אותן מבלי להציג לך אותן."</string>
+ <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"מאפשרת לאפליקציה לקבל ולעבד הודעות WAP. ההרשאה הזו כוללת את היכולת לעקוב אחר הודעות שנשלחו אליך ולמחוק אותן מבלי להציג לך אותן."</string>
<string name="permlab_getTasks" msgid="7460048811831750262">"אחזור אפליקציות פעילות"</string>
<string name="permdesc_getTasks" msgid="7388138607018233726">"מאפשרת לאפליקציה לאחזר מידע לגבי משימות הפועלות כרגע וכאלו שפעלו לאחרונה. ייתכן שההרשאה הזו תתיר לאפליקציה לגלות מידע לגבי האפליקציות שבהן נעשה שימוש במכשיר."</string>
<string name="permlab_manageProfileAndDeviceOwners" msgid="639849495253987493">"ניהול בעלים של פרופיל ומכשיר"</string>
@@ -388,15 +391,15 @@
<string name="permlab_reorderTasks" msgid="7598562301992923804">"סידור מחדש של אפליקציות פעילות"</string>
<string name="permdesc_reorderTasks" msgid="8796089937352344183">"מאפשר לאפליקציה להעביר משימות לחזית ולרקע. האפליקציה עשוי לעשות זאת ללא התערבותך."</string>
<string name="permlab_enableCarMode" msgid="893019409519325311">"הפוך מצב מכונית לפעיל"</string>
- <string name="permdesc_enableCarMode" msgid="56419168820473508">"מאפשר לאפליקציה לאפשר את מצב מכונית."</string>
+ <string name="permdesc_enableCarMode" msgid="56419168820473508">"מאפשרת לאפליקציה להפעיל את מצב מכונית."</string>
<string name="permlab_killBackgroundProcesses" msgid="6559320515561928348">"סגירת אפליקציות אחרות"</string>
<string name="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"מאפשר לאפליקציה להפסיק תהליכים ברקע המבוצעים על ידי אפליקציות אחרות. הדבר עשוי לגרום להפסקת פעולתם של אפליקציות אחרות."</string>
<string name="permlab_systemAlertWindow" msgid="5757218350944719065">"אפליקציה זו יכולה להופיע מעל אפליקציות אחרות."</string>
- <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"אפליקציה זו יכולה להופיע מעל אפליקציות אחרות או בחלקים אחרים של המסך. ייתכן שהדבר יפריע לך להשתמש באפליקציות וישנה את הופעתן."</string>
+ <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"האפליקציה הזו יכולה להופיע מעל אפליקציות אחרות או בחלקים אחרים של המסך. ייתכן שהדבר יפריע לך להשתמש באפליקציות וישנה את האופן שבו הן מופיעות."</string>
<string name="permlab_runInBackground" msgid="541863968571682785">"פעולה ברקע"</string>
- <string name="permdesc_runInBackground" msgid="4344539472115495141">"האפליקציה הזו יכולה לפעול ברקע. ייתכן שהסוללה תתרוקן מהר יותר במצב זה."</string>
+ <string name="permdesc_runInBackground" msgid="4344539472115495141">"האפליקציה הזו יכולה לפעול ברקע. ייתכן שהסוללה תתרוקן מהר יותר במצב הזה."</string>
<string name="permlab_useDataInBackground" msgid="783415807623038947">"שימוש בנתונים ברקע"</string>
- <string name="permdesc_useDataInBackground" msgid="1230753883865891987">"האפליקציה הזו יכולה להשתמש בנתונים ברקע. ייתכן שצריכת הנתונים תעלה במצב זה."</string>
+ <string name="permdesc_useDataInBackground" msgid="1230753883865891987">"האפליקציה הזו יכולה להשתמש בנתונים ברקע. ייתכן שצריכת הנתונים תגדל במצב הזה."</string>
<string name="permlab_persistentActivity" msgid="464970041740567970">"הגדרת האפליקציה לפעול תמיד"</string>
<string name="permdesc_persistentActivity" product="tablet" msgid="6055271149187369916">"מאפשר לאפליקציה להפוך חלקים ממנו לקבועים בזיכרון. פעולה זו עשויה להגביל את הזיכרון הזמין לאפליקציות אחרים ולהאט את פעולת הטאבלט."</string>
<string name="permdesc_persistentActivity" product="tv" msgid="6800526387664131321">"מאפשרת לאפליקציה לאחסן חלקים שלה בזיכרון באופן קבוע. פעולה זו עשויה להגביל את הזיכרון הזמין לאפליקציות אחרות ולהאט את הפעולה של מכשיר ה-Android TV."</string>
@@ -406,19 +409,19 @@
<string name="permlab_getPackageSize" msgid="375391550792886641">"מדידת נפח האחסון של אפליקציות"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"מאפשר לאפליקציה לאחזר את הקוד, הנתונים, וגודלי קובצי המטמון שלו"</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"שינוי הגדרות מערכת"</string>
- <string name="permdesc_writeSettings" msgid="8293047411196067188">"מאפשר לאפליקציה לשנות את נתוני הגדרות המערכת. אפליקציות זדוניות עלולות לשבש את תצורת המערכת שלך."</string>
+ <string name="permdesc_writeSettings" msgid="8293047411196067188">"מאפשרת לאפליקציה לשנות את נתוני הגדרות המערכת. אפליקציות זדוניות עלולות לשבש את תצורת המערכת שלך."</string>
<string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"הפעלה בעת אתחול"</string>
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"מאפשר לאפליקציה להפעיל את עצמו מיד עם סיום תהליך האתחול של המערכת. משום כך הפעלת הטאבלט עשויה להתארך והאפליקציה עלולה להאט את הפעילות הכללית של הטאבלט, בשל פעילותה התמידית."</string>
- <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"מאפשרת לאפליקציה להפעיל את עצמה ברגע שהמערכת מסיימת את ההפעלה. פעולה זו עשויה להאריך את הזמן שדרוש כדי להפעיל את מכשיר ה-Android TV, והיא מאפשרת לאפליקציה להאט את המכשיר כולו כי האפליקציה רצה כל הזמן."</string>
+ <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"מאפשרת לאפליקציה להפעיל את עצמה ברגע שהמערכת מסיימת את ההפעלה. הפעולה הזו עשויה להאריך את הזמן שדרוש כדי להפעיל את מכשיר ה-Android TV, והיא מאפשרת לאפליקציה להאט את המכשיר כולו כי האפליקציה פועלת כל הזמן."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"מאפשר לאפליקציה להפעיל את עצמו מיד עם השלמת תהליך האתחול של המערכת. משום כך הפעלת הטלפון עשויה להתארך והאפליקציה עלולה להאט את הפעילות הכללית של הטלפון, בשל פעילותה התמידית."</string>
- <string name="permlab_broadcastSticky" msgid="4552241916400572230">"שלח שידור דביק"</string>
- <string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"מאפשר לאפליקציה לשלוח שידורים דביקים, אשר נותרים לאחר סיום השידור. אפליקציות זדוניות עלולות להאט את פעילות הטאבלט או להפוך אותה לבלתי יציבה על ידי אילוץ המכשיר להשתמש ביותר מדי זיכרון."</string>
+ <string name="permlab_broadcastSticky" msgid="4552241916400572230">"שליחת שידור במיקום קבוע"</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"מאפשרת לאפליקציה לשלוח שידורים במיקום קבוע, אשר נותרים לאחר סיום השידור. אפליקציות זדוניות עלולות להאט את פעילות הטאבלט או להפוך אותה לבלתי יציבה על ידי אילוץ המכשיר להשתמש ביותר מדי זיכרון."</string>
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"מאפשרת לאפליקציה לשלוח שידורים \"דביקים\" (sticky), שנותרים לאחר שהשידור מסתיים. בעקבות שימוש מופרז באפשרות זו, שיעור ניצול הזיכרון יהיה גבוה מדי ומכשיר ה-Android TV עלול לפעול בצורה איטית או בלתי יציבה."</string>
- <string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"מאפשר לאפליקציה לשלוח שידורים דביקים, אשר נותרים לאחר סיום השידור. אפליקציות זדוניות עלולות להאט את פעילות הטלפון או להפוך אותה לבלתי יציבה על ידי אילוץ המכשיר להשתמש ביותר מדי זיכרון."</string>
+ <string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"מאפשרת לאפליקציה לשלוח שידורים במיקום קבוע, אשר נותרים לאחר סיום השידור. אפליקציות זדוניות עלולות להאט את פעילות הטלפון או להפוך אותה לבלתי יציבה על ידי אילוץ המכשיר להשתמש ביותר מדי זיכרון."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"קריאת אנשי הקשר שלך"</string>
<string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"מאפשרת לאפליקציה לקרוא נתונים על אנשי הקשר השמורים בטאבלט שלך. לאפליקציות תהיה גם גישה לחשבונות בטאבלט שיצרו אנשי קשר. פעולה זו עשויה לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת. הרשאה זו מאפשרת לאפליקציות לשמור נתונים של אנשי הקשר שלך, ואפליקציות זדוניות עלולות לשתף נתונים של אנשי קשר ללא ידיעתך."</string>
<string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"מאפשרת לאפליקציה לקרוא נתונים על אנשי הקשר השמורים במכשיר ה-Android TV שלך. לאפליקציות תהיה גם גישה לחשבונות במכשיר ה-Android TV שיצרו אנשי קשר. פעולה זו עשויה לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת. הרשאה זו מאפשרת לאפליקציות לשמור נתונים של אנשי הקשר שלך, ואפליקציות זדוניות עלולות לשתף נתונים של אנשי קשר ללא ידיעתך."</string>
- <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"מאפשרת לאפליקציה לקרוא נתונים על אנשי הקשר השמורים בטלפון שלך. לאפליקציות תהיה גם גישה לחשבונות בטלפון שיצרו אנשי קשר. פעולה זו עשויה לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת. הרשאה זו מאפשרת לאפליקציות לשמור נתונים של אנשי הקשר שלך, ואפליקציות זדוניות עלולות לשתף נתונים של אנשי קשר ללא ידיעתך."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"מאפשרת לאפליקציה לקרוא נתונים על אנשי הקשר השמורים בטלפון שלך. לאפליקציות תהיה גם גישה לחשבונות בטלפון שדרכם נוצרו אנשי קשר. הפעולה הזו עשויה לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת. ההרשאה הזו מאפשרת לאפליקציות לשמור נתונים של אנשי הקשר שלך, ואפליקציות זדוניות עלולות לשתף נתונים של אנשי קשר ללא ידיעתך."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"שינוי אנשי הקשר שלך"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"מאפשרת לאפליקציה לשנות את הנתונים לגבי אנשי הקשר המאוחסנים בטאבלט שלך. הרשאה זו מאפשרת לאפליקציות למחוק נתונים של אנשי קשר."</string>
<string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"מאפשרת לאפליקציה לשנות את הנתונים לגבי אנשי הקשר המאוחסנים במכשיר ה-Android TV שלך. ההרשאה הזו מאפשרת לאפליקציות למחוק נתונים של אנשי קשר."</string>
@@ -426,11 +429,11 @@
<string name="permlab_readCallLog" msgid="1739990210293505948">"קריאת יומן שיחות"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"אפליקציה זו יכולה לקרוא את היסטוריית השיחות שלך."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"כתיבת יומן שיחות"</string>
- <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"מאפשר לאפליקציה לשנות את יומן השיחות של הטאבלט, כולל נתונים על שיחות נכנסות ויוצאות. אפליקציות זדוניות עלולות לעשות בכך שימוש כדי למחוק או לשנות את יומן השיחות שלך."</string>
+ <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"מאפשרת לאפליקציה לשנות את יומן השיחות של הטאבלט, כולל נתונים על שיחות נכנסות ויוצאות. אפליקציות זדוניות עלולות לעשות בכך שימוש כדי למחוק או לשנות את יומן השיחות שלך."</string>
<string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"מאפשרת לאפליקציה לשנות את יומן השיחות של מכשיר ה-Android TV, כולל נתונים על שיחות נכנסות ויוצאות. אפליקציות זדוניות עלולות להשתמש בכך כדי למחוק או לשנות את יומן השיחות."</string>
<string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"מאפשר לאפליקציה לשנות את יומן השיחות של הטלפון, כולל נתונים על שיחות נכנסות ויוצאות. אפליקציות זדוניות עלולות לעשות בכך שימוש כדי למחוק או לשנות את יומן השיחות שלך."</string>
<string name="permlab_bodySensors" msgid="3411035315357380862">"גישה אל חיישני גוף (כמו מוניטורים לקצב לב)"</string>
- <string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"מאפשר לאפליקציה לגשת אל נתוני חיישנים העוקבים אחר מצבך הגופני, כמו קצב הלב."</string>
+ <string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"מאפשרת לאפליקציה לגשת אל נתוני חיישנים העוקבים אחר מצבך הגופני, כמו קצב הלב."</string>
<string name="permlab_readCalendar" msgid="6408654259475396200">"קריאה של אירועי יומן והפרטים שלהם"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"האפליקציה הזו יכולה לקרוא את כל אירועי היומן המאוחסנים בטאבלט, ולשתף או לשמור את נתוני היומן."</string>
<string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"אפליקציה זו יכולה לקרוא את כל אירועי היומן המאוחסנים במכשיר ה-Android TV, ולשתף או לשמור את נתוני היומן."</string>
@@ -443,7 +446,7 @@
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"מאפשרת לאפליקציה לגשת לפקודות נוספות של ספק המיקום. הרשאה זו עשויה לאפשר לאפליקציה לשבש את פעולת ה-GPS או מקורות מיקום אחרים."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"קבלת גישה למיקום מדויק בחזית בלבד"</string>
<string name="permdesc_accessFineLocation" msgid="6732174080240016335">"האפליקציה הזו יכולה לקבל את המיקום המדויק שלך משירותי המיקום כאשר היא בשימוש. האפליקציה תקבל את המיקום רק אם הפעלת את שירותי המיקום במכשיר. פעולה זו עלולה להגביר את השימוש בסוללה."</string>
- <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"קבלת גישה למיקום משוער תתבצע בחזית בלבד"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"קבלת גישה למיקום משוער לאפליקציות בחזית בלבד"</string>
<string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"כאשר האפליקציה בשימוש היא יכולה לקבל משירותי המיקום את המיקום המשוער שלך. האפליקציה תקבל את המיקום רק אם הפעלת את שירותי המיקום במכשיר."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"גישה למיקום ברקע"</string>
<string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"לאפליקציה תמיד יש גישה למיקום, גם כשאינה בשימוש."</string>
@@ -457,18 +460,18 @@
<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>
+ <string name="permlab_camera" msgid="6320282492904119413">"צילום תמונות וסרטונים"</string>
<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="permdesc_systemCamera" msgid="5938360914419175986">"האפליקציה הזו בעלת ההרשאות, או אפליקציית המערכת הזו, יכולה לצלם תמונות ולהקליט סרטונים באמצעות מצלמת מערכת בכל זמן. בנוסף, לאפליקציה נדרשת ההרשאה android.permission.CAMERA"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"אפליקציה או שירות יוכלו לקבל קריאות חוזרות (callback) כשמכשירי מצלמה ייפתחו או ייסגרו."</string>
<string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"האפליקציה הזו יכולה לקבל קריאות חוזרות (callback) כשמכשיר מצלמה כלשהו נפתח (באמצעות אפליקציה) או נסגר."</string>
<string name="permlab_vibrate" msgid="8596800035791962017">"שליטה ברטט"</string>
<string name="permdesc_vibrate" msgid="8733343234582083721">"מאפשר לאפליקציה לשלוט ברטט."</string>
<string name="permdesc_vibrator_state" msgid="7050024956594170724">"מאפשרת לאפליקציה לקבל גישה למצב רטט."</string>
- <string name="permlab_callPhone" msgid="1798582257194643320">"התקשר ישירות למספרי טלפון"</string>
+ <string name="permlab_callPhone" msgid="1798582257194643320">"חיוג ישירות למספרי טלפון"</string>
<string name="permdesc_callPhone" msgid="5439809516131609109">"מאפשר לאפליקציה להתקשר למספרי טלפון ללא התערבותך. פעולה זו עשויה לגרום לשיחות או לחיובים לא צפויים. שים לב שהדבר לא מאפשר לאפליקציה להתקשר למספרי חירום. אפליקציות זדוניות עשויות לגרום לעלויות על ידי ביצוע שיחות ללא התערבותך."</string>
<string name="permlab_accessImsCallService" msgid="442192920714863782">"גישה אל שירות שיחות IMS"</string>
<string name="permdesc_accessImsCallService" msgid="6328551241649687162">"מאפשר לאפליקציה להשתמש בשירות ה-IMS לביצוע שיחות ללא התערבותך."</string>
@@ -477,7 +480,7 @@
<string name="permlab_manageOwnCalls" msgid="9033349060307561370">"ניתוב שיחות דרך המערכת"</string>
<string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"מאפשרת לאפליקציה לנתב את השיחות דרך המערכת כדי לשפר את חוויית השיחה."</string>
<string name="permlab_callCompanionApp" msgid="3654373653014126884">"ניתן להציג שיחות ולשלוט בהן באמצעות המערכת."</string>
- <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"מאפשר לאפליקציה להציג שיחות נוכחיות ולשלוט בהן במכשיר. זה כולל פרטים כמו מספרי שיחה של שיחות ומצב השיחה."</string>
+ <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"מאפשרת לאפליקציה להציג שיחות נוכחיות ולשלוט בהן במכשיר – כולל פרטים כמו מספרי שיחה של שיחות ומצב השיחה."</string>
<string name="permlab_exemptFromAudioRecordRestrictions" msgid="1164725468350759486">"פטור מהגבלות של הקלטת אודיו"</string>
<string name="permdesc_exemptFromAudioRecordRestrictions" msgid="2425117015896871976">"פוטרת את האפליקציה מהגבלות של הקלטת אודיו."</string>
<string name="permlab_acceptHandover" msgid="2925523073573116523">"המשך שיחה מאפליקציה אחרת"</string>
@@ -497,22 +500,22 @@
<string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"מאפשרת לאפליקציה להשתמש במשדר האינפרה-אדום של מכשיר ה-Android TV."</string>
<string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"מאפשרת לאפליקציה להשתמש במשדר האינפרא-אדום של הטלפון."</string>
<string name="permlab_setWallpaper" msgid="6959514622698794511">"הגדרת טפט"</string>
- <string name="permdesc_setWallpaper" msgid="2973996714129021397">"מאפשר לאפליקציה להגדיר את טפט המערכת."</string>
+ <string name="permdesc_setWallpaper" msgid="2973996714129021397">"מאפשרת לאפליקציה להגדיר את טפט המערכת."</string>
<string name="permlab_setWallpaperHints" msgid="1153485176642032714">"התאמת גודל הטפט שלך"</string>
<string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"מאפשר לאפליקציה להגדיר את סמני הגודל של טפט המערכת."</string>
<string name="permlab_setTimeZone" msgid="7922618798611542432">"הגדרת אזור זמן"</string>
- <string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"מאפשר לאפליקציה לשנות את אזור הזמן של הטאבלט."</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"מאפשרת לאפליקציה לשנות את אזור הזמן של הטאבלט."</string>
<string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"מאפשרת לאפליקציה לשנות את אזור הזמן של מכשיר ה-Android TV."</string>
- <string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"מאפשר לאפליקציה לשנות את אזור הזמן של הטלפון."</string>
+ <string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"מאפשר, לאפליקציה לשנות את אזור הזמן של הטלפון."</string>
<string name="permlab_getAccounts" msgid="5304317160463582791">"חיפוש חשבונות במכשיר"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"מאפשר לאפליקציה לקבל רשימה של חשבונות המוכרים לטאבלט. הדבר עשוי לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"מאפשרת לאפליקציה לקבל רשימה של חשבונות המוכרים לטאבלט. הדבר עשוי לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת."</string>
<string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"מאפשרת לאפליקציה לקבל את רשימת החשבונות המוכרים למכשיר ה-Android TV. הפרטים עשויים לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת."</string>
<string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"מאפשר לאפליקציה לקבל רשימה של חשבונות המוכרים לטלפון. הדבר עשוי לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת."</string>
<string name="permlab_accessNetworkState" msgid="2349126720783633918">"הצגת חיבורי רשת"</string>
<string name="permdesc_accessNetworkState" msgid="4394564702881662849">"מאפשרת לאפליקציה להציג מידע לגבי חיבורי רשת, למשל, אילו רשתות קיימות ומחוברות."</string>
<string name="permlab_createNetworkSockets" msgid="3224420491603590541">"קבלת גישת רשת מלאה"</string>
- <string name="permdesc_createNetworkSockets" msgid="7722020828749535988">"מאפשר לאפליקציה ליצור Sockets ולהשתמש בפרוטוקולי רשת מותאמים אישית. הדפדפן, כמו אפליקציות אחרות, מספק אמצעים לשליחת נתונים לאינטרנט, כך שאישור זה אינו נחוץ לשליחת נתונים לאינטרנט."</string>
- <string name="permlab_changeNetworkState" msgid="8945711637530425586">"שנה את קישוריות הרשת"</string>
+ <string name="permdesc_createNetworkSockets" msgid="7722020828749535988">"מאפשרת לאפליקציה ליצור Sockets ולהשתמש בפרוטוקולי רשת מותאמים אישית. הדפדפן, כמו אפליקציות אחרות, מספק אמצעים לשליחת נתונים לאינטרנט, כך שאישור זה אינו נחוץ לשליחת נתונים לאינטרנט."</string>
+ <string name="permlab_changeNetworkState" msgid="8945711637530425586">"שינוי של קישוריות הרשת"</string>
<string name="permdesc_changeNetworkState" msgid="649341947816898736">"מאפשר לאפליקציה לשנות את מצב הקישוריות של הרשת."</string>
<string name="permlab_changeTetherState" msgid="9079611809931863861">"שינוי של קישוריות קשורה"</string>
<string name="permdesc_changeTetherState" msgid="3025129606422533085">"מאפשר לאפליקציה לשנות את מצב הקישוריות של רשת קשורה."</string>
@@ -520,28 +523,32 @@
<string name="permdesc_accessWifiState" msgid="6913641669259483363">"מאפשר לאפליקציה להציג מידע על רשתות Wi-Fi, למשל, האם Wi-Fi מופעל, כמו גם שם מכשירי ה-Wi-Fi המחוברים."</string>
<string name="permlab_changeWifiState" msgid="7947824109713181554">"התחברות והתנתקות מ-Wi-Fi"</string>
<string name="permdesc_changeWifiState" msgid="7170350070554505384">"מאפשר לאפליקציה להתחבר לנקודות גישת Wi-Fi ולהתנתק מהן, וכן לבצע שינויים בתצורת המכשיר עבור רשתות Wi-Fi."</string>
- <string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"אפשר קבלת שידורים מרובים ב-Wi-Fi"</string>
+ <string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"מאפשרת לקבל שידורים מרובים ב-Wi-Fi"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"מאפשר לאפליקציה לקבל חבילות שנשלחו לכל המכשירים ברשת Wi-Fi באמצעות כתובות שידור לקבוצה, ולא רק בטאבלט שלך. צריכת החשמל גבוהה יותר מאשר במצב שאינו שידור לקבוצה."</string>
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"מאפשרת לאפליקציה לקבל חבילות שנשלחו לכל המכשירים ברשת Wi-Fi באמצעות כתובות מולטיקאסט, ולא רק למכשיר ה-Android TV. צריכת החשמל תהיה גבוהה יותר מאשר במצב שאינו מולטיקאסט."</string>
- <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"מאפשר לאפליקציה לקבל חבילות שנשלחו לכל המכשירים ברשת Wi-Fi באמצעות כתובות שידור לקבוצה, ולא רק בטלפון שלך. צריכת החשמל גבוהה יותר מאשר במצב שאינו שידור לקבוצה."</string>
+ <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"מאפשרת לאפליקציה לקבל חבילות שנשלחו לכל המכשירים ברשת Wi-Fi באמצעות כתובות שידור לקבוצה, ולא רק בטלפון שלך. צריכת החשמל גבוהה יותר מאשר במצב שאינו שידור לקבוצה."</string>
<string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"גישה להגדרות Bluetooth"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"מאפשר לאפליקציה להגדיר את תצורתו של הטאבלט המקומי מסוג Bluetooth וכן לגלות מכשירים מרוחקים ולבצע התאמה איתם."</string>
- <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"מאפשרת לאפליקציה להגדיר Bluetooth במכשיר ה-Android TV, ולגלות מכשירים מרוחקים ולבצע התאמה איתם."</string>
+ <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"מאפשרת לאפליקציה להגדיר Bluetooth במכשיר ה-Android TV, ולגלות מכשירים מרוחקים ולבצע איתם התאמה."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"מאפשר לאפליקציה להגדיר את תצורתו של הטלפון המקומי מסוג Bluetooth וכן לגלות מכשירים מרוחקים ולבצע התאמה איתם."</string>
<string name="permlab_accessWimaxState" msgid="7029563339012437434">"התחברות והתנתקות מ-WiMAX"</string>
- <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"מאפשר לאפליקציה לדעת האם WiNMAX מופעל, כמו גם לקבל מידע האם רשתות WiNMAX כלשהן מחוברות."</string>
+ <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"מאפשרת לאפליקציה לדעת האם WiNMAX מופעל, ולקבל מידע לגבי רשתות WiNMAX מחוברות."</string>
<string name="permlab_changeWimaxState" msgid="6223305780806267462">"שנה את מצב WiMAX"</string>
- <string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"מאפשר לאפליקציה לחבר את הטאבלט לרשתות WiMAX ולהתנתק מהן."</string>
+ <string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"מאפשרת לאפליקציה לחבר את הטאבלט לרשתות WiMAX ולהתנתק מהן."</string>
<string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"מאפשרת לאפליקציה לחבר את מכשיר ה-Android TV לרשתות WiMAX ולהתנתק מהן."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"מאפשר לאפליקציה לחבר את הטלפון לרשתות WiMAX ולהתנתק מהן."</string>
<string name="permlab_bluetooth" msgid="586333280736937209">"התאמה למכשירי Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"מאפשר לאפליקציה להציג את תצורת ה-Bluetooth בטאבלט, וכן ליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"מאפשרת לאפליקציה להציג את הגדרת ה-Bluetooth במכשיר ה-Android TV, וליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
- <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"מאפשר לאפליקציה להציג את תצורת ה-Bluetooth בטלפון, וכן ליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
+ <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"מאפשרת לאפליקציה להציג את תצורת ה-Bluetooth בטלפון, וכן ליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"גילוי מכשירי Bluetooth בקרבת מקום והתאמה ביניהם"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"מאפשרת לאפליקציה לגלות מכשירי Bluetooth בקרבת מקום ולבצע התאמה איתם"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"התחברות למכשירי Bluetooth מתאימים"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"מאפשרת לאפליקציה להתחבר למכשירי Bluetooth מותאמים"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"פרטים על שירות תשלום מועדף ב-NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"מאפשרת לאפליקציה לקבל פרטים על שירות תשלום מועדף ב-NFC, כמו עזרים רשומים ויעד של נתיב."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"שלוט ב-Near Field Communication"</string>
- <string name="permdesc_nfc" msgid="8352737680695296741">"מאפשר לאפליקציה נהל תקשורת עם תגים, כרטיסים וקוראים מסוג \'תקשורת מטווח קצר\'."</string>
+ <string name="permdesc_nfc" msgid="8352737680695296741">"מאפשרת לאפליקציה נהל תקשורת עם תגים, כרטיסים וקוראים מסוג \'תקשורת מטווח קצר\' (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ביטול נעילת המסך שלך"</string>
<string name="permdesc_disableKeyguard" msgid="3223710003098573038">"מאפשר לאפליקציה להשבית את נעילת המקשים וכל אמצעי אבטחה משויך המבוסס על סיסמה. לדוגמה, הטלפון משבית את נעילת המקשים בעת קבלה של שיחת טלפון נכנסת, ולאחר מכן מפעיל מחדש את נעילת המקשים עם סיום השיחה."</string>
<string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"בקשת מידע לגבי מידת המורכבות של נעילת המסך"</string>
@@ -551,7 +558,7 @@
<string name="permlab_manageFingerprint" msgid="7432667156322821178">"ניהול חומרה של טביעות אצבעות"</string>
<string name="permdesc_manageFingerprint" msgid="2025616816437339865">"מאפשר לאפליקציה להפעיל שיטות להוספה ומחיקה של תבניות טביעות אצבעות שבהן ייעשה שימוש."</string>
<string name="permlab_useFingerprint" msgid="1001421069766751922">"שימוש בחומרה של טביעות אצבעות"</string>
- <string name="permdesc_useFingerprint" msgid="412463055059323742">"מאפשר לאפליקציה להשתמש בחומרה של טביעות אצבעות לצורך אימות"</string>
+ <string name="permdesc_useFingerprint" msgid="412463055059323742">"מאפשרת לאפליקציה להשתמש בחומרה של טביעות אצבעות לצורך אימות"</string>
<string name="permlab_audioWrite" msgid="8501705294265669405">"לשנות את אוסף המוזיקה שלך"</string>
<string name="permdesc_audioWrite" msgid="8057399517013412431">"מאפשרת לאפליקציה לשנות את אוסף המוזיקה שלך."</string>
<string name="permlab_videoWrite" msgid="5940738769586451318">"לשנות את אוסף הסרטונים שלך"</string>
@@ -562,7 +569,7 @@
<string name="permdesc_mediaLocation" msgid="597912899423578138">"מאפשרת לאפליקציה לקרוא מיקומים מאוסף המדיה שלך."</string>
<string name="biometric_app_setting_name" msgid="3339209978734534457">"שימוש במידע ביומטרי"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"שימוש במידע ביומטרי בנעילת מסך"</string>
- <string name="biometric_dialog_default_title" msgid="55026799173208210">"אימות זהותך"</string>
+ <string name="biometric_dialog_default_title" msgid="55026799173208210">"אימות הזהות שלך"</string>
<string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"יש להשתמש במידע ביומטרי כדי להמשיך"</string>
<string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"יש להשתמש במידע הביומטרי או בנעילת המסך כדי להמשיך"</string>
<string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"חומרה ביומטרית לא זמינה"</string>
@@ -573,25 +580,35 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"שגיאה באימות"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"שימוש בנעילת מסך"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"יש להזין את פרטי הכניסה של המכשיר כדי להמשיך"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"זוהתה טביעת אצבע חלקית. אפשר לנסות שוב."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"לא ניתן היה לעבד את טביעת האצבע. נסה שוב."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"החיישן של טביעות האצבעות מלוכלך. צריך לנקות אותו ולנסות שוב."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"הזזת את האצבע מהר מדי. נסה שוב."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"הזזת את האצבע לאט מדי. נסה שוב."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"טביעת האצבע אומתה"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"זיהוי הפנים בוצע"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"זיהוי הפנים בוצע. יש ללחוץ על אישור"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"החומרה בשביל טביעות אצבעות אינה זמינה."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"לא ניתן לאחסן טביעת אצבע. יש להסיר טביעת אצבע קיימת."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"נגמר הזמן הקצוב לטביעת אצבע. אפשר לנסות שוב."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"פעולת טביעת האצבע בוטלה."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"פעולת טביעת האצבע בוטלה על ידי המשתמש."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"יותר מדי ניסיונות. יש לנסות שוב מאוחר יותר."</string>
<string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"יותר מדי ניסיונות. חיישן טביעות האצבע הושבת."</string>
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"כדאי לנסות שוב."</string>
- <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"לא נרשמו טביעות אצבע."</string>
+ <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"לא נסרקו טביעות אצבע."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"במכשיר זה אין חיישן טביעות אצבע."</string>
<string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"החיישן מושבת באופן זמני."</string>
<string name="fingerprint_name_template" msgid="8941662088160289778">"אצבע <xliff:g id="FINGERID">%d</xliff:g>"</string>
@@ -607,8 +624,16 @@
<string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"שימוש בחומרה לשחרור נעילה על ידי זיהוי פנים"</string>
<string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"מאפשרת לאפליקציה להשתמש בחומרה לשחרור נעילה על ידי זיהוי פנים לצורך אימות"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"שחרור נעילה על ידי זיהוי פנים"</string>
- <string name="face_recalibrate_notification_title" msgid="5944930528030496897">"יש לבצע רישום מחדש של הפנים שלך"</string>
+ <string name="face_recalibrate_notification_title" msgid="5944930528030496897">"יש לבצע סריקה חוזרת של הפנים שלך"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"לשיפור הזיהוי יש לבצע רישום מחדש של הפנים שלך"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"לא ניתן היה לקלוט את הפנים במדויק. יש לנסות שוב."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"בהיר מדי. צריך תאורה עדינה יותר."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"התמונה חשוכה מדי. צריך תאורה חזקה יותר."</string>
@@ -621,7 +646,7 @@
<string name="face_acquired_poor_gaze" msgid="4427153558773628020">"יש להביט ישירות אל המכשיר."</string>
<string name="face_acquired_not_detected" msgid="2945945257956443257">"עליך למקם את הפנים ישירות מול הטלפון."</string>
<string name="face_acquired_too_much_motion" msgid="8199691445085189528">"יותר מדי תנועה. יש להחזיק את הטלפון בצורה יציבה."</string>
- <string name="face_acquired_recalibrate" msgid="8724013080976469746">"יש לרשום מחדש את הפנים."</string>
+ <string name="face_acquired_recalibrate" msgid="8724013080976469746">"יש לסרוק שוב את הפנים."</string>
<string name="face_acquired_too_different" msgid="4699657338753282542">"כבר לא ניתן לזהות פנים. יש לנסות שוב."</string>
<string name="face_acquired_too_similar" msgid="7684650785108399370">"דומה מדי, יש לשנות תנוחה."</string>
<string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"עליך ליישר קצת את הראש."</string>
@@ -633,8 +658,8 @@
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"לא ניתן לאמת את הפנים. החומרה לא זמינה."</string>
<string name="face_error_timeout" msgid="522924647742024699">"יש לנסות שוב את שחרור הנעילה על ידי זיהוי פנים."</string>
- <string name="face_error_no_space" msgid="5649264057026021723">"לא ניתן לאחסן נתוני פנים. תחילה יש למחוק פנים ישנים."</string>
- <string name="face_error_canceled" msgid="2164434737103802131">"פעולת הפנים בוטלה."</string>
+ <string name="face_error_no_space" msgid="5649264057026021723">"לא ניתן לאחסן נתוני פנים חדשים. תחילה יש למחוק את הנתונים הישנים."</string>
+ <string name="face_error_canceled" msgid="2164434737103802131">"הפעולה לאימות הפנים בוטלה."</string>
<string name="face_error_user_canceled" msgid="8553045452825849843">"שחרור הנעילה על ידי זיהוי פנים בוטל על ידי המשתמש."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"יותר מדי ניסיונות. יש לנסות שוב מאוחר יותר."</string>
<string name="face_error_lockout_permanent" msgid="8277853602168960343">"יותר מדי ניסיונות. שחרור נעילה על ידי זיהוי פנים מושבת."</string>
@@ -653,9 +678,9 @@
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"קרא את הגדרות הסינכרון"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"מאפשר לאפליקציה לקרוא את הגדרות הסנכרון של חשבון. לדוגמה, ניתן לגלות כך האם האפליקציה \'אנשים\' מסונכרן עם חשבון כלשהו."</string>
<string name="permlab_writeSyncSettings" msgid="6583154300780427399">"הפעלת וכיבוי סנכרון"</string>
- <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"מאפשר לאפליקציה לשנות את הגדרות הסנכרון של חשבון. לדוגמה, ניתן להשתמש בכך על מנת להפעיל סנכרון של האפליקציה \'אנשים\' עם חשבון כלשהו."</string>
+ <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"מאפשרת לאפליקציה לשנות את הגדרות הסנכרון של חשבונות. לדוגמה, אפשר להשתמש בהרשאה הזו כדי להפעיל סנכרון של האפליקציה \'אנשים\' עם חשבון כלשהו."</string>
<string name="permlab_readSyncStats" msgid="3747407238320105332">"קריאת הנתונים הסטטיסטיים של הסנכרון"</string>
- <string name="permdesc_readSyncStats" msgid="3867809926567379434">"מאפשר לאפליקציה לקרוא את סטטיסטיקת הסנכרון של חשבון, כולל היסטוריית אירועי הסנכרון וכמות הנתונים שסונכרנה."</string>
+ <string name="permdesc_readSyncStats" msgid="3867809926567379434">"מאפשרת לאפליקציה לקרוא את סטטיסטיקת הסנכרון של חשבון, כולל היסטוריית אירועי הסנכרון וכמות הנתונים שסונכרנה."</string>
<string name="permlab_sdcardRead" msgid="5791467020950064920">"קריאת התוכן של האחסון המשותף שלך"</string>
<string name="permdesc_sdcardRead" msgid="6872973242228240382">"מאפשר לאפליקציה לקרוא את התוכן של האחסון המשותף."</string>
<string name="permlab_sdcardWrite" msgid="4863021819671416668">"שינוי או מחיקה של תוכן האחסון המשותף שלך"</string>
@@ -665,21 +690,21 @@
<string name="permlab_register_sim_subscription" msgid="1653054249287576161">"רישום חיבורי Telecom SIM חדשים"</string>
<string name="permdesc_register_sim_subscription" msgid="4183858662792232464">"מאפשר לאפליקציה לרשום חיבורי Telecom SIM חדשים."</string>
<string name="permlab_register_call_provider" msgid="6135073566140050702">"רשום חיבורי Telecom חדשים"</string>
- <string name="permdesc_register_call_provider" msgid="4201429251459068613">"מאפשר לאפליקציה לרשום חיבורי תקשורת חדשים."</string>
+ <string name="permdesc_register_call_provider" msgid="4201429251459068613">"מאפשרת לאפליקציה לרשום חיבורי תקשורת חדשים."</string>
<string name="permlab_connection_manager" msgid="3179365584691166915">"ניהול חיבורי תקשורת"</string>
<string name="permdesc_connection_manager" msgid="1426093604238937733">"מאפשר לאפליקציה לנהל חיבורי תקשורת."</string>
<string name="permlab_bind_incall_service" msgid="5990625112603493016">"צור אינטראקציה עם מסך שיחה נכנסת"</string>
<string name="permdesc_bind_incall_service" msgid="4124917526967765162">"מאפשר לאפליקציה לקבוע מתי ואיך המשתמש יראה את מסך השיחה הנכנסת."</string>
<string name="permlab_bind_connection_service" msgid="5409268245525024736">"צור אינטראקציה עם שירותי טלפוניה"</string>
- <string name="permdesc_bind_connection_service" msgid="6261796725253264518">"מאפשר לאפליקציה ליצור אינטראקציה עם שירותי טלפוניה כדי לבצע/לקבל שיחות."</string>
- <string name="permlab_control_incall_experience" msgid="6436863486094352987">"ספק חווית משתמש של שיחה נכנסת"</string>
- <string name="permdesc_control_incall_experience" msgid="5896723643771737534">"מאפשר לאפליקציה לספק חוויית משתמש של שיחה נכנסת."</string>
+ <string name="permdesc_bind_connection_service" msgid="6261796725253264518">"מאפשרת לאפליקציה ליצור אינטראקציה עם שירותי טלפוניה כדי לבצע ולקבל שיחות."</string>
+ <string name="permlab_control_incall_experience" msgid="6436863486094352987">"סיפוק חווית שימוש של שיחה נכנסת"</string>
+ <string name="permdesc_control_incall_experience" msgid="5896723643771737534">"מאפשרת לאפליקציה לספק חוויית שימוש של שיחה נכנסת."</string>
<string name="permlab_readNetworkUsageHistory" msgid="8470402862501573795">"קריאת נתוני שימוש היסטוריים ברשת"</string>
<string name="permdesc_readNetworkUsageHistory" msgid="1112962304941637102">"מאפשר לאפליקציה לקרוא נתוני שימוש היסטוריים ברשת עבור רשתות ואפליקציות ספציפיות."</string>
<string name="permlab_manageNetworkPolicy" msgid="6872549423152175378">"נהל מדיניות רשת"</string>
- <string name="permdesc_manageNetworkPolicy" msgid="1865663268764673296">"מאפשר לאפליקציה לנהל מדיניות הרשת להגדיר כללים ספציפיים-לאפליקציה."</string>
- <string name="permlab_modifyNetworkAccounting" msgid="7448790834938749041">"שנה ניהול חשבונות של שימוש ברשת"</string>
- <string name="permdesc_modifyNetworkAccounting" msgid="5076042642247205390">"הרשאה זו מאפשרת לאפליקציה לשנות את אופן החישוב של נתוני שימוש ברשת מול כל אפליקציה. לא מיועד לשימוש באפליקציות רגילות."</string>
+ <string name="permdesc_manageNetworkPolicy" msgid="1865663268764673296">"מאפשרת לאפליקציה לנהל את מדיניות הרשת ולהגדיר כללים ספציפיים-לאפליקציה."</string>
+ <string name="permlab_modifyNetworkAccounting" msgid="7448790834938749041">"שינוי ניהול החשבונות של שימוש ברשת"</string>
+ <string name="permdesc_modifyNetworkAccounting" msgid="5076042642247205390">"ההרשאה הזו מאפשרת לאפליקציה לשנות את אופן החישוב של נתוני שימוש ברשת מול כל אפליקציה. לא מיועדת לשימוש באפליקציות רגילות."</string>
<string name="permlab_accessNotifications" msgid="7130360248191984741">"גישה להתראות"</string>
<string name="permdesc_accessNotifications" msgid="761730149268789668">"מאפשר לאפליקציה לאחזר, לבדוק ולמחוק התראות, כולל כאלה שפורסמו על ידי אפליקציות אחרות."</string>
<string name="permlab_bindNotificationListenerService" msgid="5848096702733262458">"איגוד לשירות של מאזין להתראות"</string>
@@ -705,7 +730,7 @@
<string name="permlab_bindCarrierServices" msgid="2395596978626237474">"איגוד לשירותי ספק"</string>
<string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"מאפשרת לבעלים לאגד לשירות ספק. לא נחוצה לאפליקציות רגילות בדרך כלל."</string>
<string name="permlab_access_notification_policy" msgid="5524112842876975537">"גישה אל \'נא לא להפריע\'"</string>
- <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"מאפשר לאפליקציה לקרוא ולכתוב את התצורה של \'נא לא להפריע\'."</string>
+ <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"מאפשרת לאפליקציה לקרוא ולכתוב את התצורה של התכונה \'נא לא להפריע\'."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"התחלת צפייה בהרשאות השימוש"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"מאפשרת לבעלים להפעיל את השימוש בהרשאות עבור אפליקציה מסוימת. הרשאה זו אף פעם לא נדרשת עבור אפליקציות רגילות."</string>
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"גישה לנתוני חיישנים בתדירות דגימה גבוהה"</string>
@@ -726,20 +751,20 @@
<string name="policylab_wipeData" msgid="1359485247727537311">"מחיקת כל הנתונים"</string>
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"מחיקה של נתוני הטאבלט ללא אזהרה, באמצעות איפוס לנתוני היצרן."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"מחיקה ללא אזהרה של נתוני מכשיר ה-Android TV באמצעות איפוס לנתוני היצרן."</string>
- <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"מחיקה של נתוני הטלפון, ללא אזהרה, על ידי ביצוע איפוס נתוני יצרן."</string>
+ <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"מחיקה של נתוני הטלפון, ללא אזהרה, על ידי ביצוע איפוס לנתוני היצרן."</string>
<string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"מחיקת נתוני משתמש"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"מחיקה ללא אזהרה של נתוני המשתמש הזה בטאבלט הזה."</string>
- <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"מחיקה ללא אזהרה של נתוני המשתמש הזה במכשיר ה-Android TV הזה."</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"מחיקה של נתוני המשתמש הזה במכשיר ה-Android TV, ללא אזהרה."</string>
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"מחיקה ללא אזהרה של נתוני המשתמש הזה בטלפון הזה."</string>
<string name="policylab_setGlobalProxy" msgid="215332221188670221">"הגדר את שרת ה-Proxy הכללי של המכשיר"</string>
<string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"הגדרה של שרת ה-proxy הגלובלי שבו ייעשה שימוש כשהמדיניות פועלת. רק הבעלים של המכשיר יכול להגדיר את שרת ה-proxy הגלובלי."</string>
<string name="policylab_expirePassword" msgid="6015404400532459169">"הגדרת תפוגה לסיסמת מסך הנעילה"</string>
<string name="policydesc_expirePassword" msgid="9136524319325960675">"שינוי התדירות לדרישת השינוי של הסיסמה, קוד הגישה או קו ביטול הנעילה של מסך הנעילה."</string>
- <string name="policylab_encryptedStorage" msgid="9012936958126670110">"הגדר הצפנת אחסון"</string>
- <string name="policydesc_encryptedStorage" msgid="1102516950740375617">"דרוש שנתוני אפליקציות מאוחסנות יהיו מוצפנים."</string>
+ <string name="policylab_encryptedStorage" msgid="9012936958126670110">"הגדרת הצפנה של אחסון"</string>
+ <string name="policydesc_encryptedStorage" msgid="1102516950740375617">"נדרש שנתונים של אפליקציות מאוחסנות יהיו מוצפנים."</string>
<string name="policylab_disableCamera" msgid="5749486347810162018">"השבתת מצלמות"</string>
<string name="policydesc_disableCamera" msgid="3204405908799676104">"מנע שימוש בכל המצלמות שבמכשיר."</string>
- <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"השבת חלק מהתכונות של נעילת המסך"</string>
+ <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"השבתת חלק מהתכונות של נעילת המסך"</string>
<string name="policydesc_disableKeyguardFeatures" msgid="6641673177041195957">"מניעת שימוש בחלק מהתכונות של נעילת המסך."</string>
<string-array name="phoneTypes">
<item msgid="8996339953292723951">"בית"</item>
@@ -803,9 +828,9 @@
<string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string>
<string name="phoneTypeWorkMobile" msgid="7522314392003565121">"נייד של העבודה"</string>
<string name="phoneTypeWorkPager" msgid="3748332310638505234">"זימונית מהעבודה"</string>
- <string name="phoneTypeAssistant" msgid="757550783842231039">"מסייע"</string>
+ <string name="phoneTypeAssistant" msgid="757550783842231039">"אסיסטנט"</string>
<string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string>
- <string name="eventTypeCustom" msgid="3257367158986466481">"מותאם אישית"</string>
+ <string name="eventTypeCustom" msgid="3257367158986466481">"בהתאמה אישית"</string>
<string name="eventTypeBirthday" msgid="7770026752793912283">"תאריך לידה"</string>
<string name="eventTypeAnniversary" msgid="4684702412407916888">"יום השנה"</string>
<string name="eventTypeOther" msgid="530671238533887997">"אחר"</string>
@@ -840,7 +865,7 @@
<string name="relationTypeBrother" msgid="7141662427379247820">"אח"</string>
<string name="relationTypeChild" msgid="9076258911292693601">"ילד"</string>
<string name="relationTypeDomesticPartner" msgid="7825306887697559238">"שותף לחיים"</string>
- <string name="relationTypeFather" msgid="3856225062864790596">"אב"</string>
+ <string name="relationTypeFather" msgid="3856225062864790596">"אבא"</string>
<string name="relationTypeFriend" msgid="3192092625893980574">"חבר"</string>
<string name="relationTypeManager" msgid="2272860813153171857">"מנהל"</string>
<string name="relationTypeMother" msgid="2331762740982699460">"אמא"</string>
@@ -859,7 +884,7 @@
<string name="keyguard_password_enter_puk_code" msgid="3112256684547584093">"יש להקליד את קוד ה-PUK ואת קוד האימות החדש"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="2825313071899938305">"קוד PUK"</string>
<string name="keyguard_password_enter_pin_prompt" msgid="5505434724229581207">"קוד אימות חדש"</string>
- <string name="keyguard_password_entry_touch_hint" msgid="4032288032993261520"><font size="17">"הקש כדי להקליד את הסיסמה"</font></string>
+ <string name="keyguard_password_entry_touch_hint" msgid="4032288032993261520"><font size="17">"יש להקיש כדי להקליד את הסיסמה"</font></string>
<string name="keyguard_password_enter_password_code" msgid="2751130557661643482">"הקלד סיסמה לביטול הנעילה"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="7792964196473964340">"יש להקליד קוד אימות לביטול הנעילה"</string>
<string name="keyguard_password_wrong_pin_code" msgid="8583732939138432793">"קוד אימות שגוי"</string>
@@ -867,24 +892,24 @@
<string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"מספר חירום"</string>
<string name="lockscreen_carrier_default" msgid="6192313772955399160">"אין שירות"</string>
<string name="lockscreen_screen_locked" msgid="7364905540516041817">"המסך נעול."</string>
- <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"לחץ על \'תפריט\' כדי לבטל את הנעילה או כדי לבצע שיחת חירום."</string>
- <string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"לחץ על \'תפריט\' כדי לבטל את הנעילה."</string>
- <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"שרטט קו לביטול נעילת המסך"</string>
+ <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"יש ללחוץ על \'תפריט\' כדי לבטל את הנעילה או כדי לבצע שיחת חירום."</string>
+ <string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"יש ללחוץ על \'תפריט\' כדי לבטל את הנעילה."</string>
+ <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"יש לשרטט קו לביטול נעילת המסך"</string>
<string name="lockscreen_emergency_call" msgid="7549683825868928636">"שיחת חירום"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"חזרה לשיחה"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"נכון!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"כדאי לנסות שוב"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"כדאי לנסות שוב"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"בטל את הנעילה לכל התכונות והנתונים"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"חרגת ממספר הניסיונות המרבי של זיהוי פנים"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"חרגת ממספר הניסיונות המרבי לשחרור נעילה על ידי זיהוי פנים"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"אין כרטיס SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"אין כרטיס SIM בטאבלט."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"אין כרטיס SIM במכשיר ה-Android TV."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="1408695081255172556">"אין כרטיס SIM בטלפון."</string>
- <string name="lockscreen_missing_sim_instructions" msgid="8473601862688263903">"הכנס כרטיס SIM."</string>
- <string name="lockscreen_missing_sim_instructions_long" msgid="3664999892038416334">"כרטיס ה-SIM חסר או שלא ניתן לקרוא אותו. הכנס כרטיס SIM."</string>
- <string name="lockscreen_permanent_disabled_sim_message_short" msgid="3812893366715730539">"לא ניתן להשתמש בכרטיס SIM זה."</string>
- <string name="lockscreen_permanent_disabled_sim_instructions" msgid="4358929052509450807">"כרטיס ה-SIM שלך הושבת לצמיתות.\nפנה לספק השירות האלחוטי שלך לקבלת כרטיס SIM אחר."</string>
+ <string name="lockscreen_missing_sim_instructions" msgid="8473601862688263903">"יש להכניס כרטיס SIM."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="3664999892038416334">"כרטיס ה-SIM חסר או שלא ניתן לקרוא אותו. יש להכניס כרטיס SIM."</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short" msgid="3812893366715730539">"לא ניתן להשתמש בכרטיס ה-SIM הזה."</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="4358929052509450807">"כרטיס ה-SIM שלך הושבת באופן סופי.\nיש לפנות לספק השירות האלחוטי שלך לקבלת כרטיס SIM אחר."</string>
<string name="lockscreen_transport_prev_description" msgid="2879469521751181478">"הרצועה הקודמת"</string>
<string name="lockscreen_transport_next_description" msgid="2931509904881099919">"הטראק הבא"</string>
<string name="lockscreen_transport_pause_description" msgid="6705284702135372494">"השהה"</string>
@@ -895,15 +920,15 @@
<string name="emergency_calls_only" msgid="3057351206678279851">"שיחות חירום בלבד"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"רשת נעולה"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"כרטיס SIM נעול באמצעות PUK."</string>
- <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"עיין במדריך למשתמש או פנה לשירות הלקוחות."</string>
+ <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"יש לעיין במדריך למשתמש או לפנות לשירות הלקוחות."</string>
<string name="lockscreen_sim_locked_message" msgid="3160196135801185938">"כרטיס ה-SIM נעול."</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="2286497117428409709">"מבטל נעילה של כרטיס SIM…"</string>
- <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nיש לנסות שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"הקלדת סיסמה שגויה <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים.\n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"הקלדת קוד גישה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים.\n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"שרטטת באופן שגוי את קו ביטול הנעילה <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטאבלט באמצעות פרטי הכניסה שלך ל-Google.\n\nנסה שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, יהיה צורך לבטל את נעילת הטאבלט באמצעות פרטי הכניסה שלך ל-Google.\n\nיש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את הנעילה של מכשיר ה-Android TV באמצעות כניסה לחשבון Google שלך.\n\n נסה שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטלפון באמצעות פרטי הכניסה שלך ל-Google.\n\n נסה שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, יהיה צורך לבטל את נעילת הטלפון באמצעות פרטי הכניסה שלך ל-Google.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"ביצעת <xliff:g id="NUMBER_0">%1$d</xliff:g> ניסיונות שגויים לביטול נעילת הטאבלט. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, הטאבלט יעבור איפוס לברירת המחדל של היצרן וכל נתוני המשתמש יאבדו."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"ניסית לבטל בצורה שגויה את הנעילה של מכשיר ה-Android TV <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, מכשיר ה-Android TV יעבור איפוס לברירת המחדל של היצרן וכל נתוני המשתמש יאבדו."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"ביצעת <xliff:g id="NUMBER_0">%1$d</xliff:g> ניסיונות שגויים לביטול נעילת הטלפון. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, הטלפון יעבור איפוס לברירת המחדל של היצרן וכל נתוני המשתמש יאבדו."</string>
@@ -912,15 +937,15 @@
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"ביצעת <xliff:g id="NUMBER">%d</xliff:g> ניסיונות שגויים לביטול נעילת הטלפון. הטלפון יעבור כעת איפוס לברירת המחדל של היצרן."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"נסה שוב בעוד <xliff:g id="NUMBER">%d</xliff:g> שניות."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"שכחת את קו ביטול הנעילה?"</string>
- <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"ביטול נעילת חשבון"</string>
+ <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"ביטול נעילת החשבון"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"בוצעו ניסיונות רבים מדי לשרטוט קו ביטול נעילה."</string>
<string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"כדי לבטל את הנעילה, עליך להיכנס באמצעות חשבון Google שלך."</string>
<string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"שם משתמש (אימייל)"</string>
<string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"סיסמה"</string>
<string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"כניסה"</string>
<string name="lockscreen_glogin_invalid_input" msgid="4369219936865697679">"שם משתמש או סיסמה לא חוקיים."</string>
- <string name="lockscreen_glogin_account_recovery_hint" msgid="1683405808525090649">"שכחת את שם המשתמש או הסיסמה?\nהיכנס לכתובת "<b>"google.com/accounts/recovery"</b></string>
- <string name="lockscreen_glogin_checking_password" msgid="2607271802803381645">"בודק..."</string>
+ <string name="lockscreen_glogin_account_recovery_hint" msgid="1683405808525090649">"שכחת את שם המשתמש או הסיסמה?\nאפשר להיכנס לכתובת "<b>"google.com/accounts/recovery"</b></string>
+ <string name="lockscreen_glogin_checking_password" msgid="2607271802803381645">"בבדיקה..."</string>
<string name="lockscreen_unlock_label" msgid="4648257878373307582">"בטל נעילה"</string>
<string name="lockscreen_sound_on_label" msgid="1660281470535492430">"קול פועל"</string>
<string name="lockscreen_sound_off_label" msgid="2331496559245450053">"ללא קול"</string>
@@ -943,7 +968,7 @@
<string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"סידור מחדש של Widgets התחיל."</string>
<string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"סידור מחדש של Widgets הסתיים."</string>
<string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> נמחק."</string>
- <string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"הרחב את אזור ביטול הנעילה."</string>
+ <string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"הרחבה של אזור ביטול הנעילה."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"ביטול נעילה באמצעות הסטה."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"ביטול נעילה על ידי שרטוט קו."</string>
<string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"ביטול נעילה באמצעות זיהוי פנים."</string>
@@ -964,12 +989,12 @@
<string name="factorytest_not_system" msgid="5658160199925519869">"הפעולה FACTORY_TEST נתמכת רק עבור חבילות שהותקנו ב-/system/app."</string>
<string name="factorytest_no_action" msgid="339252838115675515">"לא נמצאה חבילה המספקת את הפעולה FACTORY_TEST."</string>
<string name="factorytest_reboot" msgid="2050147445567257365">"אתחל מחדש"</string>
- <string name="js_dialog_title" msgid="7464775045615023241">"בדף שבכתובת \'<xliff:g id="TITLE">%s</xliff:g>\' כתוב כך:"</string>
+ <string name="js_dialog_title" msgid="7464775045615023241">"בדף שבכתובת \'<xliff:g id="TITLE">%s</xliff:g>\' כתוב:"</string>
<string name="js_dialog_title_default" msgid="3769524569903332476">"JavaScript"</string>
<string name="js_dialog_before_unload_title" msgid="7012587995876771246">"אישור ניווט"</string>
<string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"צא מדף זה"</string>
- <string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"הישאר בדף זה"</string>
- <string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nהאם אתה בטוח שברצונך לנווט אל מחוץ לדף זה?"</string>
+ <string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"להישאר בדף הזה"</string>
+ <string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nבטוח שברצונך לנווט אל מחוץ לדף הזה?"</string>
<string name="save_password_label" msgid="9161712335355510035">"אישור"</string>
<string name="double_tap_toast" msgid="7065519579174882778">"טיפ: הקש פעמיים כדי להגדיל ולהקטין."</string>
<string name="autofill_this_form" msgid="3187132440451621492">"מילוי אוטומטי"</string>
@@ -993,25 +1018,31 @@
<string name="autofill_emirate" msgid="2544082046790551168">"אמירות"</string>
<string name="permlab_readHistoryBookmarks" msgid="9102293913842539697">"קריאת סימניות והיסטוריית האינטרנט שלך"</string>
<string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"מאפשר לאפליקציה לקרוא את ההיסטוריה של כל כתובות האתרים שבהן הדפדפן ביקר, ואת כל ה-Bookmarks של הדפדפן. שים לב: דפדפני צד שלישי או אפליקציות אחרות עם יכולות לדפדוף באינטרנט אינם יכולים לאכוף אישור זה."</string>
- <string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"כתיבת סימניות והיסטוריית אינטרנט"</string>
+ <string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"כתיבת סימניות והיסטורייה של אתרים"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"מאפשר לאפליקציה לשנות את ההיסטוריה או ה-Bookmarks של הדפדפן המאוחסנים בטאבלט. הדבר עשוי לאפשר לאפליקציה למחוק או לשנות נתוני דפדפן. שים לב: אישור זה אינו ניתן לאכיפה על ידי דפדפני צד שלישי או אפליקציות אחרות בעלות יכולות גלישה באינטרנט."</string>
<string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"מאפשרת לאפליקציה לשנות את הסימניות או את היסטוריית הדפדפן השמורות במכשיר ה-Android TV. הרשאה זו עשויה לאפשר לאפליקציה למחוק או לשנות נתוני דפדפן. הערה: ייתכן שההרשאה לא תיושם על ידי דפדפנים של צד שלישי או על ידי אפליקציות אחרות עם יכולות גלישה באינטרנט."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"מאפשר לאפליקציה לשנות את ההיסטוריה או ה-Bookmarks של הדפדפן המאוחסנים בטלפון. הדבר עשוי לאפשר לאפליקציה למחוק או לשנות נתוני דפדפן. שים לב: אישור זה אינו ניתן לאכיפה על ידי דפדפני צד שלישי או אפליקציות אחרות בעלות יכולות גלישה באינטרנט."</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"הגדרת התראה"</string>
- <string name="permdesc_setAlarm" msgid="2185033720060109640">"מאפשר לאפליקציה להגדיר התראה באפליקציה מותקנת של שעון מעורר. אפליקציות מסוימות של שעון מעורר אינן מיישמות תכונה זו."</string>
- <string name="permlab_addVoicemail" msgid="4770245808840814471">"הוסף דואר קולי"</string>
- <string name="permdesc_addVoicemail" msgid="5470312139820074324">"מאפשר לאפליקציה להוסיף הודעות לתיבת הדואר הקולי."</string>
+ <string name="permdesc_setAlarm" msgid="2185033720060109640">"מאפשרת לאפליקציה להגדיר התראה באפליקציה מותקנת של שעון מעורר. אפליקציות מסוימות של שעון מעורר אינן מיישמות את התכונה הזו."</string>
+ <string name="permlab_addVoicemail" msgid="4770245808840814471">"הוספה של דואר קולי"</string>
+ <string name="permdesc_addVoicemail" msgid="5470312139820074324">"מאפשרת לאפליקציה להוסיף הודעות לתיבת הדואר הקולי."</string>
<string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"שינוי הרשאות המיקום הגיאוגרפי של הדפדפן"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"מאפשר לאפליקציה לשנות את הרשאות המיקום הגיאוגרפי של הדפדפן. אפליקציות זדוניות עלולות להשתמש בכך כדי לאפשר משלוח של פרטי מיקום לאתרים זדוניים אחרים."</string>
<string name="save_password_message" msgid="2146409467245462965">"האם ברצונך שהדפדפן יזכור סיסמה זו?"</string>
<string name="save_password_notnow" msgid="2878327088951240061">"לא עכשיו"</string>
- <string name="save_password_remember" msgid="6490888932657708341">"זכור"</string>
+ <string name="save_password_remember" msgid="6490888932657708341">"כן, לשמור"</string>
<string name="save_password_never" msgid="6776808375903410659">"אף פעם"</string>
<string name="open_permission_deny" msgid="5136793905306987251">"אין לך הרשאה לפתוח דף זה."</string>
<string name="text_copied" msgid="2531420577879738860">"הטקסט הועתק ללוח."</string>
<string name="copied" msgid="4675902854553014676">"ההעתקה בוצעה"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"האפליקציה <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> הודבקה מ-<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"האפליקציה <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> הודבקה מהלוח"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"עוד"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"תפריט+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1031,7 +1062,7 @@
<string name="searchview_description_submit" msgid="6771060386117334686">"שליחת שאילתה"</string>
<string name="searchview_description_voice" msgid="42360159504884679">"חיפוש קולי"</string>
<string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"האם להפעיל את התכונה \'גילוי באמצעות מגע\'?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> רוצה להפעיל את התכונה \'חקור על ידי מגע\'. כאשר התכונה \'חקור על ידי מגע\' מופעלת, אתה יכול לשמוע או לראות תיאורים של הפריטים שעליהם אצבעך מונחת או לקיים אינטראקציה עם הטאבלט באמצעות תנועות אצבע."</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> רוצה להפעיל את התכונה \'גילוי באמצעות מגע\'. כאשר התכונה הזו מופעלת, אפשר לשמוע או לראות תיאורים של הפריטים שעליהם הנחת את האצבע או לקיים אינטראקציה עם הטאבלט באמצעות תנועות."</string>
<string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> רוצה להפעיל את התכונה \'חקור על ידי מגע\'. כאשר התכונה \'חקור על ידי מגע\' מופעלת, אתה יכול לשמוע או לראות תיאורים של הפריטים שעליהם אצבעך מונחת או לקיים אינטראקציה עם הטלפון באמצעות תנועות אצבע."</string>
<string name="oneMonthDurationPast" msgid="4538030857114635777">"לפני חודש אחד"</string>
<string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"לפני חודש אחד"</string>
@@ -1039,7 +1070,7 @@
<item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> הימים האחרונים</item>
<item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> הימים האחרונים</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> הימים האחרונים</item>
- <item quantity="one">יום <xliff:g id="COUNT_0">%d</xliff:g> אחרון</item>
+ <item quantity="one">היום האחרון (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
</plurals>
<string name="last_month" msgid="1528906781083518683">"בחודש שעבר"</string>
<string name="older" msgid="1645159827884647400">"ישן יותר"</string>
@@ -1081,7 +1112,7 @@
<item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> שנים</item>
<item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> שנים</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> שנים</item>
- <item quantity="one">שנה <xliff:g id="COUNT_0">%d</xliff:g></item>
+ <item quantity="one">שנה אחת (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
</plurals>
<plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440">
<item quantity="two">בעוד <xliff:g id="COUNT_1">%d</xliff:g> דקות</item>
@@ -1135,7 +1166,7 @@
<item quantity="two">בעוד <xliff:g id="COUNT_1">%d</xliff:g> דקות</item>
<item quantity="many">בעוד <xliff:g id="COUNT_1">%d</xliff:g> דקות</item>
<item quantity="other">בעוד <xliff:g id="COUNT_1">%d</xliff:g> דקות</item>
- <item quantity="one">בעוד <xliff:g id="COUNT_0">%d</xliff:g> דקה</item>
+ <item quantity="one">בעוד דקה אחת (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
</plurals>
<plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959">
<item quantity="two">בעוד <xliff:g id="COUNT_1">%d</xliff:g> שעות</item>
@@ -1156,8 +1187,8 @@
<item quantity="one">בעוד שנה <xliff:g id="COUNT_0">%d</xliff:g></item>
</plurals>
<string name="VideoView_error_title" msgid="5750686717225068016">"בעיה בווידאו"</string>
- <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"סרטון זה אינו חוקי להעברה כמדיה זורמת למכשיר זה."</string>
- <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"לא ניתן להפעיל סרטון זה."</string>
+ <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"לא ניתן להעביר את הסרטון הזה בסטרימינג למכשיר."</string>
+ <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"לא ניתן להפעיל את הסרטון הזה."</string>
<string name="VideoView_error_button" msgid="5138809446603764272">"אישור"</string>
<string name="relative_time" msgid="8572030016028033243">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="noon" msgid="8365974533050605886">"צהריים"</string>
@@ -1166,15 +1197,15 @@
<string name="Midnight" msgid="8176019203622191377">"חצות"</string>
<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="selectAll" msgid="1532369154488982046">"בחירת הכול"</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>
- <string name="paste_as_plain_text" msgid="7664800665823182587">"הדבק כטקסט פשוט"</string>
- <string name="replace" msgid="7842675434546657444">"החלף..."</string>
+ <string name="paste_as_plain_text" msgid="7664800665823182587">"הדבקה כטקסט פשוט"</string>
+ <string name="replace" msgid="7842675434546657444">"החלפה..."</string>
<string name="delete" msgid="1514113991712129054">"מחיקה"</string>
- <string name="copyUrl" msgid="6229645005987260230">"העתק כתובת אתר"</string>
+ <string name="copyUrl" msgid="6229645005987260230">"העתקת כתובת URL"</string>
<string name="selectTextMode" msgid="3225108910999318778">"בחר טקסט"</string>
<string name="undo" msgid="3175318090002654673">"ביטול"</string>
<string name="redo" msgid="7231448494008532233">"בצע מחדש"</string>
@@ -1186,15 +1217,15 @@
<string name="editTextMenuTitle" msgid="857666911134482176">"פעולות טקסט"</string>
<string name="low_internal_storage_view_title" msgid="9024241779284783414">"מקום האחסון עומד להיגמר"</string>
<string name="low_internal_storage_view_text" msgid="8172166728369697835">"ייתכן שפונקציות מערכת מסוימות לא יפעלו"</string>
- <string name="low_internal_storage_view_text_no_boot" msgid="7368968163411251788">"אין מספיק שטח אחסון עבור המערכת. ודא שיש לך שטח פנוי בגודל 250MB התחל שוב."</string>
- <string name="app_running_notification_title" msgid="8985999749231486569">"<xliff:g id="APP_NAME">%1$s</xliff:g> פועל"</string>
+ <string name="low_internal_storage_view_text_no_boot" msgid="7368968163411251788">"אין מספיק מקום אחסון עבור המערכת. עליך לוודא שיש לך מקום פנוי בנפח של 250MB ולהתחיל שוב."</string>
+ <string name="app_running_notification_title" msgid="8985999749231486569">"אפליקציית <xliff:g id="APP_NAME">%1$s</xliff:g> פועלת"</string>
<string name="app_running_notification_text" msgid="5120815883400228566">"הקש לקבלת מידע נוסף או כדי לעצור את האפליקציה."</string>
<string name="ok" msgid="2646370155170753815">"אישור"</string>
<string name="cancel" msgid="6908697720451760115">"ביטול"</string>
<string name="yes" msgid="9069828999585032361">"אישור"</string>
<string name="no" msgid="5122037903299899715">"ביטול"</string>
<string name="dialog_alert_title" msgid="651856561974090712">"זהירות"</string>
- <string name="loading" msgid="3138021523725055037">"טוען..."</string>
+ <string name="loading" msgid="3138021523725055037">"בטעינה..."</string>
<string name="capital_on" msgid="2770685323900821829">"מופעל"</string>
<string name="capital_off" msgid="7443704171014626777">"כבוי"</string>
<string name="checked" msgid="9179896827054513119">"מסומן"</string>
@@ -1204,15 +1235,15 @@
<string name="whichApplication" msgid="5432266899591255759">"השלמת פעולה באמצעות"</string>
<string name="whichApplicationNamed" msgid="6969946041713975681">"להשלמת הפעולה באמצעות %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"השלם פעולה"</string>
- <string name="whichViewApplication" msgid="5733194231473132945">"פתח באמצעות"</string>
+ <string name="whichViewApplication" msgid="5733194231473132945">"פתיחה באמצעות"</string>
<string name="whichViewApplicationNamed" msgid="415164730629690105">"פתח באמצעות %1$s"</string>
- <string name="whichViewApplicationLabel" msgid="7367556735684742409">"פתח"</string>
+ <string name="whichViewApplicationLabel" msgid="7367556735684742409">"פתיחה"</string>
<string name="whichOpenHostLinksWith" msgid="7645631470199397485">"פתיחת קישורים של <xliff:g id="HOST">%1$s</xliff:g> באמצעות"</string>
<string name="whichOpenLinksWith" msgid="1120936181362907258">"פתיחת קישורים באמצעות"</string>
<string name="whichOpenLinksWithApp" msgid="6917864367861910086">"פתיחת קישורים באמצעות <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
<string name="whichOpenHostLinksWithApp" msgid="2401668560768463004">"פתיחת קישורים של <xliff:g id="HOST">%1$s</xliff:g> באמצעות <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
<string name="whichGiveAccessToApplicationLabel" msgid="7805857277166106236">"הענקת גישה"</string>
- <string name="whichEditApplication" msgid="6191568491456092812">"ערוך באמצעות"</string>
+ <string name="whichEditApplication" msgid="6191568491456092812">"עריכה באמצעות"</string>
<string name="whichEditApplicationNamed" msgid="8096494987978521514">"עריכה באמצעות %1$s"</string>
<string name="whichEditApplicationLabel" msgid="1463288652070140285">"עריכה"</string>
<string name="whichSendApplication" msgid="4143847974460792029">"שיתוף"</string>
@@ -1220,28 +1251,28 @@
<string name="whichSendApplicationLabel" msgid="7467813004769188515">"שתף"</string>
<string name="whichSendToApplication" msgid="77101541959464018">"שליחה באמצעות"</string>
<string name="whichSendToApplicationNamed" msgid="3385686512014670003">"שליחה באמצעות %1$s"</string>
- <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"שלח"</string>
+ <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"שליחה"</string>
<string name="whichHomeApplication" msgid="8276350727038396616">"בחר אפליקציה שתשמש כדף הבית"</string>
<string name="whichHomeApplicationNamed" msgid="5855990024847433794">"השתמש ב-%1$s כדף הבית"</string>
<string name="whichHomeApplicationLabel" msgid="8907334282202933959">"צלם תמונה"</string>
<string name="whichImageCaptureApplication" msgid="2737413019463215284">"צלם תמונה באמצעות"</string>
<string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"צילום תמונה באמצעות %1$s"</string>
<string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"צלם תמונה"</string>
- <string name="alwaysUse" msgid="3153558199076112903">"השתמש כברירת מחדל עבור פעולה זו."</string>
+ <string name="alwaysUse" msgid="3153558199076112903">"שימוש כברירת מחדל עבור הפעולה הזו."</string>
<string name="use_a_different_app" msgid="4987790276170972776">"השתמש באפליקציה אחרת"</string>
<string name="clearDefaultHintMsg" msgid="1325866337702524936">"נקה את הגדרת המחדל ב\'הגדרות מערכת\' < Google Apps < \'הורדות\'."</string>
<string name="chooseActivity" msgid="8563390197659779956">"בחירת פעולה"</string>
- <string name="chooseUsbActivity" msgid="2096269989990986612">"בחר אפליקציה עבור התקן ה-USB"</string>
+ <string name="chooseUsbActivity" msgid="2096269989990986612">"בחירת אפליקציה עבור התקן ה-USB"</string>
<string name="noApplications" msgid="1186909265235544019">"אין אפליקציות שיכולות לבצע את הפעולה הזו."</string>
<string name="aerr_application" msgid="4090916809370389109">"האפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> הפסיקה"</string>
<string name="aerr_process" msgid="4268018696970966407">"התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הפסיק"</string>
<string name="aerr_application_repeated" msgid="7804378743218496566">"האפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> נעצרת שוב ושוב"</string>
<string name="aerr_process_repeated" msgid="1153152413537954974">"האפליקציה <xliff:g id="PROCESS">%1$s</xliff:g> נעצרת שוב ושוב"</string>
- <string name="aerr_restart" msgid="2789618625210505419">"פתח שוב את האפליקציה"</string>
+ <string name="aerr_restart" msgid="2789618625210505419">"פתיחת האפליקציה מחדש"</string>
<string name="aerr_report" msgid="3095644466849299308">"שליחת משוב"</string>
<string name="aerr_close" msgid="3398336821267021852">"סגירה"</string>
<string name="aerr_mute" msgid="2304972923480211376">"השתק עד הפעלה מחדש של המכשיר"</string>
- <string name="aerr_wait" msgid="3198677780474548217">"המתן"</string>
+ <string name="aerr_wait" msgid="3198677780474548217">"להמתין"</string>
<string name="aerr_close_app" msgid="8318883106083050970">"סגור את האפליקציה"</string>
<string name="anr_title" msgid="7290329487067300120"></string>
<string name="anr_activity_application" msgid="8121716632960340680">"האפליקציה <xliff:g id="APPLICATION">%2$s</xliff:g> אינה מגיבה"</string>
@@ -1257,7 +1288,7 @@
<string name="launch_warning_original" msgid="3332206576800169626">"אפליקציית <xliff:g id="APP_NAME">%1$s</xliff:g> הופעלה במקור."</string>
<string name="screen_compat_mode_scale" msgid="8627359598437527726">"שינוי קנה-מידה"</string>
<string name="screen_compat_mode_show" msgid="5080361367584709857">"להציג תמיד"</string>
- <string name="screen_compat_mode_hint" msgid="4032272159093750908">"אפשר תכונה זו מחדש ב\'הגדרות מערכת\' < Google Apps < \'הורדות\'."</string>
+ <string name="screen_compat_mode_hint" msgid="4032272159093750908">"אפשר להפעיל מחדש את התכונה הזו ב\'הגדרות מערכת\' < Google Apps < \'הורדות\'."</string>
<string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> אינו תומך בהגדרת הגודל הנוכחית של התצוגה, והתנהגותו עשויה להיות בלתי צפויה."</string>
<string name="unsupported_display_size_show" msgid="980129850974919375">"הצג תמיד"</string>
<string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g> נבנתה לגרסה לא תואמת של מערכת ההפעלה של Android ועלולה להתנהג באופן לא צפוי. ייתכן שקיימת גרסה מעודכנת של האפליקציה."</string>
@@ -1270,15 +1301,15 @@
<string name="android_upgrading_title" product="device" msgid="6774767702998149762">"הפעלת המכשיר מתחילה…"</string>
<string name="android_start_title" product="default" msgid="4036708252778757652">"הפעלת הטלפון מתחילה…"</string>
<string name="android_start_title" product="automotive" msgid="7917984412828168079">"הפעלת Android מתחילה…"</string>
- <string name="android_start_title" product="tablet" msgid="4429767260263190344">"הפעלת הטאבלט מתחילה…"</string>
+ <string name="android_start_title" product="tablet" msgid="4429767260263190344">"הטאבלט בתהליך הפעלה…"</string>
<string name="android_start_title" product="device" msgid="6967413819673299309">"הפעלת המכשיר מתחילה…"</string>
<string name="android_upgrading_fstrim" msgid="3259087575528515329">"מתבצעת אופטימיזציה של האחסון."</string>
<string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"עדכון המערכת לקראת סיום…"</string>
<string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> מבצעת שדרוג…"</string>
- <string name="android_upgrading_apk" msgid="1339564803894466737">"מבצע אופטימיזציה של אפליקציה <xliff:g id="NUMBER_0">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
- <string name="android_preparing_apk" msgid="589736917792300956">"מכין את <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
+ <string name="android_upgrading_apk" msgid="1339564803894466737">"מתבצעת אופטימיזציה של אפליקציה <xliff:g id="NUMBER_0">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <string name="android_preparing_apk" msgid="589736917792300956">"המערכת מכינה את <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"מפעיל אפליקציות."</string>
- <string name="android_upgrading_complete" msgid="409800058018374746">"מסיים אתחול."</string>
+ <string name="android_upgrading_complete" msgid="409800058018374746">"תהליך האתחול בשלבי סיום."</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> פועל"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"יש להקיש כדי לחזור למשחק"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"בחירת משחק"</string>
@@ -1315,20 +1346,20 @@
<string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"צלילי התראה"</string>
<string name="ringtone_picker_title_notification" msgid="6387191794719608122">"צלילי התראה"</string>
<string name="ringtone_unknown" msgid="5059495249862816475">"לא ידוע"</string>
- <string name="wifi_available_sign_in" msgid="381054692557675237">"היכנס לרשת Wi-Fi"</string>
- <string name="network_available_sign_in" msgid="1520342291829283114">"היכנס לרשת"</string>
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"כניסה לרשת Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"כניסה לרשת"</string>
<!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
<skip />
<string name="wifi_no_internet" msgid="1386911698276448061">"ל-<xliff:g id="NETWORK_SSID">%1$s</xliff:g> אין גישה לאינטרנט"</string>
- <string name="wifi_no_internet_detailed" msgid="634938444133558942">"הקש לקבלת אפשרויות"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"יש להקיש לצפייה באפשרויות"</string>
<string name="mobile_no_internet" msgid="4014455157529909781">"לרשת הסלולרית אין גישה לאינטרנט"</string>
<string name="other_networks_no_internet" msgid="6698711684200067033">"לרשת אין גישה לאינטרנט"</string>
<string name="private_dns_broken_detailed" msgid="3709388271074611847">"לא ניתן לגשת לשרת DNS הפרטי"</string>
<string name="network_partial_connectivity" msgid="4791024923851432291">"הקישוריות של <xliff:g id="NETWORK_SSID">%1$s</xliff:g> מוגבלת"</string>
- <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"כדי להתחבר למרות זאת יש להקיש"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"יש להקיש כדי להתחבר בכל זאת"</string>
<string name="network_switch_metered" msgid="1531869544142283384">"מעבר אל <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
<string name="network_switch_metered_detail" msgid="1358296010128405906">"המכשיר משתמש ברשת <xliff:g id="NEW_NETWORK">%1$s</xliff:g> כשלרשת <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> אין גישה לאינטרנט. עשויים לחול חיובים."</string>
- <string name="network_switch_metered_toast" msgid="501662047275723743">"עבר מרשת <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> לרשת <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"בוצע מעבר מרשת <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> לרשת <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
<string-array name="network_switch_type_name">
<item msgid="2255670471736226365">"חבילת גלישה"</item>
<item msgid="5520925862115353992">"Wi-Fi"</item>
@@ -1337,14 +1368,14 @@
<item msgid="9177085807664964627">"VPN"</item>
</string-array>
<string name="network_switch_type_name_unknown" msgid="3665696841646851068">"סוג רשת לא מזוהה"</string>
- <string name="accept" msgid="5447154347815825107">"קבל"</string>
+ <string name="accept" msgid="5447154347815825107">"אישור"</string>
<string name="decline" msgid="6490507610282145874">"דחה"</string>
<string name="select_character" msgid="3352797107930786979">"הוסף תו"</string>
- <string name="sms_control_title" msgid="4748684259903148341">"שולח הודעות SMS"</string>
- <string name="sms_control_message" msgid="6574313876316388239">"<b> <xliff:g id="APP_NAME">%1$s</xliff:g> </ b> שולח מספר רב של הודעות SMS. האם ברצונך לאפשר לאפליקציה זו להמשיך לשלוח הודעות?"</string>
+ <string name="sms_control_title" msgid="4748684259903148341">"מתבצעת שליחה של הודעות SMS"</string>
+ <string name="sms_control_message" msgid="6574313876316388239">"האפליקציה <b> <xliff:g id="APP_NAME">%1$s</xliff:g> </ b> שולחת מספר רב של הודעות SMS. האם לאפשר לאפליקציה הזו להמשיך לשלוח הודעות?"</string>
<string name="sms_control_yes" msgid="4858845109269524622">"כן, זה בסדר"</string>
<string name="sms_control_no" msgid="4845717880040355570">"עדיף שלא"</string>
- <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> רוצה לשלוח הודעה אל <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
+ <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"אפליקציית <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> רוצה לשלוח הודעה אל <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
<string name="sms_short_code_details" msgid="2723725738333388351">"הדבר "<b>"עלול לגרום לחיובים"</b>" בחשבון המכשיר הנייד שלך."</string>
<string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"הדבר יגרום לחיובים בחשבון המכשיר הנייד שלך."</b></string>
<string name="sms_short_code_confirm_allow" msgid="920477594325526691">"שלח"</string>
@@ -1354,7 +1385,7 @@
<string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"אפשר תמיד"</string>
<string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"לעולם אל תאפשר"</string>
<string name="sim_removed_title" msgid="5387212933992546283">"כרטיס ה-SIM הוסר"</string>
- <string name="sim_removed_message" msgid="9051174064474904617">"הרשת הסלולרית לא תהיה זמינה עד שתפעיל מחדש לאחר הכנסת כרטיס SIM חוקי."</string>
+ <string name="sim_removed_message" msgid="9051174064474904617">"הרשת הסלולרית לא תהיה זמינה עד שתבוצע הפעלה מחדש לאחר הכנסת כרטיס SIM חוקי."</string>
<string name="sim_done_button" msgid="6464250841528410598">"סיום"</string>
<string name="sim_added_title" msgid="7930779986759414595">"כרטיס ה-SIM נוסף"</string>
<string name="sim_added_message" msgid="6602906609509958680">"הפעל מחדש את המכשיר כדי לגשת אל הרשת הסלולרית."</string>
@@ -1362,21 +1393,21 @@
<string name="install_carrier_app_notification_title" msgid="5712723402213090102">"הפעלה של השירות הסלולרי"</string>
<string name="install_carrier_app_notification_text" msgid="2781317581274192728">"הורדה של אפליקציית הספק כדי להפעיל את כרטיס ה-SIM החדש"</string>
<string name="install_carrier_app_notification_text_app_name" msgid="4086877327264106484">"ניתן להוריד את האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> כדי להפעיל את כרטיס ה-SIM החדש"</string>
- <string name="install_carrier_app_notification_button" msgid="6257740533102594290">"הורדת אפליקציה"</string>
+ <string name="install_carrier_app_notification_button" msgid="6257740533102594290">"להורדת האפליקציה"</string>
<string name="carrier_app_notification_title" msgid="5815477368072060250">"ה-SIM החדש הוכנס"</string>
- <string name="carrier_app_notification_text" msgid="6567057546341958637">"הקש כדי להגדיר"</string>
+ <string name="carrier_app_notification_text" msgid="6567057546341958637">"יש להקיש כדי להגדיר"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"הגדרת שעה"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"הגדרת תאריך"</string>
<string name="date_time_set" msgid="4603445265164486816">"הגדרה"</string>
<string name="date_time_done" msgid="8363155889402873463">"סיום"</string>
<string name="perms_new_perm_prefix" msgid="6984556020395757087"><font size="12" fgcolor="#ff33b5e5">"חדש: "</font></string>
- <string name="perms_description_app" msgid="2747752389870161996">"מטעם <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
- <string name="no_permissions" msgid="5729199278862516390">"לא דרושים אישורים"</string>
+ <string name="perms_description_app" msgid="2747752389870161996">"מאת <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+ <string name="no_permissions" msgid="5729199278862516390">"לא נדרשות הרשאות"</string>
<string name="perm_costs_money" msgid="749054595022779685">"פעולה זו עשויה לחייב אותך בכסף:"</string>
<string name="dlg_ok" msgid="5103447663504839312">"אישור"</string>
<string name="usb_charging_notification_title" msgid="1674124518282666955">"טעינת המכשיר הזה באמצעות USB"</string>
<string name="usb_supplying_notification_title" msgid="5378546632408101811">"טעינת המכשיר המחובר באמצעות USB"</string>
- <string name="usb_mtp_notification_title" msgid="1065989144124499810">"העברת קבצים ב-USB מופעלת"</string>
+ <string name="usb_mtp_notification_title" msgid="1065989144124499810">"האפשרות להעברת קבצים ב-USB מופעלת"</string>
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP באמצעות USB מופעל"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"שיתוף אינטרנט בין מכשירים באמצעות USB מופעל"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI באמצעות USB מופעל"</string>
@@ -1402,12 +1433,12 @@
<string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"עיבוד דוח על באג..."</string>
<string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"האם לשתף דוח על באג?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"שיתוף דוח על באג…"</string>
- <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"מנהל המערכת ביקש דוח על באג כדי לסייע בפתרון בעיות במכשיר זה. ייתכן שאפליקציות ונתונים ישותפו."</string>
+ <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"מנהל המערכת ביקש דוח על באג כדי לסייע בפתרון בעיות במכשיר הזה. ייתכן שאפליקציות ונתונים ישותפו."</string>
<string name="share_remote_bugreport_action" msgid="7630880678785123682">"שתף"</string>
<string name="decline_remote_bugreport_action" msgid="4040894777519784346">"עדיף שלא"</string>
<string name="select_input_method" msgid="3971267998568587025">"בחר שיטת הזנה"</string>
<string name="show_ime" msgid="6406112007347443383">"להשאיר במסך בזמן שהמקלדת הפיזית פעילה"</string>
- <string name="hardware" msgid="1800597768237606953">"הצג מקלדת וירטואלית"</string>
+ <string name="hardware" msgid="1800597768237606953">"הצגת מקלדת וירטואלית"</string>
<string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"הגדרת מקלדת פיזית"</string>
<string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"הקש כדי לבחור שפה ופריסה"</string>
<string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1434,7 +1465,7 @@
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"ייתכן שיהיה צורך לפרמט מחדש את המכשיר. יש להקיש כדי להוציא את המדיה."</string>
<string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> לא נתמך"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"המדיה <xliff:g id="NAME">%s</xliff:g> לא פועלת"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"מכשיר זה אינו תומך ב-<xliff:g id="NAME">%s</xliff:g> זה. הקש כדי להגדיר בפורמט נתמך."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"אין תמיכה ב-<xliff:g id="NAME">%s</xliff:g> במכשיר הזה. יש להקיש כדי לבצע הגדרה בפורמט נתמך."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"יש לבחור כדי להגדיר את <xliff:g id="NAME">%s</xliff:g> בפורמט נתמך."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"ייתכן שיהיה צורך לפרמט מחדש את המכשיר"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> הוסר באופן בלתי צפוי"</string>
@@ -1444,51 +1475,51 @@
<string name="ext_media_unmounting_notification_title" msgid="4147986383917892162">"הוצאה של <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"אין להסיר"</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"הגדרה"</string>
- <string name="ext_media_unmount_action" msgid="966992232088442745">"הוצא"</string>
- <string name="ext_media_browse_action" msgid="344865351947079139">"גלה"</string>
+ <string name="ext_media_unmount_action" msgid="966992232088442745">"הוצאה"</string>
+ <string name="ext_media_browse_action" msgid="344865351947079139">"עיון במדיה"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"החלפת פלט"</string>
- <string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> חסר"</string>
+ <string name="ext_media_missing_title" msgid="3209472091220515046">"חסר: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_missing_message" msgid="4408988706227922909">"יש להכניס שוב את ההתקן"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"מעביר את <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="ext_media_move_title" msgid="2682741525619033637">"מעביר נתונים"</string>
+ <string name="ext_media_move_title" msgid="2682741525619033637">"מתבצעת העברה של נתונים"</string>
<string name="ext_media_move_success_title" msgid="4901763082647316767">"העברת התוכן הסתיימה"</string>
<string name="ext_media_move_success_message" msgid="9159542002276982979">"התוכן הועבר אל <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_failure_title" msgid="3184577479181333665">"לא ניתן היה להעביר תוכן"</string>
<string name="ext_media_move_failure_message" msgid="4197306718121869335">"יש לנסות שוב להעביר את התוכן"</string>
<string name="ext_media_status_removed" msgid="241223931135751691">"הוסר"</string>
- <string name="ext_media_status_unmounted" msgid="8145812017295835941">"הוצא"</string>
+ <string name="ext_media_status_unmounted" msgid="8145812017295835941">"בוצעה הוצאה"</string>
<string name="ext_media_status_checking" msgid="159013362442090347">"בודק…"</string>
<string name="ext_media_status_mounted" msgid="3459448555811203459">"מוכן"</string>
<string name="ext_media_status_mounted_ro" msgid="1974809199760086956">"לקריאה בלבד"</string>
<string name="ext_media_status_bad_removal" msgid="508448566481406245">"הוסר בצורה לא בטוחה"</string>
<string name="ext_media_status_unmountable" msgid="7043574843541087748">"פגום"</string>
<string name="ext_media_status_unsupported" msgid="5460509911660539317">"לא נתמך"</string>
- <string name="ext_media_status_ejecting" msgid="7532403368044013797">"מוציא…"</string>
+ <string name="ext_media_status_ejecting" msgid="7532403368044013797">"מתבצעת הוצאה…"</string>
<string name="ext_media_status_formatting" msgid="774148701503179906">"מפרמט…"</string>
<string name="ext_media_status_missing" msgid="6520746443048867314">"לא הוכנס"</string>
<string name="activity_list_empty" msgid="4219430010716034252">"לא נמצאו פעילויות תואמות."</string>
<string name="permlab_route_media_output" msgid="8048124531439513118">"ניתוב פלט מדיה"</string>
<string name="permdesc_route_media_output" msgid="1759683269387729675">"מאפשר לאפליקציה לנתב פלט מדיה למכשירים חיצוניים אחרים."</string>
<string name="permlab_readInstallSessions" msgid="7279049337895583621">"קריאת פעילות התקנה"</string>
- <string name="permdesc_readInstallSessions" msgid="4012608316610763473">"מאפשר לאפליקציה לקרוא הפעלות התקנה. הרשאה זו מאפשרת לה לראות פרטים על התקנות פעילות של חבילות."</string>
+ <string name="permdesc_readInstallSessions" msgid="4012608316610763473">"מאפשרת לאפליקציה לקרוא פעילויות התקנה. ההרשאה הזו מאפשרת לה לראות פרטים על התקנות פעילות של חבילות."</string>
<string name="permlab_requestInstallPackages" msgid="7600020863445351154">"בקשה להתקנת חבילות"</string>
<string name="permdesc_requestInstallPackages" msgid="3969369278325313067">"מתיר לאפליקציה לבקש התקנה של חבילות."</string>
<string name="permlab_requestDeletePackages" msgid="2541172829260106795">"בקשה למחוק חבילות"</string>
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"מתיר לאפליקציה לבקש מחיקה של חבילות."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"בקשה להתעלם מאופטימיזציות של הסוללה"</string>
- <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"מאפשר לאפליקציה לבקש רשות להתעלם מאופטימיזציות של הסוללה לאפליקציה הזו."</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"מאפשרת לאפליקציה לבקש רשות להתעלם מאופטימיזציות של הסוללה לאפליקציה הזו."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"הקש פעמיים לבקרת מרחק מתצוגה"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"לא ניתן להוסיף widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"התחל"</string>
<string name="ime_action_search" msgid="4501435960587287668">"חיפוש"</string>
- <string name="ime_action_send" msgid="8456843745664334138">"שלח"</string>
+ <string name="ime_action_send" msgid="8456843745664334138">"שליחה"</string>
<string name="ime_action_next" msgid="4169702997635728543">"הבא"</string>
<string name="ime_action_done" msgid="6299921014822891569">"סיום"</string>
<string name="ime_action_previous" msgid="6548799326860401611">"הקודם"</string>
<string name="ime_action_default" msgid="8265027027659800121">"בצע"</string>
<string name="dial_number_using" msgid="6060769078933953531">"חיוג למספר\nבאמצעות <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="6200708808003692594">"צור איש קשר\nבאמצעות <xliff:g id="NUMBER">%s</xliff:g>"</string>
- <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"האפליקציות הבאות מבקשות אישור לגשת לחשבונך, כעת ובעתיד."</string>
+ <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"האפליקציות הבאות מבקשות אישור לגשת לחשבון שלך, עכשיו ובעתיד."</string>
<string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"לאפשר את הבקשה הזו?"</string>
<string name="grant_permissions_header_text" msgid="3420736827804657201">"בקשת גישה"</string>
<string name="allow" msgid="6195617008611933762">"כן, זה בסדר"</string>
@@ -1501,7 +1532,7 @@
<string name="sync_binding_label" msgid="469249309424662147">"סנכרון"</string>
<string name="accessibility_binding_label" msgid="1974602776545801715">"נגישות"</string>
<string name="wallpaper_binding_label" msgid="1197440498000786738">"טפט"</string>
- <string name="chooser_wallpaper" msgid="3082405680079923708">"שנה טפט"</string>
+ <string name="chooser_wallpaper" msgid="3082405680079923708">"שינוי טפט"</string>
<string name="notification_listener_binding_label" msgid="2702165274471499713">"מאזין להתראות"</string>
<string name="vr_listener_binding_label" msgid="8013112996671206429">"VR ליסנר"</string>
<string name="condition_provider_service_binding_label" msgid="8490641013951857673">"ספק תנאי"</string>
@@ -1509,7 +1540,7 @@
<string name="vpn_title" msgid="5906991595291514182">"VPN מופעל"</string>
<string name="vpn_title_long" msgid="6834144390504619998">"VPN מופעל על ידי <xliff:g id="APP">%s</xliff:g>"</string>
<string name="vpn_text" msgid="2275388920267251078">"הקש כדי לנהל את הרשת."</string>
- <string name="vpn_text_long" msgid="278540576806169831">"מחובר אל <xliff:g id="SESSION">%s</xliff:g>. הקש כדי לנהל את הרשת."</string>
+ <string name="vpn_text_long" msgid="278540576806169831">"בוצע חיבור אל <xliff:g id="SESSION">%s</xliff:g>. יש להקיש כדי לנהל את הרשת."</string>
<string name="vpn_lockdown_connecting" msgid="6096725311950342607">"ה-VPN שמופעל תמיד, מתחבר..."</string>
<string name="vpn_lockdown_connected" msgid="2853127976590658469">"ה-VPN שפועל תמיד, מחובר"</string>
<string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"אין חיבור ל-VPN שפועל כל הזמן"</string>
@@ -1537,7 +1568,7 @@
<string name="share" msgid="4157615043345227321">"שתף"</string>
<string name="find" msgid="5015737188624767706">"מצא"</string>
<string name="websearch" msgid="5624340204512793290">"חיפוש באינטרנט"</string>
- <string name="find_next" msgid="5341217051549648153">"חפש את הבא"</string>
+ <string name="find_next" msgid="5341217051549648153">"מציאת ההתאמה הבאה"</string>
<string name="find_previous" msgid="4405898398141275532">"חיפוש של הקודם"</string>
<string name="gpsNotifTicker" msgid="3207361857637620780">"בקשת מיקום מאת <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="gpsNotifTitle" msgid="1590033371665669570">"בקשת מיקום"</string>
@@ -1548,7 +1579,7 @@
<string name="sync_too_many_deletes_desc" msgid="7409327940303504440">"יש <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> פריטים שנמחקו עבור <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g> , בחשבון <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. איזו פעולה ברצונך לבצע?"</string>
<string name="sync_really_delete" msgid="5657871730315579051">"מחק את הפריטים"</string>
<string name="sync_undo_deletes" msgid="5786033331266418896">"בטל את פעולות המחיקה"</string>
- <string name="sync_do_nothing" msgid="4528734662446469646">"אל תעשה דבר כרגע"</string>
+ <string name="sync_do_nothing" msgid="4528734662446469646">"לא לבצע שום פעולה כרגע"</string>
<string name="choose_account_label" msgid="5557833752759831548">"בחירת חשבון"</string>
<string name="add_account_label" msgid="4067610644298737417">"הוספת חשבון"</string>
<string name="add_account_button_label" msgid="322390749416414097">"הוספת חשבון"</string>
@@ -1557,11 +1588,11 @@
<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>
- <string name="time_picker_increment_hour_button" msgid="3063572723197178242">"הוסף שעה"</string>
- <string name="time_picker_decrement_hour_button" msgid="584101766855054412">"הפחת שעה"</string>
- <string name="time_picker_increment_set_pm_button" msgid="5889149366900376419">"הגדר PM"</string>
- <string name="time_picker_decrement_set_am_button" msgid="1422608001541064087">"הגדר AM"</string>
+ <string name="time_picker_decrement_minute_button" msgid="230925389943411490">"הפחתת דקה"</string>
+ <string name="time_picker_increment_hour_button" msgid="3063572723197178242">"הוספת שעה"</string>
+ <string name="time_picker_decrement_hour_button" msgid="584101766855054412">"הפחתת שעה"</string>
+ <string name="time_picker_increment_set_pm_button" msgid="5889149366900376419">"הגדרת PM"</string>
+ <string name="time_picker_decrement_set_am_button" msgid="1422608001541064087">"הגדרת AM"</string>
<string name="date_picker_increment_month_button" msgid="3447263316096060309">"הוסף חודש"</string>
<string name="date_picker_decrement_month_button" msgid="6531888937036883014">"הפחתת חודש"</string>
<string name="date_picker_increment_day_button" msgid="4349336637188534259">"הוסף יום"</string>
@@ -1580,7 +1611,7 @@
<string name="activitychooserview_choose_application" msgid="3500574466367891463">"בחר אפליקציה"</string>
<string name="activitychooserview_choose_application_error" msgid="6937782107559241734">"לא ניתן היה להפעיל את <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="shareactionprovider_share_with" msgid="2753089758467748982">"שתף עם"</string>
- <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"שתף עם <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"שיתוף עם <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="content_description_sliding_handle" msgid="982510275422590757">"נקודת אחיזה להחלקה. לחיצה ארוכה."</string>
<string name="description_target_unlock_tablet" msgid="7431571180065859551">"החלק לביטול נעילה."</string>
<string name="action_bar_home_description" msgid="1501655419158631974">"נווט לדף הבית"</string>
@@ -1588,7 +1619,7 @@
<string name="action_menu_overflow_description" msgid="4579536843510088170">"אפשרויות נוספות"</string>
<string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="8490227947584914460">"אחסון שיתוף פנימי"</string>
+ <string name="storage_internal" msgid="8490227947584914460">"אחסון פנימי משותף"</string>
<string name="storage_sd_card" msgid="3404740277075331881">"כרטיס SD"</string>
<string name="storage_sd_card_label" msgid="7526153141147470509">"כרטיס SD של <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="448030813201444573">"כונן USB"</string>
@@ -1641,14 +1672,14 @@
<string name="default_audio_route_category_name" msgid="5241740395748134483">"מערכת"</string>
<string name="bluetooth_a2dp_audio_route_name" msgid="4214648773120426288">"אודיו Bluetooth"</string>
<string name="wireless_display_route_description" msgid="8297563323032966831">"צג אלחוטי"</string>
- <string name="media_route_button_content_description" msgid="2299223698196869956">"העבר"</string>
+ <string name="media_route_button_content_description" msgid="2299223698196869956">"העברה (cast)"</string>
<string name="media_route_chooser_title" msgid="6646594924991269208">"התחברות למכשיר"</string>
<string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"העברת מסך אל מכשיר"</string>
- <string name="media_route_chooser_searching" msgid="6119673534251329535">"מחפש מכשירים…"</string>
+ <string name="media_route_chooser_searching" msgid="6119673534251329535">"המערכת מחפשת מכשירים…"</string>
<string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"הגדרות"</string>
<string name="media_route_controller_disconnect" msgid="7362617572732576959">"נתק"</string>
<string name="media_route_status_scanning" msgid="8045156315309594482">"סורק..."</string>
- <string name="media_route_status_connecting" msgid="5845597961412010540">"מתחבר..."</string>
+ <string name="media_route_status_connecting" msgid="5845597961412010540">"מתבצע חיבור..."</string>
<string name="media_route_status_available" msgid="1477537663492007608">"זמין"</string>
<string name="media_route_status_not_available" msgid="480912417977515261">"לא זמין"</string>
<string name="media_route_status_in_use" msgid="6684112905244944724">"בשימוש"</string>
@@ -1674,11 +1705,11 @@
<string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"כרטיס ה-SIM מושבת כעת. הזן קוד PUK כדי להמשיך. פנה אל הספק לפרטים."</string>
<string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"הזן את קוד הגישה הרצוי"</string>
<string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"אשר את קוד הגישה הרצוי"</string>
- <string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"מבטל נעילה של כרטיס SIM…"</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"מתבצע ביטול נעילה של כרטיס SIM…"</string>
<string name="kg_password_wrong_pin_code" msgid="9013856346870572451">"קוד גישה שגוי."</string>
<string name="kg_invalid_sim_pin_hint" msgid="4821601451222564077">"הקלד קוד גישה שאורכו 4 עד 8 ספרות."</string>
<string name="kg_invalid_sim_puk_hint" msgid="2539364558870734339">"קוד PUK צריך להיות בן 8 ספרות."</string>
- <string name="kg_invalid_puk" msgid="4809502818518963344">"הזן מחדש את קוד PUK הנכון. ניסיונות חוזרים ישביתו לצמיתות את כרטיס ה-SIM."</string>
+ <string name="kg_invalid_puk" msgid="4809502818518963344">"יש להזין שוב את קוד ה-PUK הנכון. ניסיונות חוזרים ישביתו את כרטיס ה-SIM באופן סופי."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"קודי הגישה אינם תואמים"</string>
<string name="kg_login_too_many_attempts" msgid="699292728290654121">"ניסיונות רבים מדי לשרטוט קו ביטול נעילה."</string>
<string name="kg_login_instructions" msgid="3619844310339066827">"כדי לבטל את הנעילה, עליך להיכנס באמצעות חשבון Google שלך."</string>
@@ -1687,17 +1718,17 @@
<string name="kg_login_submit_button" msgid="893611277617096870">"כניסה"</string>
<string name="kg_login_invalid_input" msgid="8292367491901220210">"שם משתמש או סיסמה לא חוקיים."</string>
<string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"שכחת את שם המשתמש או הסיסמה?\nהיכנס לכתובת "<b>"google.com/accounts/recovery"</b></string>
- <string name="kg_login_checking_password" msgid="4676010303243317253">"בודק חשבון…"</string>
+ <string name="kg_login_checking_password" msgid="4676010303243317253">"מתבצעת בדיקה של החשבון…"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"הקלדת קוד גישה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"הקלדת סיסמה שגויה <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים.\n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"ביצעת <xliff:g id="NUMBER_0">%1$d</xliff:g> ניסיונות שגויים לביטול נעילת הטלפון. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, הטאבלט יעבור איפוס לברירת המחדל של היצרן וכל נתוני המשתמש יאבדו."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"ניסית לבטל בצורה שגויה את הנעילה של מכשיר ה-Android TV <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, מכשיר ה-Android TV יעבור איפוס לברירת המחדל של היצרן וכל נתוני המשתמש יאבדו."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"ניסית לבטל בצורה שגויה את הנעילה של מכשיר ה-Android TV <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, מכשיר ה-Android TV יעבור איפוס לברירת המחדל של היצרן וכל נתוני המשתמש יאבדו."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"ביצעת <xliff:g id="NUMBER_0">%1$d</xliff:g> ניסיונות שגויים לביטול נעילת הטלפון. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, הטלפון יעבור איפוס לברירת המחדל של היצרן וכל נתוני המשתמש יאבדו."</string>
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"ביצעת <xliff:g id="NUMBER">%d</xliff:g> ניסיונות שגויים לביטול נעילת הטאבלט. הטאבלט יעבור כעת איפוס לברירת המחדל של היצרן."</string>
<string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"ניסית לבטל בצורה שגויה את הנעילה של מכשיר ה-Android TV <xliff:g id="NUMBER">%d</xliff:g> פעמים. מכשיר ה-Android TV יעבור כעת איפוס לברירת המחדל של היצרן."</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"ביצעת <xliff:g id="NUMBER">%d</xliff:g> ניסיונות שגויים לביטול נעילת הטלפון. הטלפון יעבור כעת איפוס לברירת המחדל של היצרן."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטאבלט באמצעות חשבון אימייל.\n\nנסה שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, יהיה צורך לבטל את נעילת הטאבלט באמצעות חשבון אימייל.\n\nיש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
<string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, יהיה צורך לבטל את הנעילה של מכשיר ה-Android TV באמצעות חשבון אימייל.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטלפון באמצעות חשבון אימייל.\n\nנסה שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
@@ -1706,10 +1737,10 @@
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"להשתמש בקיצור הדרך לתכונת הנגישות?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"כשקיצור הדרך מופעל, לחיצה על שני לחצני עוצמת הקול למשך שלוש שניות מפעילה את תכונת הנגישות."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"האם להפעיל את מקש הקיצור לתכונות הנגישות?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"לחיצה ארוכה על שני לחצני עוצמת הקול למשך מספר שניות מפעילה את תכונות הנגישות. בעקבות זאת, ייתכן שאופן הפעולה של המכשיר ישתנה.\n\nהתכונות הנוכחיות:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nניתן לשנות תכונות נבחרות ב\'הגדרות\' > \'נגישות\'."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"לחיצה ארוכה על שני לחצני עוצמת הקול למשך מספר שניות מפעילה את תכונות הנגישות. בעקבות זאת, ייתכן שאופן הפעולה של המכשיר ישתנה.\n\nהתכונות הנוכחיות:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nניתן לשנות את התכונות שנבחרו ב\'הגדרות\' > \'נגישות\'."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"האם להפעיל את מקש הקיצור של <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
- <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ניתן ללחוץ על שני מקשי עוצמת הקול למשך מספר שניות כדי להפעיל את <xliff:g id="SERVICE">%1$s</xliff:g>, תכונת נגישות. בעקבות זאת, ייתכן שאופן הפעולה של המכשיר ישתנה.\n\nאפשר לשנות את מקשי הקיצור האלה לתכונה נוספת ב\'הגדרות\' > \'נגישות\'."</string>
+ <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"לחיצה על שני מקשי עוצמת הקול למשך מספר שניות מפעילה את תכונת הנגישות <xliff:g id="SERVICE">%1$s</xliff:g>. ייתכן שאופן הפעולה של המכשיר ישתנה בעקבות זאת.\n\nאפשר לשנות את מקשי הקיצור האלה לתכונה אחרת ב\'הגדרות\' > \'נגישות\'."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"אני רוצה להפעיל"</string>
<string name="accessibility_shortcut_off" msgid="3651336255403648739">"לא להפעיל"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"מופעל"</string>
@@ -1734,7 +1765,7 @@
<string name="color_inversion_feature_name" msgid="326050048927789012">"היפוך צבעים"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"תיקון צבעים"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"מעומעם במיוחד"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הופעל."</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. שירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הופעל."</string>
<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>
@@ -1851,10 +1882,10 @@
<string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"קודי האימות לא תואמים. יש לנסות שוב."</string>
<string name="restr_pin_error_too_short" msgid="1547007808237941065">"קוד הגישה קצר מדי. חייב להיות באורך 4 ספרות לפחות."</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
- <item quantity="two">נסה שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות</item>
- <item quantity="many">נסה שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות</item>
- <item quantity="other">נסה שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות</item>
- <item quantity="one">נסה שוב בעוד שנייה אחת</item>
+ <item quantity="two">יש לנסות שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות</item>
+ <item quantity="many">יש לנסות שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות</item>
+ <item quantity="other">יש לנסות שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות</item>
+ <item quantity="one">יש לנסות שוב בעוד שנייה אחת</item>
</plurals>
<string name="restr_pin_try_later" msgid="5897719962541636727">"יש לנסות שוב מאוחר יותר"</string>
<string name="immersive_cling_title" msgid="2307034298721541791">"צפייה במסך מלא"</string>
@@ -1872,14 +1903,14 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> שני בעבודה"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> שלישי בעבודה"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"בקש קוד גישה לפני ביטול הצמדה"</string>
- <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"בקש קו ביטול נעילה לפני ביטול הצמדה"</string>
+ <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"צריך לבקש קו ביטול נעילה לפני ביטול הצמדה"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"בקש סיסמה לפני ביטול הצמדה"</string>
<string name="package_installed_device_owner" msgid="7035926868974878525">"הותקנה על ידי מנהל המערכת"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"עודכנה על ידי מנהל המערכת"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"נמחקה על ידי מנהל המערכת"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"אישור"</string>
<string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"כדי להאריך את חיי הסוללה, התכונה \'חיסכון בסוללה\':\n\n• מפעילה עיצוב כהה\n• מכבה או מגבילה פעילות ברקע, חלק מהאפקטים החזותיים ותכונות אחרות כמו Ok Google\n\n"<annotation id="url">"למידע נוסף"</annotation></string>
- <string name="battery_saver_description" msgid="6794188153647295212">"כדי להאריך את חיי הסוללה, התכונה \'חיסכון בסוללה\':\n\n• מפעילה עיצוב כהה\n• מכבה או מגבילה פעילות ברקע, חלק מהאפקטים החזותיים ותכונות אחרות כמו Ok Google"</string>
+ <string name="battery_saver_description" msgid="6794188153647295212">"כדי להאריך את חיי הסוללה, התכונה \'חיסכון בסוללה\':\n\n• מפעילה עיצוב כהה\n• משביתה או מגבילה פעילות ברקע, חלק מהאפקטים החזותיים ותכונות אחרות כמו Hey Google"</string>
<string name="data_saver_description" msgid="4995164271550590517">"כדי לסייע בהפחתת השימוש בנתונים, חוסך הנתונים (Data Saver) מונע מאפליקציות מסוימות שליחה או קבלה של נתונים ברקע. אפליקציה שבה נעשה שימוש כרגע יכולה לגשת לנתונים, אבל בתדירות נמוכה יותר. המשמעות היא, למשל, שתמונות יוצגו רק לאחר שמקישים עליהן."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"להפעיל את חוסך הנתונים?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"הפעלה"</string>
@@ -1945,7 +1976,7 @@
<string name="zen_mode_default_events_name" msgid="2280682960128512257">"אירוע"</string>
<string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"שינה"</string>
<string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> משתיק חלק מהצלילים"</string>
- <string name="system_error_wipe_data" msgid="5910572292172208493">"קיימת בעיה פנימית במכשיר שלך, וייתכן שהתפקוד שלו לא יהיה יציב עד שתבצע איפוס לנתוני היצרן."</string>
+ <string name="system_error_wipe_data" msgid="5910572292172208493">"קיימת בעיה פנימית במכשיר שלך, וייתכן שהוא לא יתפקד כראוי עד שיבוצע איפוס לנתוני היצרן."</string>
<string name="system_error_manufacturer" msgid="703545241070116315">"קיימת בעיה פנימית במכשיר שלך. לקבלת פרטים, צור קשר עם היצרן."</string>
<string name="stk_cc_ussd_to_dial" msgid="3139884150741157610">"בקשת USSD שונתה לשיחה רגילה"</string>
<string name="stk_cc_ussd_to_ss" msgid="4826846653052609738">"בקשת USSD שונתה לבקשת SS"</string>
@@ -1967,7 +1998,7 @@
<string name="usb_midi_peripheral_product_name" msgid="2836276258480904434">"יציאת USB בציוד היקפי"</string>
<string name="floating_toolbar_open_overflow_description" msgid="2260297653578167367">"אפשרויות נוספות"</string>
<string name="floating_toolbar_close_overflow_description" msgid="3949818077708138098">"סגור את האפשרויות הנוספות"</string>
- <string name="maximize_button_text" msgid="4258922519914732645">"הגדל"</string>
+ <string name="maximize_button_text" msgid="4258922519914732645">"הגדלה"</string>
<string name="close_button_text" msgid="10603510034455258">"סגירה"</string>
<string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
<string name="call_notification_answer_action" msgid="5999246836247132937">"תשובה"</string>
@@ -1986,7 +2017,7 @@
<string name="importance_from_user" msgid="2782756722448800447">"עליך להגדיר את החשיבות של ההתראות האלה."</string>
<string name="importance_from_person" msgid="4235804979664465383">"ההודעה חשובה בשל האנשים המעורבים."</string>
<string name="notification_history_title_placeholder" msgid="7748630986182249599">"התראות אפליקציה בהתאמה אישית"</string>
- <string name="user_creation_account_exists" msgid="2239146360099708035">"האם לאפשר לאפליקציה <xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש באמצעות <xliff:g id="ACCOUNT">%2$s</xliff:g> (כבר קיים משתמש לחשבון הזה) ?"</string>
+ <string name="user_creation_account_exists" msgid="2239146360099708035">"האם לאפשר לאפליקציה <xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש באמצעות <xliff:g id="ACCOUNT">%2$s</xliff:g> (כבר קיים משתמש לחשבון הזה)?"</string>
<string name="user_creation_adding" msgid="7305185499667958364">"האם לאפשר לאפליקציה <xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש באמצעות <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
<string name="language_selection_title" msgid="52674936078683285">"הוספת שפה"</string>
<string name="country_selection_title" msgid="5221495687299014379">"העדפת אזור"</string>
@@ -1995,7 +2026,7 @@
<string name="language_picker_section_all" msgid="1985809075777564284">"כל השפות"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"כל האזורים"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"חיפוש"</string>
- <string name="app_suspended_title" msgid="888873445010322650">"האפליקציה אינה זמינה"</string>
+ <string name="app_suspended_title" msgid="888873445010322650">"האפליקציה לא זמינה"</string>
<string name="app_suspended_default_message" msgid="6451215678552004172">"האפליקציה <xliff:g id="APP_NAME_0">%1$s</xliff:g> לא זמינה כרגע. את הזמינות שלה אפשר לנהל באפליקציה <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"מידע נוסף"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ביטול ההשהיה של האפליקציה"</string>
@@ -2007,11 +2038,11 @@
<string name="deprecated_target_sdk_message" msgid="5203207875657579953">"האפליקציה הזו עוצבה לגרסה ישנה יותר של Android וייתכן שלא תפעל כראוי. ניתן לבדוק אם יש עדכונים או ליצור קשר עם המפתח."</string>
<string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"האם יש עדכון חדש?"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"יש לך הודעות חדשות"</string>
- <string name="new_sms_notification_content" msgid="3197949934153460639">"פתח את אפליקציית ה-SMS כדי להציג"</string>
+ <string name="new_sms_notification_content" msgid="3197949934153460639">"יש לפתוח את אפליקציית ה-SMS כדי להציג"</string>
<string name="profile_encrypted_title" msgid="9001208667521266472">"ייתכן שחלק מהפונקציונליות תהיה מוגבלת"</string>
<string name="profile_encrypted_detail" msgid="5279730442756849055">"פרופיל העבודה נעול"</string>
<string name="profile_encrypted_message" msgid="1128512616293157802">"הקש לביטול נעילת פרופיל העבודה"</string>
- <string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"מחובר אל <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+ <string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"התבצע חיבור אל <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"הקש כדי להציג קבצים"</string>
<string name="pin_target" msgid="8036028973110156895">"הצמדה"</string>
<string name="pin_specific_target" msgid="7824671240625957415">"הצמדה של <xliff:g id="LABEL">%1$s</xliff:g>"</string>
@@ -2041,7 +2072,7 @@
<string name="time_picker_input_error" msgid="8386271930742451034">"יש להזין שעה חוקית"</string>
<string name="time_picker_prompt_label" msgid="303588544656363889">"מהי השעה הנכונה"</string>
<string name="time_picker_text_input_mode_description" msgid="4761160667516611576">"העבר למצב קלט טקסט לצורך הזנת השעה"</string>
- <string name="time_picker_radial_mode_description" msgid="1222342577115016953">"העבר למצב שעון לצורך הזנת השעה"</string>
+ <string name="time_picker_radial_mode_description" msgid="1222342577115016953">"מעבר למצב שעון לצורך הזנת השעה"</string>
<string name="autofill_picker_accessibility_title" msgid="4425806874792196599">"אפשרויות מילוי אוטומטי"</string>
<string name="autofill_save_accessibility_title" msgid="1523225776218450005">"שמירה לצורך מילוי אוטומטי"</string>
<string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"לא ניתן למלא את התוכן באופן אוטומטי"</string>
@@ -2074,7 +2105,7 @@
<string name="autofill_save_type_generic_card" msgid="1019367283921448608">"כרטיס"</string>
<string name="autofill_save_type_username" msgid="1018816929884640882">"שם משתמש"</string>
<string name="autofill_save_type_email_address" msgid="1303262336895591924">"כתובת אימייל"</string>
- <string name="etws_primary_default_message_earthquake" msgid="8401079517718280669">"הישאר רגוע וחפש מחסה בקרבת מקום."</string>
+ <string name="etws_primary_default_message_earthquake" msgid="8401079517718280669">"חשוב להישאר רגועים ולחפש מחסה בקרבת מקום."</string>
<string name="etws_primary_default_message_tsunami" msgid="5828171463387976279">"יש להתפנות מיידית מאזורים הסמוכים לחופים ולנהרות למקום בטוח יותר, כגון שטח גבוה יותר."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="4888224011071875068">"הישאר רגוע וחפש מחסה בקרבת מקום."</string>
<string name="etws_primary_default_message_test" msgid="4583367373909549421">"בדיקה של הודעות חירום"</string>
@@ -2086,7 +2117,7 @@
<string name="mmcc_illegal_me" msgid="6505557881889904915">"הטלפון לא מורשה לזיהוי קולי"</string>
<string name="mmcc_authentication_reject_msim_template" msgid="4480853038909922153">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> אינו מאושר לשימוש ברשת"</string>
<string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="3688508325248599657">"אין ניהול תצורה עבור SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
- <string name="mmcc_illegal_ms_msim_template" msgid="832644375774599327">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> אינו מאושר לשימוש ברשת"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="832644375774599327">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> אינו מאושר לשימוש ברשת"</string>
<string name="mmcc_illegal_me_msim_template" msgid="4802735138861422802">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> אינו מאושר לשימוש ברשת"</string>
<string name="popup_window_default_title" msgid="6907717596694826919">"חלון קופץ"</string>
<string name="slice_more_content" msgid="3377367737876888459">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
@@ -2096,7 +2127,7 @@
<string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"לא ניתן היה לשחזר את קיצור הדרך"</string>
<string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"מקש הקיצור מושבת"</string>
<string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"הסרת התקנה"</string>
- <string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"רוצה לפתוח בכל זאת"</string>
+ <string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"לפתוח בכל זאת"</string>
<string name="harmful_app_warning_title" msgid="8794823880881113856">"אותרה אפליקציה מזיקה"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> רוצה להציג חלקים מ-<xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"עריכה"</string>
@@ -2105,7 +2136,7 @@
<string name="notification_channel_system_changes" msgid="2462010596920209678">"שינויי מערכת"</string>
<string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"נא לא להפריע"</string>
<string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"חדש: מצב \'נא לא להפריע\' מסתיר התראות"</string>
- <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ניתן להקיש כדי לקבל מידע נוסף ולשנות."</string>
+ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"אפשר להקיש כדי לקבל מידע נוסף ולבצע שינויים."</string>
<string name="zen_upgrade_notification_title" msgid="8198167698095298717">"ההגדרה \'נא לא להפריע\' השתנתה"</string>
<string name="zen_upgrade_notification_content" msgid="5228458567180124005">"יש להקיש כדי לבדוק מה חסום."</string>
<string name="notification_app_name_system" msgid="3045196791746735601">"מערכת"</string>
@@ -2137,7 +2168,7 @@
<string name="mime_type_image" msgid="2134307276151645257">"תמונה"</string>
<string name="mime_type_image_ext" msgid="5743552697560999471">"תמונה בפורמט <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
<string name="mime_type_compressed" msgid="8737300936080662063">"ארכיון"</string>
- <string name="mime_type_compressed_ext" msgid="4775627287994475737">"קובץ ארכיון <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="mime_type_compressed_ext" msgid="4775627287994475737">"קובץ ארכיון מסוג <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
<string name="mime_type_document" msgid="3737256839487088554">"מסמך"</string>
<string name="mime_type_document_ext" msgid="2398002765046677311">"מסמך <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
<string name="mime_type_spreadsheet" msgid="8188407519131275838">"גיליון אלקטרוני"</string>
@@ -2178,20 +2209,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"עבודה"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"תצוגה אישית"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"תצוגת עבודה"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"לא ניתן לשתף את התוכן הזה עם אפליקציות לעבודה"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"מנהל ה-IT לא מתיר לשתף את התוכן הזה עם אפליקציות מפרופיל העבודה שלך"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"לא ניתן לפתוח את התוכן הזה באפליקציות לעבודה"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"מנהל ה-IT לא מתיר לפתוח את התוכן הזה באפליקציות מפרופיל העבודה שלך"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"לא ניתן לשתף את התוכן הזה עם אפליקציות לשימוש אישי"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"מנהל ה-IT לא מתיר לשתף את התוכן הזה עם אפליקציות מהפרופיל האישי שלך"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"לא ניתן לפתוח את התוכן הזה באפליקציות לשימוש אישי"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"מנהל ה-IT לא מתיר לפתוח את התוכן הזה באפליקציות מהפרופיל האישי שלך"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"פרופיל העבודה מושהה"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"הפעלה"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"אין תמיכה בתוכן הזה באפליקציות לעבודה"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"אי אפשר לפתוח את התוכן הזה באמצעות אפליקציות לעבודה"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"אין תמיכה בתוכן הזה באפליקציות לשימוש אישי"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"אי אפשר לפתוח את התוכן הזה באמצעות אפליקציות לשימוש אישי"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"קוד אימות לביטול הנעילה של רשת SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"קוד אימות לביטול הנעילה של תת-קבוצה ברשת SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"קוד אימות לביטול הנעילה של כרטיס SIM עסקי"</string>
@@ -2246,8 +2288,8 @@
<string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"נשלחת בקשה לביטול נעילה של PUK…"</string>
<string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"נשלחת בקשה לביטול נעילה של PUK…"</string>
<string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"נשלחת בקשה לביטול נעילה של PUK…"</string>
- <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"נכשלה הבקשה לביטול הנעילה של רשת SIM."</string>
- <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"נכשלה הבקשה לביטול הנעילה של תת-קבוצה ברשת SIM."</string>
+ <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"לא ניתן היה לבטל את הנעילה של רשת SIM."</string>
+ <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"לא ניתן היה לבטל את הנעילה של תת-קבוצה ברשת SIM."</string>
<string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"נכשלה הבקשה לביטול הנעילה של ספק שירות SIM."</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"נכשלה הבקשה לביטול הנעילה של כרטיס SIM עסקי."</string>
<string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"נכשלה הבקשה לביטול נעילת SIM."</string>
@@ -2255,27 +2297,27 @@
<string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"נכשלה הבקשה לביטול הנעילה של RUIM network2."</string>
<string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"נכשלה הבקשה לביטול נעילה של RUIM hrpd."</string>
<string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"נכשלה הבקשה לביטול הנעילה של כרטיס RUIM עסקי."</string>
- <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"נכשלה הבקשה לביטול הנעילה של ספק שירות RUIM."</string>
- <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"נכשלה הבקשה לביטול הנעילה של כרטיס RUIM."</string>
+ <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"לא ניתן היה לבטל את הנעילה של ספק שירות RUIM."</string>
+ <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"לא ניתן היה לבטל את הנעילה של כרטיס RUIM."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"נכשל ביטול נעילה של PUK."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"נכשל ביטול נעילה של PUK."</string>
- <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"נכשל ביטול נעילה של PUK."</string>
+ <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"לא ניתן היה לבטל את הנעילה של PUK."</string>
<string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"נכשל ביטול נעילה של PUK."</string>
- <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"נכשל ביטול נעילה של PUK."</string>
- <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"נכשל ביטול נעילה של PUK."</string>
- <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"נכשל ביטול נעילה של PUK."</string>
- <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"נכשל ביטול נעילה של PUK."</string>
- <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"נכשל ביטול נעילה של PUK."</string>
- <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"נכשל ביטול נעילה של PUK."</string>
+ <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"לא ניתן היה לבטל את הנעילה של PUK."</string>
+ <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"לא ניתן היה לבטל נעילה של PUK."</string>
+ <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"לא ניתן היה לבטל נעילה של PUK."</string>
+ <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"לא ניתן היה לבטל את הנעילה של PUK."</string>
+ <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"לא ניתן היה לבטל את הנעילה של PUK."</string>
+ <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"לא ניתן היה לבטל נעילה של PUK."</string>
<string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"נכשל ביטול נעילה של PUK."</string>
- <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"נכשלה הבקשה לביטול נעילת SPN."</string>
- <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"נכשלה הבקשה לביטול הנעילה של PLMN לבית כשווה-ערך ל-SP."</string>
+ <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"לא ניתן היה לבטל את נעילת SPN."</string>
+ <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"לא ניתן היה לבטל את הנעילה של PLMN לבית כשווה-ערך ל-SP."</string>
<string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"נכשלה הבקשה לביטול נעילה של ICCID."</string>
- <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"נכשלה הבקשה לביטול נעילה של IMPI."</string>
- <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"נכשלה הבקשה לביטול הנעילה של ספק שירות של תת-קבוצה ברשת."</string>
+ <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"לא ניתן היה לבטל נעילה של IMPI."</string>
+ <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"לא ניתן היה לבטל הנעילה של ספק שירות של תת-קבוצה ברשת."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"ביטול הנעילה של רשת SIM בוצע בהצלחה."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"ביטול הנעילה של תת-קבוצה ברשת SIM בוצע בהצלחה."</string>
- <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"ביטול הנעילה של ספק שירות SIM בוצע בהצלחה ."</string>
+ <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"ביטול הנעילה של ספק שירות ה-SIM בוצע."</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"ביטול הנעילה של כרטיס SIM עסקי בוצע בהצלחה."</string>
<string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"ביטול נעילת SIM בוצע בהצלחה."</string>
<string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"ביטול הנעילה של RUIM network1 בוצע בהצלחה."</string>
@@ -2293,7 +2335,7 @@
<string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"ביטול נעילה של PUK בוצע בהצלחה."</string>
<string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"ביטול נעילה של PUK בוצע בהצלחה."</string>
<string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"ביטול נעילה של PUK בוצע בהצלחה."</string>
- <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"ביטול נעילה של PUK בוצע בהצלחה."</string>
+ <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"הנעילה של PUK בוטלה."</string>
<string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"ביטול נעילה של PUK בוצע בהצלחה."</string>
<string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"ביטול נעילת SPN בוצע בהצלחה."</string>
<string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"בוצע בהצלחה ביטול הנעילה של PLMN לבית כשווה-ערך ל-SP."</string>
@@ -2304,8 +2346,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"הגדלה של חלק מהמסך"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"עכשיו אפשר להגדיל את המסך המלא או אזור ספציפי במסך, או לעבור בין שתי האפשרויות."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"הפעלה בהגדרות"</string>
<string name="dismiss_action" msgid="1728820550388704784">"סגירה"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"כדי להמשיך, האפליקציה <b><xliff:g id="APP">%s</xliff:g></b> צריכה גישה למיקרופון של המכשיר שלך."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 95a0f86..aa98621 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"実行中のアプリ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"電池を消費しているアプリ"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"拡大"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"ユーザー補助機能に関するセキュリティ ポリシー"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」が電池を使用しています"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個のアプリが電池を使用しています"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"タップして電池やデータの使用量を確認"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"身体活動にアクセス"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"カメラ"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"写真と動画の撮影"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"付近の Bluetooth デバイス"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"付近の Bluetooth デバイスの検出と接続"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"通話履歴"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"通話履歴の読み取りと書き込み"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"電話"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"タブレットのBluetooth設定を表示すること、ペアのデバイスに接続すること/ペアのデバイスからの接続を受け入れることをアプリに許可します。"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV デバイスの Bluetooth 設定の表示と、ペア設定されたデバイスへの接続の確立、またはペア設定されたデバイスからの接続の受け入れをアプリに許可します。"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"モバイルデバイスのBluetooth設定を表示すること、ペアのデバイスに接続すること/ペアのデバイスからの接続を受け入れることをアプリに許可します。"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"付近の Bluetooth デバイスの検出とペア設定"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"付近の Bluetooth デバイスの検出とペア設定をアプリに許可します"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"ペア設定された Bluetooth デバイスへの接続"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"ペア設定された Bluetooth デバイスへの接続をアプリに許可します"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"優先される NFC お支払いサービスの情報"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"登録されている支援やルートの目的地など、優先される NFC お支払いサービスの情報を取得することをアプリに許可します。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFCの管理"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"エラー認証"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"画面ロックの使用"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"続行するにはデバイスの認証情報を入力してください"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"指紋を一部しか検出できませんでした。もう一度お試しください。"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"指紋を処理できませんでした。もう一度お試しください。"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"指紋認証センサーに汚れがあります。汚れを落としてもう一度お試しください。"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"指を離すのが速すぎました。もう一度お試しください。"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"指の動きが遅すぎました。もう一度お試しください。"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"指紋認証を完了しました"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"顔を認証しました"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"顔を認証しました。[確認] を押してください"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"指紋認証ハードウェアは使用できません。"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"指紋を保存できません。既存の指紋を削除してください。"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"指紋の読み取りがタイムアウトになりました。もう一度お試しください。"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋の操作をキャンセルしました。"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"指紋の操作がユーザーによりキャンセルされました。"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"顔認証"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"顔の再登録"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"認識を改善するには、顔を再登録してください"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"顔を認識できませんでした。もう一度お試しください。"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"明るすぎます。もっと暗い場所でお試しください。"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"暗すぎます。もっと明るい場所でお試しください。"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"コピーしました"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> から <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> に貼り付けました"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"クリップボードから <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> に貼り付けました"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"その他"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"MENU+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"仕事用"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"個人用ビュー"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"仕事用ビュー"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"仕事用アプリでこのコンテンツを共有することはできません"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT 管理者は、仕事用プロファイルのアプリでこのコンテンツを共有することを許可していません"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"仕事用アプリでこのコンテンツを開くことはできません"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT 管理者は、仕事用プロファイルのアプリでこのコンテンツを開くことを許可していません"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"個人用アプリでこのコンテンツを共有することはできません"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT 管理者は、個人用プロファイルのアプリでこのコンテンツを共有することを許可していません"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"個人用アプリでこのコンテンツを開くことはできません"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT 管理者は、個人用プロファイルのアプリでこのコンテンツを開くことを許可していません"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"仕事用プロファイルが一時停止しています"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ON にする"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"このコンテンツに対応する仕事用アプリはありません"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"このコンテンツを開くことができる仕事用アプリはありません"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"このコンテンツに対応する個人用アプリはありません"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"このコンテンツを開くことができる個人用アプリはありません"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM のネットワーク ロック解除 PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM のネットワーク サブネットのロック解除 PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM の企業ロック解除 PIN"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"画面の一部を拡大できます"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"画面全体または一部を拡大したり、画面全体と一部の拡大を切り替えたりできるようになりました。"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"[設定] で ON にする"</string>
<string name="dismiss_action" msgid="1728820550388704784">"閉じる"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"続行するには、<b><xliff:g id="APP">%s</xliff:g></b> にデバイスのマイクへのアクセスを許可する必要があります。"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 4f27b37..5d851e0 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"აპი გაშვებულია"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ბატარეის მხარჯავი აპები"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"გადიდება"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"მარტივი წვდომის უსაფრთხოების წესები"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> იყენებს ბატარეას"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"ბატარეას <xliff:g id="NUMBER">%1$d</xliff:g> აპი იყენებს"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"შეეხეთ ბატარეისა და მონაცემების მოხმარების შესახებ დეტალური ინფორმაციისთვის"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ფიზიკური აქტივობაზე წვდომა"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"კამერა"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ფოტოებისა და ვიდეოების გადაღება"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"ახლომახლო Bluetooth მოწყობილობები"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"ახლომახლო Bluetooth მოწყობილობების აღმოჩენა და მათთან დაკავშირება"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"ზარების ჟურნალები"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ზარების ჟურნალის წაკითხვა და მასში ჩაწერა"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ტელეფონი"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"აპს შეეძლება, ნახოს Bluetooth-ის კონფიგურაცია ტაბლეტზე, შექმნას და მიიღოს კავშირები დაწყვილებულ მოწყობილობებთან."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ნებას რთავს აპს, თქვენს Android TV მოწყობილობაზე ნახოს Bluetooth-ის კონფიგურაცია, ასევე, დაამყაროს და მიიღოს კავშირები დაწყვილებულ მოწყობილობებთან."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"აპს შეეძლება, ნახოს Bluetooth-ის კონფიგურაცია ტელეფონზე და შექმნას და მიიღოს კავშირები დაწყვილებულ მოწყობილობებთან."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"Bluetooth მოწყობილობების აღმოჩენა დასაწყვილებლად"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"საშუალებას აძლევს აპს, აღმოაჩინოს ახლომახლო Bluetooth მოწყობილობები დასაწყვილებლად"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"დაწყვილებულ Bluetooth მოწყობილობებთან დაკავშირება"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"საშუალებას აძლევს აპს, დაუკავშირდეს დაწყვილებულ Bluetooth მოწყობილობებს"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"უპირატესი NFC გადახდის სერვისის ინფორმაცია"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"საშუალებას აძლევს აპს, მიიღოს უპირატესი NFC გადახდის სერვისის ინფორმაცია, მაგალითად, რეგისტრირებული დახმარება და დანიშნულება."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ახლო მოქმედების რადიოკავშირი (NFC) მართვა"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"შეცდომა ავთენტიკაციისას"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"გამოიყენეთ ეკრანის დაბლოკვა"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"გასაგრძელებლად შეიყვანეთ თქვენი მოწყობილობის ავტორიზაციის მონაცემი"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"აღმოჩენილია თითის ნაწილობრივი ანაბეჭდი. გთხოვთ, სცადოთ ხელახლა."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"თითის ანაბეჭდის დამუშავება ვერ მოხერხდა. გთხოვთ, ცადოთ ხელახლა."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"თითის ანაბეჭდის სენსორი დაბინძურებულია. გთხოვთ, გაასუფთაოთ და სცადოთ ხელახლა."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"თითის აღება მეტისმეტად სწრაფად მოხდა. გთხოვთ, სცადოთ ხელახლა."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"თითის აღება მეტისმეტად ნელა მოხდა. გთხოვთ, სცადოთ ხელახლა."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"თითის ანაბეჭდი ავტორიზებულია"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"სახე ავტორიზებულია"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"სახე ავტორიზებულია, დააჭირეთ დადასტურებას"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"თითის ანაბეჭდის აპარატურა არ არის ხელმისაწვდომი."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"თითის ანაბეჭდის შენახვა ვერ ხერხდება. გთხოვთ, ამოშალოთ არსებული თითის ანაბეჭდი."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"თითის ანაბეჭდის ლოდინის დრო ამოიწურა. სცადეთ ხელახლა."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"თითის ანაბეჭდის აღების ოპერაცია გაუქმდა."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"თითის ანაბეჭდის ოპერაცია გააუქმა მომხმარებელმა."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"განბლოკვა სახით"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"დაარეგისტრირეთ თქვენი სახე ხელახლა"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ამოცნობის გასაუმჯობესებლად, გთხოვთ, ხელახლა დაარეგისტრიროთ თქვენი სახე"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"სახის ზუსტი მონაცემები არ აღიბეჭდა. ცადეთ ხელახლა."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"მეტისმეტად ნათელია. ცადეთ უფრო სუსტი განათება."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"მეტისმეტად ბნელია. ცადეთ უფრო ძლიერი განათება."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"დაკოპირდა"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-დან <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>-ში ჩასმული"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-მა ჩასვა გაცვლის ბუფერიდან"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"დამატებით"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"მენიუ+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,7 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"მალსახმობის გამოყენება"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ფერთა ინვერსია"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ფერთა კორექცია"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"დამატებითი დაბნელება"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"დამატებითი დაბინდვა"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ჩართულია."</string>
<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> რომ გამოიყენოთ, დააჭირეთ ხმის ორივე ღილაკზე 3 წამის განმავლობაში"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"სამსახური"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"პირადი ხედი"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"სამსახურის ხედი"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"სამსახურის აპებით გაზიარება ვერ მოხერხდება"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"თქვენი IT ადმინისტრატორი გიკრძალავთ ამ კონტენტის გაზიარებას თქვენი სამსახურის პროფილის აპებიდან"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"ამის სამსახურის აპებით გახსნა ვერ მოხერხდება"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"თქვენი IT ადმინისტრატორი გიკრძალავთ ამ კონტენტის გახსნას თქვენი სამსახურის პროფილის აპებიდან"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"პირადი აპებით გაზიარება ვერ მოხერხდება"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"თქვენი IT ადმინისტრატორი გიკრძალავთ ამ კონტენტის გაზიარებას თქვენი პერსონალური პროფილის აპებიდან"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"ამის პირადი აპებით გახსნა ვერ მოხერხდება"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"თქვენი IT ადმინისტრატორი გიკრძალავთ ამ კონტენტის გახსნას თქვენი პერსონალური პროფილის აპებიდან"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"სამსახურის პროფილი დაპაუზებულია"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ჩართვა"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"სამსახურის აპებს არ აქვს ამ კონტენტის მხარდაჭერა"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ამ კონტენტს სამსახურის აპები ვერ გახსნის"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"პერსონალურ აპებს არ აქვს ამ კონტენტის მხარდაჭერა"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"ამ კონტენტს პერსონალური აპები ვერ გახსნის"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ქსელის განბლოკვის PIN-კოდი"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ქსელის ქვედანაყოფის განბლოკვის PIN-კოდი"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM-ის კორპორატიული განბლოკვის PIN-კოდი"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"გაადიდეთ თქვენი ეკრანის ნაწილი"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"თქვენ უკვე შეგიძლიათ გაადიდოთ სრული ეკრანი, მისი გარკვეული ნაწილი, ან მონაცვლეობით გადართოთ ამ ორ ვარიანტს შორის."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ჩართვა პარამეტრებში"</string>
<string name="dismiss_action" msgid="1728820550388704784">"უარყოფა"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"გასაგრძელებლად <b><xliff:g id="APP">%s</xliff:g></b>-ს თქვენი მოწყობილობის მიკროფონზე წვდომა სჭირდება."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index df1bbeb..0f82f84 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Қолданба қосулы"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Батареяны пайдаланып жатқан қолданбалар"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ұлғайту"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Арнайы мүмкіндіктер қауіпсіздігі саясаты"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батареяны пайдалануда"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> қолданба батареяны пайдалануда"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батарея мен деректер трафигі туралы білу үшін түртіңіз"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"іс-қимыл дерегін алу"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Камера"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"суретке түсіріп, бейне жазу"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Маңайдағы Bluetooth құрылғылары"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"маңайдағы Bluetooth құрылғыларын анықтау және жұптау"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Қоңырау журналдары"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"телефонның қоңыраулар журналын оқу және жазу"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Телефон"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Қолданбаға планшеттегі Bluetooth конфигурациясын көру және жұпталған құрылғымен байланыс орнату немесе қабылдау мүмкіндігін береді."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Қолданба Android TV құрылғыңыздағы Bluetooth конфигурациясын көре алады және жұпталған құрылғылармен байланыс орнатып, оларды қабылдай алатын болады."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Қолданбаға телефондағы Bluetooth конфигурациясын көру және жұпталған құрылғымен байланыс орнату немесе қабылдау мүмкіндігін береді"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"маңайдағы Bluetooth құрылғыларын анықтау және жұптау"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Қолданбаға маңайдағы Bluetooth құрылғыларын анықтап, жұптауға рұқсат береді."</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"жұпталған Bluetooth құрылғыларына қосылу"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Қолданбаға жұпталған Bluetooth құрылғыларына қосылуға рұқсат береді."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Таңдаулы NFC төлеу қызметі туралы ақпарат"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Қолданба тіркелген көмектер және баратын жер маршруты сияқты таңдаулы NFC төлеу қызметі туралы ақпаратты ала алатын болады."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFC функциясын басқару"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Аутентификациялауда қате шықты."</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Экран құлпын пайдалану"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Жалғастыру үшін құрылғының тіркелу деректерін енгізіңіз."</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Саусақ ізі толық анықталмады. Әрекетті қайталаңыз."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Саусақ ізін өңдеу мүмкін емес. Әрекетті қайталаңыз."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Сканер лас. Тазалап, әрекетті қайталаңыз."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Саусағыңызды тым жылдам қозғалттыңыз. Әрекетті қайталап көріңіз."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Саусағыңызды тым баяу қозғалттыңыз. Әрекетті қайталап көріңіз."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Саусақ ізі аутентификацияланды"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Бет танылды"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Бет танылды, \"Растау\" түймесін басыңыз"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Саусақ ізі жабдығы қолжетімді емес."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Саусақ ізін сақтау мүмкін емес. Бар саусақ ізін жойыңыз."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Саусақ ізін күту уақыты бітті. Әрекетті қайталаңыз."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Саусақ ізі операциясынан бас тартылған."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Пайдаланушы саусақ ізі операциясынан бас тартты."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Бетті қайта тіркеу"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Құрылғы жүзіңізді жақсырақ тануы үшін, бетіңізді қайта тіркеңіз."</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Бет деректері дұрыс алынбады. Әрекетті қайталаңыз."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Тым ашық. Күңгірттеу жарық керек."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Тым қараңғы. Молырақ жарық керек."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Көшірілді"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> қолданбасынан <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> қолданбасына қойылды."</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Буферден <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> қолданбасына қойылды."</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Көбірек"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Mәзір+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1833,7 +1864,7 @@
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Әкімші жойған"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Жарайды"</string>
<string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Батарея жұмысының ұзақтығын арттыру үшін Батареяны үнемдеу режимі:\n\n•қараңғы тақырыпты іске қосады;\n•фондық әрекеттерді, кейбір көрнекі әсерлерді және \"Ok Google\" сияқты басқа да функцияларды өшіреді не шектейді.\n\n"<annotation id="url">"Толығырақ"</annotation></string>
- <string name="battery_saver_description" msgid="6794188153647295212">"Батарея ұзағырақ жұмыс істеуі үшін, Battery Saver:\n\n• қараңғы тақырыпты қосады;\n•фондық жұмысты, кейбір визуалды әсерлерді және \"Ok Google\" сияқты басқа функцияларды өшіреді не шектейді."</string>
+ <string name="battery_saver_description" msgid="6794188153647295212">"Батарея ұзағырақ жұмыс істеуі үшін, Батареяны үнемдеу режимі:\n\n• қараңғы тақырыпты қосады;\n•фондық жұмысты, кейбір визуалды әсерлерді және \"Ok Google\" сияқты басқа функцияларды өшіреді не шектейді."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Дерек шығынын азайту үшін Трафикті үнемдеу функциясы кейбір қолданбаларға деректерді фондық режимде жіберуге және алуға жол бермейді. Ашық тұрған қолданба деректерді пайдаланады, бірақ шектеулі шамада (мысалы, кескіндер оларды түрткенге дейін көрсетілмейді)."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Трафикті үнемдеу функциясын қосу керек пе?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Қосу"</string>
@@ -2054,9 +2085,9 @@
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Бұл хабарландырудың маңыздылық деңгейі төмендетілді. Пікір қалдыру үшін түртіңіз."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Режим туралы хабарландыру"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея заряды азаюы мүмкін"</string>
- <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарея ұзаққа жетуі үшін, Battery Saver іске қосылды"</string>
+ <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарея ұзаққа жетуі үшін, Батареяны үнемдеу режимі іске қосылды"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Батареяны үнемдеу режимі"</string>
- <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver өшірілді"</string>
+ <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Батареяны үнемдеу режимі өшірілді"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефонның заряды жеткілікті. Функцияларға енді шектеу қойылмайды."</string>
<string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Планшеттің заряды жеткілікті. Функцияларға енді шектеу қойылмайды."</string>
<string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Құрылғының заряды жеткілікті. Функцияларға енді шектеу қойылмайды."</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Жұмыс"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Жеке көру"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Жұмыс деректерін көру"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Мұны жұмыс қолданбаларымен бөлісу мүмкін емес"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Әкімші бұл мазмұнды жұмыс профиліндегі қолданбалармен бөлісуге рұқсат етпейді."</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Мұны жұмыс қолданбаларымен ашу мүмкін емес"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Әкімші бұл мазмұнды жұмыс профиліндегі қолданбалармен ашуға рұқсат етпейді."</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Мұны жеке қолданбалармен бөлісу мүмкін емес"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Әкімші бұл мазмұнды жеке профильдегі қолданбалармен бөлісуге рұқсат етпейді."</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Мұны жеке қолданбалармен ашу мүмкін емес"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Әкімші бұл мазмұнды жеке профильдегі қолданбалармен ашуға рұқсат етпейді."</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Жұмыс профилі кідіртілді."</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Қосу"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Бұл мазмұнды ешқандай жұмыс қолданбасы қолдай алмайды."</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Бұл мазмұнды ешқандай жұмыс қолданбасы аша алмайды."</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Бұл мазмұнды ешқандай жеке қолданба қолдай алмайды."</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Бұл мазмұнды ешқандай жеке қолданба аша алмайды."</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM желісінің құлпын ашатын PIN коды"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM желісі ішкі жиынтығының құлпын ашатын PIN коды"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Корпоративтік SIM картасының құлпын ашатын PIN коды"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Экран бөлігін ұлғайтыңыз"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Енді толық экранды не оның бір бөлігін ұлғайтуға немесе осы опцияларды алма-кезек қолдануға болады."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Параметрлер бөлімінен қосу"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Қабылдамау"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Жалғастыру үшін <b><xliff:g id="APP">%s</xliff:g></b> қолданбасы құрылғыңыздың микрофонына рұқсат алу керек."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index e8f45bc..8528118 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"កម្មវិធីដែលកំពុងដំណើរការ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"កម្មវិធីដែលកំពុងប្រើថ្ម"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ការពង្រីក"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"គោលការណ៍ស្ដីពីសុវត្ថិភាពនៃភាពងាយស្រួល"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងប្រើថ្ម"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"កម្មវិធីចំនួន <xliff:g id="NUMBER">%1$d</xliff:g> កំពុងប្រើថ្ម"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ចុចដើម្បីមើលព័ត៌មានលម្អិតអំពីការប្រើប្រាស់ទិន្នន័យ និងថ្ម"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ចូលប្រើសកម្មភាពរាងកាយរបស់អ្នក"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"កាមេរ៉ា"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ថតរូប និងថតវីដេអូ"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"ឧបករណ៍ប៊្លូធូសដែលនៅជិត"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"ស្វែងរក និងភ្ជាប់ទៅឧបករណ៍ប៊្លូធូសដែលនៅជិត"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"កំណត់ហេតុហៅទូរសព្ទ"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"អាន និងសរសេរកំណត់ហេតុហៅទូរសព្ទ"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ទូរសព្ទ"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ឲ្យកម្មវិធីមើលការកំណត់រចនាសម្ព័ន្ធប៊្លូធូសលើកុំព្យូទ័របន្ទះ ព្រមទាំងធ្វើការតភ្ជាប់ និងទទួលជាមួយឧបករណ៍បានផ្គូផ្គង។"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"អនុញ្ញាតឱ្យកម្មវិធីមើលការកំណត់រចនាសម្ព័ន្ធប៊្លូធូសនៅលើឧបករណ៍ Android TV របស់អ្នក ព្រមទាំងធ្វើការតភ្ជាប់ និងទទួលយកការតភ្ជាប់ជាមួយឧបករណ៍ដែលបានផ្គូផ្គង។"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ឲ្យកម្មវិធីមើលការកំណត់រចនាសម្ព័ន្ធប៊្លូធូសក្នុងទូរស័ព្ទ ដើម្បីទទួល និងតភ្ជាប់ជាមួយឧបករណ៍បានផ្គូផ្គង។"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"ស្វែងរក និងផ្គូផ្គងឧបករណ៍ប៊្លូធូសដែលនៅជិត"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"អនុញ្ញាតឱ្យកម្មវិធីស្វែងរក និងផ្គូផ្គងឧបករណ៍ប៊្លូធូសដែលនៅជិត"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"ភ្ជាប់ទៅឧបករណ៍ប៊្លូធូសដែលបានផ្គូផ្គង"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"អនុញ្ញាតឱ្យកម្មវិធីភ្ជាប់ទៅឧបករណ៍ប៊្លូធូសដែលបានផ្គូផ្គង"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ព័ត៌មានអំពីសេវាបង់ប្រាក់តាម NFC ជាអាទិភាព"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"អនុញ្ញាតឱ្យកម្មវិធីទទួលបានព័ត៌មានអំពីសេវាបង់ប្រាក់តាម nfc ជាអាទិភាពដូចជា គោលដៅផ្លូវ និងព័ត៌មានកំណត់អត្តសញ្ញាណកម្មវិធី ដែលបានចុះឈ្មោះជាដើម។"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ពិនិត្យការទាក់ទងនៅក្បែរ (NFC)"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"មានបញ្ហាក្នុងការផ្ទៀងផ្ទាត់"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ប្រើការចាក់សោអេក្រង់"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"បញ្ចូលព័ត៌មានផ្ទៀងផ្ទាត់ឧបករណ៍របស់អ្នក ដើម្បីបន្ត"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"បានផ្តិតយកស្នាមម្រាមដៃមិនពេញលក្ខណៈ។ សូមព្យាយាមម្តងទៀត។"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"មិនអាចដំណើរការស្នាមម្រាមដៃបានទេ។ សូមព្យាយាមម្តងទៀត។"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"ឧបករណ៍ចាប់ស្នាមម្រាមដៃគឺប្រឡាក់។ សូមសម្អាត រួចព្យាយាមម្តងទៀត។"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"ម្រាមដៃផ្លាស់ទីលឿនពេក។ សូមព្យាយាមម្តងទៀត។"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ចលនាម្រាមដៃយឺតពេកហើយ។ សូមព្យាយាមម្តងទៀត។"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"បានផ្ទៀងផ្ទាត់ស្នាមម្រាមដៃ"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"បានផ្ទៀងផ្ទាត់មុខ"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"បានផ្ទៀងផ្ទាត់មុខ សូមចុចបញ្ជាក់"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ផ្នែករឹងស្នាមម្រាមដៃមិនមានទេ។"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"មិនអាចផ្ទុកស្នាមម្រាមដៃទេ។ សូមយកស្នាមម្រាមដៃដែលមានស្រាប់ចេញ។"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"ស្នាមម្រាមដៃបានអស់ម៉ោង។ សូមព្យាយាមម្តងទៀត។"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"បានបោះបង់ប្រតិបត្តិការស្នាមម្រាមដៃ។"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ប្រតិបត្តិការស្នាមម្រាមដៃត្រូវបានបោះបង់ដោយអ្នកប្រើប្រាស់។"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ការដោះសោតាមទម្រង់មុខ"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ស្កេនបញ្ចូលមុខរបស់អ្នកម្ដងទៀត"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ដើម្បីធ្វើឱ្យការសម្គាល់មុខប្រសើរជាងមុន សូមស្កេនបញ្ចូលមុខរបស់អ្នកម្ដងទៀត"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"មិនអាចថតទិន្នន័យទម្រង់មុខបានត្រឹមត្រូវទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"ភ្លឺពេក។ សូមសាកល្បងប្រើពន្លឺស្រាលជាងនេះ។"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"ងងឹតជ្រុល។ សូមសាកល្បងប្រើពន្លឺភ្លឺជាងនេះ។"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"បានចម្លង"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> បានដាក់ចូលពី <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> បានដាក់ចូលពីឃ្លីបបត"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"ច្រើនទៀត"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"ម៉ឺនុយ +"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"ការងារ"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ទិដ្ឋភាពផ្ទាល់ខ្លួន"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"ទិដ្ឋភាពការងារ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"មិនអាចចែករំលែកខ្លឹមសារនេះតាមរយៈកម្មវិធីការងារបានទេ"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"អ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកមិនអនុញ្ញាតឱ្យអ្នកចែករំលែកខ្លឹមសារនេះតាមរយៈកម្មវិធីនៅក្នុងកម្រងព័ត៌មានការងាររបស់អ្នកទេ"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"មិនអាចបើកខ្លឹមសារនេះដោយប្រើកម្មវិធីការងារបានទេ"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"អ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកមិនអនុញ្ញាតឱ្យអ្នកបើកខ្លឹមសារនេះដោយប្រើកម្មវិធីនៅក្នុងកម្រងព័ត៌មានការងាររបស់អ្នកទេ"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"មិនអាចចែករំលែកខ្លឹមសារនេះតាមរយៈកម្មវិធីផ្ទាល់ខ្លួនបានទេ"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"អ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកមិនអនុញ្ញាតឱ្យអ្នកចែករំលែកខ្លឹមសារនេះតាមរយៈកម្មវិធីនៅក្នុងកម្រងព័ត៌មានផ្ទាល់ខ្លួនរបស់អ្នកទេ"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"មិនអាចបើកខ្លឹមសារនេះដោយប្រើកម្មវិធីផ្ទាល់ខ្លួនបានទេ"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"អ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកមិនអនុញ្ញាតឱ្យអ្នកបើកខ្លឹមសារនេះដោយប្រើកម្មវិធីនៅក្នុងកម្រងព័ត៌មានផ្ទាល់ខ្លួនរបស់អ្នកទេ"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"កម្រងព័ត៌មានការងារត្រូវបានផ្អាក"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"បើក"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"មិនមានកម្មវិធីការងារដែលអាចប្រើខ្លឹមសារនេះបានទេ"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"មិនមានកម្មវិធីការងារដែលអាចបើកខ្លឹមសារនេះបានទេ"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"មិនមានកម្មវិធីផ្ទាល់ខ្លួនដែលអាចប្រើខ្លឹមសារនេះបានទេ"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"មិនមានកម្មវិធីផ្ទាល់ខ្លួនដែលអាចបើកខ្លឹមសារនេះបានទេ"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"កូដ PIN ដោះសោបណ្ដាញស៊ីម"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"កូដ PIN ដោះសោសំណុំរងនៃបណ្ដាញស៊ីម"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"កូដ PIN ដោះសោក្រុមហ៊ុនស៊ីម"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"ពង្រីកផ្នែកនៃអេក្រង់របស់អ្នក"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"ឥឡូវនេះ អ្នកអាចពង្រីកអេក្រង់ពេញរបស់អ្នក តំបន់ជាក់លាក់ ឬប្ដូររវាងជម្រើសទាំងពីរ។"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"បើកនៅក្នុងការកំណត់"</string>
<string name="dismiss_action" msgid="1728820550388704784">"ច្រានចោល"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"ដើម្បីបន្ត <b><xliff:g id="APP">%s</xliff:g></b> ត្រូវការសិទ្ធិចូលប្រើមីក្រូហ្វូនរបស់ឧបករណ៍អ្នក។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index cfa6cf8..f0ed6fa 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App ರನ್ ಆಗುತ್ತಿದೆ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ಅಪ್ಲಿಕೇಶನ್ಗಳು ಬ್ಯಾಟರಿಯನ್ನು ಉಪಯೋಗಿಸುತ್ತಿವೆ"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ಹಿಗ್ಗಿಸುವಿಕೆ"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"ಪ್ರವೇಶಿಸುವಿಕೆ ಭದ್ರತಾ ನೀತಿ"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್, ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸುತ್ತಿದೆ"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್ಗಳು ಬ್ಯಾಟರಿ ಬಳಸುತ್ತಿವೆ"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ಬ್ಯಾಟರಿ,ಡೇಟಾ ಬಳಕೆಯ ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ನಿಮ್ಮ ದೈಹಿಕ ಚಟುವಟಿಕೆಯನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"ಕ್ಯಾಮರಾ"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ಚಿತ್ರಗಳನ್ನು ತೆಗೆಯಲು, ವೀಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಲು"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"ಸಮೀಪದಲ್ಲಿರುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳು"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"ಸಮೀಪದಲ್ಲಿರುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಅನ್ವೇಷಿಸಿ ಮತ್ತು ಅವುಗಳಿಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"ಕರೆಯ ಲಾಗ್"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ಪೋನ್ ಕರೆಯ ಲಾಗ್ ಅನ್ನು ಓದಿ ಮತ್ತು ಬರೆಯಿರಿ"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ಫೋನ್"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ಟ್ಯಾಬ್ಲೆಟ್ನಲ್ಲಿ ಬ್ಲೂಟೂತ್ನ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ವೀಕ್ಷಿಸಲು ಮತ್ತು ಜೋಡಿ ಮಾಡಿರುವ ಸಾಧನಗಳೊಂದಿಗೆ ಸಂಪರ್ಕಗಳನ್ನು ಕಲ್ಪಿಸಲು ಹಾಗೂ ಸ್ವೀಕರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಬ್ಲೂಟೂತ್ನ ಕಾನ್ಫಿಗರೇಶನ್ ವೀಕ್ಷಿಸಲು ಮತ್ತು ಜೋಡಿಸಿರುವ ಸಾಧನಗಳೊಂದಿಗೆ ಸಂಪರ್ಕಗಳನ್ನು ಮಾಡಲು ಮತ್ತು ಸ್ವೀಕರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ಫೋನ್ನಲ್ಲಿ ಬ್ಲೂಟೂತ್ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ವೀಕ್ಷಿಸಲು ಮತ್ತು ಜೋಡಿ ಮಾಡಿರುವ ಸಾಧನಗಳೊಂದಿಗೆ ಸಂಪರ್ಕಗಳನ್ನು ಕಲ್ಪಿಸಲು ಹಾಗೂ ಸ್ವೀಕರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"ಸಮೀಪದಲ್ಲಿರುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಅನ್ವೇಷಿಸಿ ಮತ್ತು ಅವುಗಳಿಗೆ ಜೋಡಿಸಿ"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"ಸಮೀಪದಲ್ಲಿರುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಅನ್ವೇಷಿಸಲು ಮತ್ತು ಅವುಗಳಿಗೆ ಜೋಡಿಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸಿ"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"ಜೋಡಿಸಿರುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳಿಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"ಜೋಡಿಸಲಾಗಿರುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳಿಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ಆದ್ಯತೆಯ NFC ಪಾವತಿ ಸೇವಾ ಮಾಹಿತಿ"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ನೋಂದಾಯಿತ ಅಪ್ಲಿಕೇಶನ್ ಗುರುತಿಸುವಿಕೆಗಳು ಮತ್ತು ಮಾರ್ಗ ಗಮ್ಯಸ್ಥಾನಗಳಂತಹ ಆದ್ಯತೆಯ NFC ಪಾವತಿ ಸೇವೆಗಳ ಬಗ್ಗೆ ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ಸಮೀಪ ಕ್ಷೇತ್ರ ಸಂವಹನವನ್ನು ನಿಯಂತ್ರಿಸಿ"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"ದೃಢೀಕರಿಸುವಾಗ ದೋಷ ಎದುರಾಗಿದೆ"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಬಳಸಿ"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಸಾಧನದ ರುಜುವಾತನ್ನು ನಮೂದಿಸಿ"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"ಭಾಗಶಃ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಪತ್ತೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಕೊಳೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಅದನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"ಬೆರಳನ್ನು ಅತಿ ವೇಗವಾಗಿ ಸರಿಸಲಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ಬೆರಳನ್ನು ತುಂಬಾ ನಿಧಾನವಾಗಿ ಸರಿಸಲಾಗಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಮಾಣೀಕರಣ ಮಾಡಲಾಗಿದೆ"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ, ದೃಢೀಕರಣವನ್ನು ಒತ್ತಿ"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಹಾರ್ಡ್ವೇರ್ ಲಭ್ಯವಿಲ್ಲ."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸಂಗ್ರಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ತೆಗೆದುಹಾಕಿ."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ಬಳಕೆದಾರರು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಪಡಿಸಿದ್ದಾರೆ."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ಫೇಸ್ ಅನ್ಲಾಕ್"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ನಿಮ್ಮ ಮುಖವನ್ನು ಮರುನೋಂದಣಿ ಮಾಡಿ"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ಗುರುತಿಸುವಿಕೆಯನ್ನು ಹೆಚ್ಚಿಸಲು ನಿಮ್ಮ ಮುಖವನ್ನು ಮರುನೋಂದಣಿ ಮಾಡಿ"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"ಸರಿಯಾಗಿ ಮುಖ ಕ್ಯಾಪ್ಚರ್ ಮಾಡಲಾಗಲಿಲ್ಲ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"ತುಂಬಾ ಪ್ರಕಾಶಮಾನವಾಗಿದೆ ಮಂದ ಪ್ರಕಾಶಮಾನವಿರುವ ಲೈಟ್ ಬಳಸಿ"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"ತುಂಬಾ ಕಪ್ಪು ಛಾಯೆಯಿದೆ. ಪ್ರಕಾಶಮಾನವಾದ ಲೈಟಿಂಗ್ ಬಳಸಿ."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"ನಕಲಿಸಲಾಗಿದೆ"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ಅನ್ನು <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ಅನ್ನು ಕ್ಲಿಪ್ಬೋರ್ಡ್ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"ಇನ್ನಷ್ಟು"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"ಮೆನು+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,8 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ಶಾರ್ಟ್ಕಟ್ ಬಳಸಿ"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ಬಣ್ಣ ವಿಲೋಮ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ಬಣ್ಣ ತಿದ್ದುಪಡಿ"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (3222994553174604132) -->
- <skip />
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ಇನ್ನಷ್ಟು ಮಬ್ಬು"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
<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>
@@ -2111,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"ಕೆಲಸ"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ವೈಯಕ್ತಿಕ ವೀಕ್ಷಣೆ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"ಕೆಲಸದ ವೀಕ್ಷಣೆ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"ಕೆಲಸದ ಆ್ಯಪ್ಗಳ ಮೂಲಕ ಇದನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ನಲ್ಲಿರುವ ಆ್ಯಪ್ಗಳ ಮೂಲಕ ಈ ವಿಷಯವನ್ನು ಹಂಚಿಕೊಳ್ಳಲು, ನಿಮ್ಮ ಐಟಿ ನಿರ್ವಾಹಕರು ಅನುಮತಿ ನೀಡುವುದಿಲ್ಲ"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳ ಮೂಲಕ ಇದನ್ನು ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ನಲ್ಲಿರುವ ಆ್ಯಪ್ಗಳ ಮೂಲಕ ಈ ವಿಷಯವನ್ನು ತೆರೆಯಲು, ನಿಮ್ಮ ಐಟಿ ನಿರ್ವಾಹಕರು ಅನುಮತಿ ನೀಡುವುದಿಲ್ಲ"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"ವೈಯಕ್ತಿಕ ಆ್ಯಪ್ಗಳ ಮೂಲಕ ಇದನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಪ್ರೊಫೈಲ್ನಲ್ಲಿರುವ ಆ್ಯಪ್ಗಳ ಮೂಲಕ ಈ ವಿಷಯವನ್ನು ಹಂಚಿಕೊಳ್ಳಲು, ನಿಮ್ಮ ಐಟಿ ನಿರ್ವಾಹಕರು ಅನುಮತಿ ನೀಡುವುದಿಲ್ಲ"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"ಇದನ್ನು ವೈಯಕ್ತಿಕ ಆ್ಯಪ್ಗಳ ಮೂಲಕ ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಪ್ರೊಫೈಲ್ನಲ್ಲಿರುವ ಆ್ಯಪ್ಗಳ ಮೂಲಕ ಈ ವಿಷಯವನ್ನು ತೆರೆಯಲು, ನಿಮ್ಮ ಐಟಿ ನಿರ್ವಾಹಕರು ಅನುಮತಿ ನೀಡುವುದಿಲ್ಲ"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಪ್ರೊಫೈಲ್ ಅನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ಆನ್ ಮಾಡಿ"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಯಾವುದೇ ಆ್ಯಪ್ಗಳು ಈ ವಿಷಯವನ್ನು ಬೆಂಬಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಯಾವುದೇ ಆ್ಯಪ್ಗಳು ಈ ವಿಷಯವನ್ನು ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"ಯಾವುದೇ ವೈಯಕ್ತಿಕ ಆ್ಯಪ್ಗಳು ಈ ವಿಷಯವನ್ನು ಬೆಂಬಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"ಯಾವುದೇ ವೈಯಕ್ತಿಕ ಆ್ಯಪ್ಗಳು ಈ ವಿಷಯವನ್ನು ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ನೆಟ್ವರ್ಕ್ ಅನ್ಲಾಕ್ ಮಾಡುವ ಪಿನ್"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ನೆಟ್ವರ್ಕ್ ಸಬ್ಸೆಟ್ನ ಅನ್ಲಾಕ್ ಮಾಡುವ ಪಿನ್"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM ಕಾರ್ಪೊರೇಟ್ ಅನ್ಲಾಕ್ ಮಾಡುವ ಪಿನ್"</string>
@@ -2237,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನ ಭಾಗವನ್ನು ಹಿಗ್ಗಿಸಿ"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"ಈಗ ನಿಮ್ಮ ಪೂರ್ಣ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ಅಥವಾ ನಿರ್ದಿಷ್ಟ ಪ್ರದೇಶದಲ್ಲಿ ನೀವು ಹಿಗ್ಗಿಸುವಿಕೆ ಮಾಡಬಹುದು ಅಥವಾ ಈ ಎರಡು ಆಯ್ಕೆಗಳ ನಡುವೆ ಬದಲಾಯಿಸಬಹುದು."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಆನ್ ಮಾಡಿ"</string>
<string name="dismiss_action" msgid="1728820550388704784">"ವಜಾಗೊಳಿಸಿ"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"ಮುಂದುವರಿಯಲು, <b><xliff:g id="APP">%s</xliff:g></b> ಗೆ ನಿಮ್ಮ ಸಾಧನದ ಮೈಕ್ರೋಫೋನ್ನ ಪ್ರವೇಶದ ಅಗತ್ಯವಿದೆ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 08ceb30..bbac5e8 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"실행 중인 앱"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"배터리를 소모하는 앱"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"확대"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"접근성 보안 정책"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 배터리 사용 중"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"앱 <xliff:g id="NUMBER">%1$d</xliff:g>개에서 배터리 사용 중"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"탭하여 배터리 및 데이터 사용량 확인"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"신체 활동 정보에 액세스"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"카메라"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"사진 및 동영상 촬영"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"근처의 블루투스 기기"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"근처의 블루투스 기기를 찾고 연결"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"통화 기록"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"통화 기록 읽고 쓰기"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"전화"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"앱이 태블릿의 블루투스 설정을 확인하고 페어링된 기기에 연결하며 연결을 수락할 수 있도록 허용합니다."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"앱이 Android TV 기기에서 블루투스 설정을 보고 페어링된 기기에 연결하며 페어링된 기기와의 연결을 수락하도록 허용합니다."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"앱에서 휴대전화의 블루투스 설정을 확인하고 등록된 디바이스에 연결하며 연결을 수락할 수 있습니다."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"근처의 블루투스 기기를 찾고 페어링"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"앱이 근처의 블루투스 기기를 찾고 페어링하도록 허용"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"페어링된 블루투스 기기에 연결"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"앱이 페어링된 블루투스 기기에 연결하도록 허용"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"기본 NFC 결제 서비스 정보"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"앱이 등록된 AID와 경로 목적지 같은 기본 NFC 결제 서비스 정보를 확인하도록 허용합니다."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFC(Near Field Communication) 제어"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"인증 오류"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"화면 잠금 사용"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"계속하려면 기기의 사용자 인증 정보를 입력하세요"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"지문이 일부만 인식되었습니다. 다시 시도해 주세요."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"지문을 인식할 수 없습니다. 다시 시도해 주세요."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"지문 센서를 깨끗이 닦고 다시 시도하세요."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"손가락을 너무 빨리 움직였습니다. 다시 시도해 주세요."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"손가락을 너무 느리게 움직였습니다. 다시 시도해 주세요."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"지문이 인증됨"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"얼굴이 인증되었습니다"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"얼굴이 인증되었습니다. 확인을 누르세요"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"지문 인식 하드웨어를 사용할 수 없습니다."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"지문을 저장할 수 없습니다. 기존 지문을 삭제하세요."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"지문 인식 시간이 초과되었습니다. 다시 시도하세요."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"지문 인식 작업이 취소되었습니다."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"사용자가 지문 인식 작업을 취소했습니다."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"얼굴인식 잠금해제"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"얼굴 재등록 필요"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"인식률을 개선하려면 얼굴을 다시 등록하세요."</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"정확한 얼굴 데이터를 캡처하지 못했습니다. 다시 시도하세요."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"너무 밝습니다. 조명 밝기를 조금 낮춰보세요."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"너무 어둡습니다. 조명을 밝게 해 보세요."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"복사 완료"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> 앱이 <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> 앱에서 복사하여 붙여넣음"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> 앱이 클립보드에서 복사하여 붙여넣음"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"더보기"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2054,7 +2085,7 @@
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"이전에 이 알림의 중요도는 더 낮았습니다. 의견을 보내려면 탭하세요."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"루틴 모드 정보 알림"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"평소에 충전하는 시간 전에 배터리가 소진될 수 있습니다."</string>
- <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"배터리 수명을 연장하기 위해 배터리 세이버가 활성화되었습니다."</string>
+ <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"배터리 수명을 연장하기 위해 절전 모드가 활성화되었습니다."</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"절전 모드"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"절전 모드가 사용 중지되었습니다"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"휴대전화의 배터리가 충분하므로 기능이 더 이상 제한되지 않습니다"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"직장"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"개인 뷰"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"직장 뷰"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"직장 앱과 공유할 수 없음"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT 관리자가 이 콘텐츠를 직장 프로필의 앱과 공유할 수 있도록 허용하지 않았습니다."</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"직장 앱으로 열 수 없음"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT 관리자가 이 콘텐츠를 직장 프로필의 앱에서 열 수 있도록 허용하지 않았습니다."</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"개인 앱과 공유할 수 없는 콘텐츠"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT 관리자가 개인 프로필의 앱에서 이 콘텐츠를 공유하도록 허용하지 않습니다."</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"개인 앱으로 열 수 없는 콘텐츠"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT 관리자가 개인 프로필의 앱에서 이 콘텐츠를 열도록 허용하지 않습니다."</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"직장 프로필이 일시중지됨"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"사용 설정"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"이 콘텐츠를 지원하는 직장 앱이 없음"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"이 콘텐츠를 열 수 있는 직장 앱이 없음"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"이 콘텐츠를 지원하는 개인 앱이 없음"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"이 콘텐츠를 열 수 있는 개인 앱이 없음"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM 네트워크 잠금 해제 PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM 네트워크 하위 집합 잠금 해제 PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM 회사 잠금 해제 PIN"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"일부 화면 확대"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"이제 전체 화면, 특정 영역을 확대하거나 두 가지 옵션 간에 전환할 수 있습니다."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"설정에서 사용 설정"</string>
<string name="dismiss_action" msgid="1728820550388704784">"닫기"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"계속하려면 <b><xliff:g id="APP">%s</xliff:g></b>에서 기기 마이크에 액세스해야 합니다."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 034d94e..89d2398 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Колдонмо иштеп жатат"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Колдонмолор батареяңызды коротууда"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Чоңойтуу"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Атайын мүмкүнчүлүктөрдүн коопсуздугун коргоо саясаты"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу батареяны пайдаланып жатат"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> колдонмо батареяны пайдаланып жатат"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"кыймыл-аракеттериңизге көз салып турганга мүмкүнчүлүк алат"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Камера"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"сүрөт жана видео тартууга"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Жакын жердеги Bluetooth түзмөктөрү"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"жакын жердеги Bluetooth түзмөктөрүн аныктоо жана туташуу"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Чалуулар тизмеси"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"телефондогу чалуулар тизмесин окуу жана жазуу"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Телефон"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Колдонмого планшеттин Bluetooth конфигурацияларын көрүү, жупталган түзмөктөр менен байланыш түзүү жана кабыл алуу уруксатын берет."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV түзмөгүңүздөгү Bluetooth конфигурациясын көрүп, жупташтырылган түзмөктөргө туташууга жана туташуу сурамын кабыл алууга колдонмого уруксат берет."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Колдонмого телефондун Bluetooth конфигурацияларын көрүү, жупташкан түзмөктөр менен туташуу түзүү жана кабыл алуу уруксатын берет."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"жакын жердеги Bluetooth түзмөктөрүн аныктоо жана жупташтыруу"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Колдонмого жакын жердеги Bluetooth түзмөктөрүн аныктап, жупташтырууга уруксат берет"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"жупташтырылган Bluetooth түзмөктөрү"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Колдонмого жупташтырылган Bluetooth түзмөктөрү менен байланышууга уруксат берет"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Тандалган NFC төлөм кызматы жөнүндө маалымат"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Колдонмого катталган жардам же көздөлгөн жерге маршрут сыяктуу тандалган nfc төлөм кызматы жөнүндө маалыматты алууга уруксат берүү."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communication көзөмөлү"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Аутентификация катасы"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Экран кулпусун колдонуу"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Улантуу үчүн түзмөгүңүздүн эсептик дайындарын киргизиңиз"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Манжа изи жарым-жартылай аныкталды. Кайталап көрүңүз."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Манжа изи иштелбей койду. Кайталап көрүңүз."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Манжа изинин сенсору кирдеп калган. Тазалап, кайталап көрүңүз."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Манжаңызды өтө тез жылдырдыңыз. Кайталап көрүңүз."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Манжа өтө жай жылды. Кайталап көрүңүз."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Манжа изи текшерилди"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Жүздүн аныктыгы текшерилди"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Жүздүн аныктыгы текшерилди, эми \"Ырастоону\" басыңыз"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Манжа изинин аппараттык камсыздоосу жеткиликтүү эмес."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Манжа изин сактоо мүмкүн эмес. Учурдагы манжа изин алып салыңыз."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Манжа изин күтүү мөөнөтү бүттү. Кайталап көрүңүз."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Манжа изи иш-аракети жокко чыгарылды."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Манжа изи операциясын колдонуучу жокко чыгарды."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Жүзүнөн таануу"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Жүзүңүздү кайра таанытыңыз."</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Мыкты таануу үчүн, жүзүңүздү кайра таанытыңыз"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Жүзүңүз жакшы тартылган жок. Кайталап көрүңүз."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Өтө жарык. Жарыктыкты азайтып көрүңүз."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Өтө караңгы. Жарыгыраак жерден тартып көрүңүз."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Көчүрүлдү"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> колдонмосунан чапталды"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> алмашуу буферинен чапталды"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Дагы"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Меню+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Жумуш"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Жеке көрүнүш"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Жумуш көрүнүшү"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Бул нерсени жумуш колдонмолору аркылуу бөлүшүүгө болбойт"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT администраторуңуз бул нерсени жумуш профилиңиздеги колдонмолор аркылуу бөлүшүүгө тыюу салды"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Жумуш колдонмолору менен ачууга болбойт"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT администраторуңуз бул нерсени жумуш профилиңиздеги колдонмолор менен ачууга тыюу салды"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Бул мазмунду жеке колдонмолор аркылуу бөлүшүүгө болбойт"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT администраторуңуз бул нерсени жеке профилиңиздеги колдонмолор аркылуу бөлүшүүгө тыюу салды"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Жеке колдонмолор менен ачууга болбойт"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT администраторуңуз бул нерсени жеке профилиңиздеги колдонмолор менен ачууга тыюу салды"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Жумуш профили тындырылган"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Күйгүзүү"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Бул нерсени колдоого ала турган жумуш колдонмолору жок"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Бул нерсени ача турган жумуш колдонмолору жок"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Жеке колдонмолор бул мазмунду колдоого алышпайт"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Жеке колдонмолор бул мазмунду ача алышпайт"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM карта тармагынын кулпусун ачуучу PIN код"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM кичи тармагынын кулпусун ачуучу PIN код"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM картанын корпоративдик кулпусун ачуучу PIN код"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Экрандын бир бөлүгүн чоңойтуу"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Эми толук экранды же анын бөлүгүн чоңойтуп, же болбосо, эки параметрди которуштуруп колдоно аласыз."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Жөндөөлөрдөн күйгүзүү"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Жабуу"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Улантуу үчүн <b><xliff:g id="APP">%s</xliff:g></b> колдонмосуна түзмөгүңүздүн микрофонун пайдаланууга уруксат беришиңиз керек."</string>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 42c2c69..ca549ae 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -30,9 +30,7 @@
<!-- Height of the status bar -->
<dimen name="status_bar_height">@dimen/status_bar_height_landscape</dimen>
<!-- Height of area above QQS where battery/time go -->
- <dimen name="quick_qs_offset_height">@dimen/status_bar_height_landscape</dimen>
- <!-- Total height of QQS in landscape, this is effectively status_bar_height_landscape + 128 -->
- <dimen name="quick_qs_total_height">152dp</dimen>
+ <dimen name="quick_qs_offset_height">48dp</dimen>
<!-- Default height of an action bar. -->
<dimen name="action_bar_default_height">40dip</dimen>
<!-- Vertical padding around action bar icons. -->
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index ad56f88..8baca08 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ແອັບກຳລັງເຮັດວຽກ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ແອັບທີ່ກຳລັງໃຊ້ແບັດເຕີຣີ"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ການຂະຫຍາຍ"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"ນະໂຍບາຍຄວາມປອດໄພການຊ່ວຍເຂົ້າເຖິງ"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ແອັບກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດການນຳໃຊ້ແບັດເຕີຣີ ແລະ ອິນເຕີເນັດ"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ເຂົ້າເຖິງກິດຈະກຳທາງກາຍະພາບຂອງທ່ານ"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"ກ້ອງ"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ຖ່າຍຮູບ ແລະບັນທຶກວິດີໂອ"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"ອຸປະກອນ Bluetooth ທີ່ຢູ່ໃກ້ຄຽງ"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"ຄົ້ນພົບ ແລະ ເຊື່ອມຕໍ່ຫາອຸປະກອນ Bluetooth ທີ່ຢູ່ໃກ້ຄຽງ"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"ບັນທຶກການໂທ"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ອ່ານ ແລະ ຂຽນບັນທຶກການໂທ"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ໂທລະສັບ"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ອະນຸຍາດໃຫ້ແອັບຯເບິ່ງການຕັ້ງຄ່າຂອງ Bluetooth ໃນແທັບເລັດ ຕະຫຼອດຈົນເຊື່ອມຕໍ່ ແລະຍອມຮັບການເຊື່ອມຕໍ່ກັບອຸປະກອນທີ່ຈັບຄູ່ກັນແລ້ວ."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ອະນຸຍາດໃຫ້ແອັບເບິ່ງການຕັ້ງຄ່າ Bluetooth ຢູ່ອຸປະກອນ Android TV ຂອງທ່ານ ແລະ ຕອບຮັບການເຊື່ອມຕໍ່ກັບອຸປະກອນທີ່ຈັບຄູ່ໄວ້."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ອະນຸຍາດໃຫ້ແອັບຯເບິ່ງການຕັ້ງຄ່າຂອງ Bluetooth ໃນໂທລະສັບ, ຮວມທັງໃຫ້ສ້າງ ແລະຮັບການເຊື່ອມຕໍ່ຈາກອຸປະກອນທີ່ຈັບຄູ່ກັນ."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"ຄົ້ນພົບ ແລະ ຈັບຄູ່ອຸປະກອນ Bluetooth ທີ່ຢູ່ໃກ້ຄຽງ"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"ອະນຸຍາດໃຫ້ແອັບຄົ້ນພົບ ແລະ ຈັບຄູ່ອຸປະກອນ Bluetooth ທີ່ຢູ່ໃກ້ຄຽງໄດ້"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"ເຊື່ອມຕໍ່ຫາອຸປະກອນ Bluetooth ທີ່ຈັບຄູ່ໄວ້"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"ອະນຸຍາດໃຫ້ແອັບເຊື່ອມຕໍ່ຫາອຸປະກອນ Bluetooth ທີ່ຈັບຄູ່ແລ້ວໄດ້"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ຂໍ້ມູນບໍລິການການຈ່າຍເງິນ NFC ທີ່ຕ້ອງການ"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ອະນຸຍາດໃຫ້ແອັບຮັບຂໍ້ມູນບໍລິການການຈ່າຍເງິນ NFC ທີ່ຕ້ອງການໄດ້ ເຊັ່ນ: ການຊ່ວຍເຫຼືອແບບລົງທະບຽນ ແລະ ປາຍທາງເສັ້ນທາງ."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ຄວບຄຸມ Near Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"ເກີດຄວາມຜິດພາດໃນການພິສູດຢືນຢັນ"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ໃຊ້ການລັອກໜ້າຈໍ"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"ລະບຸຂໍ້ມູນການເຂົ້າສູ່ລະບົບອຸປະກອນຂອງທ່ານເພື່ອດຳເນີນການຕໍ່"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"ກວດພົບລາຍນີ້ວມືບາງສ່ວນແລ້ວ. ກະລຸນາລອງໃໝ່ອີກ."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ບໍ່ສາມາດດຳເນີນການລາຍນີ້ວມືໄດ້. ກະລຸນາລອງໃໝ່ອີກ."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"ເຊັນເຊີລາຍນີ້ວມືເປື້ອນ. ກະລຸນາທຳຄວາມສະອາດ ແລະລອງໃໝ່ອີກ."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"ຍ້າຍນີ້ວມືໄປໄວເກີນໄປ. ກະລຸນາລອງໃໝ່ອີກ."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ຍ້າຍນີ້ວມືໄປຊ້າເກີນໄປ. ກະລຸນາລອງໃໝ່ອີກ."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"ພິສູດຢືນຢັນລາຍນິ້ວມືແລ້ວ"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ, ກະລຸນາກົດຢືນຢັນ"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ບໍ່ມີຮາດແວລາຍນີ້ວມືໃຫ້ຢູ່."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ບໍ່ສາມາດເກັບຮັກສາລາຍນີ້ວມືໄວ້ໄດ້. ກະລຸນາເອົາລາຍນີ້ວມືທີ່ມີຢູ່ອອກໄປ."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"ເວລາລາຍນີ້ວມືບໍ່ເຂົ້າເຖິງໄດ້. ລອງໃໝ່ອີກ."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ຍົກເລີກການດຳເນີນການລາຍນີ້ວມືແລ້ວ."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ຜູ້ໃຊ້ໄດ້ຍົກເລີກຄຳສັ່ງລາຍນິ້ວມືແລ້ວ."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ປົດລັອກດ້ວຍໜ້າ"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ລົງທະບຽນໃບໜ້າຂອງທ່ານຄືນໃໝ່"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ເພື່ອປັບປຸງການຈຳແນກ, ກະລຸນາລົງທະບຽນໃບໜ້າຂອງທ່ານຄືນໃໝ່."</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"ບໍ່ສາມາດບັນທຶກຂໍ້ມູນໃບໜ້າທີ່ຖືກຕ້ອງໄດ້. ກະລຸນາລອງໃໝ່."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"ແຈ້ງເກີນໄປ. ລອງຄ່ອຍແສງໄຟລົງ."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"ມືດເກີນ. ກະລຸນາລອງໃຊ້ສະພາບແສງທີ່ແຈ້ງຂຶ້ນ."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"ສຳເນົາແລ້ວ"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"ວາງ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ຈາກ <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> ແລ້ວ"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"ວາງ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ຈາກຄລິບບອດແລ້ວ"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"ເພີ່ມເຕີມ"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"ເມນູ+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"ວຽກ"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ມຸມມອງສ່ວນຕົວ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"ມຸມມອງວຽກ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"ບໍ່ສາມາດແບ່ງປັນກັບແອັບວຽກໄດ້"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"ຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ທ່ານແບ່ງປັນເນື້ອຫານີ້ດ້ວຍແອັບໃນໂປຣໄຟລ໌ວຽກຂອງທ່ານ"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"ບໍ່ສາມາດເປີດດ້ວຍແອັບວຽກໄດ້"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"ຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ທ່ານເປີດເນື້ອຫານີ້ດ້ວຍແອັບໃນໂປຣໄຟລ໌ວຽກຂອງທ່ານ"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"ບໍ່ສາມາດແບ່ງປັນກັບແອັບສ່ວນຕົວໄດ້"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"ຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ທ່ານແບ່ງປັນເນື້ອຫານີ້ກັບແອັບໃນໂປຣໄຟລ໌ສ່ວນຕົວຂອງທ່ານ"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"ບໍ່ສາມາດເປີດດ້ວຍແອັບສ່ວນຕົວໄດ້"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"ຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ທ່ານເປີດເນື້ອຫານີ້ກັບແອັບໃນໂປຣໄຟລ໌ສ່ວນຕົວຂອງທ່ານ"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"ຢຸດໂປຣໄຟລ໌ວຽກໄວ້ຊົ່ວຄາວແລ້ວ"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ເປີດໃຊ້"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"ບໍ່ມີແອັບວຽກທີ່ຮອງຮັບເນື້ອຫານີ້"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ບໍ່ມີແອັບວຽກທີ່ສາມາດເປີດເນື້ອຫານີ້ໄດ້"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"ບໍ່ມີແອັບສ່ວນຕົວທີ່ຮອງຮັບເນື້ອຫານີ້"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"ບໍ່ມີແອັບສ່ວນຕົວທີ່ສາມາດເປີດເນື້ອຫານີ້ໄດ້"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN ປົດລັອກເຄືອຂ່າຍຊິມ"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN ການປົດລັອກຊຸດຍ່ອຍເຄືອຂ່າຍຊິມ"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN ປົດລັອກ SIM ອົງການ"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"ຂະຫຍາຍບາງສ່ວນຂອງໜ້າຈໍທ່ານ"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"ຕອນນີ້ທ່ານສາມາດຂະຫຍາຍເນື້ອຫາແບບເຕັມຈໍຂອງທ່ານ, ພື້ນທີ່ສະເພາະ ຫຼື ສະຫຼັບລະຫວ່າງຕົວເລືອກທັງສອງໄດ້ແລ້ວ."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ເປີດໃຊ້ໃນການຕັ້ງຄ່າ"</string>
<string name="dismiss_action" msgid="1728820550388704784">"ປິດໄວ້"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"ເພື່ອດຳເນີນການຕໍ່, <b><xliff:g id="APP">%s</xliff:g></b> ຕ້ອງການສິດເຂົ້າເຖິງໄມໂຄຣໂຟນອຸປະກອນທ່ານ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 1ae2996..aac2dc6 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -300,7 +300,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Programa paleista"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programos, naudojančios akumuliatoriaus energiją"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Didinimas"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Pritaikomumo saugos politika"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ naudoja akumuliatoriaus energiją"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programų, naudojančių akumuliatoriaus energiją: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Palieskite ir sužinokite išsamios informacijos apie akumuliatoriaus bei duomenų naudojimą"</string>
@@ -325,6 +326,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"galimybė pasiekti fizinę veiklą"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Fotoaparatas"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"fotografuoti ir filmuoti"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"„Bluetooth“ įrenginiai netoliese"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"aptikti „Bluetooth“ įrenginius netoliese ir prisijungti prie jų"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Skambučių žurnalai"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"skaityti ir rašyti telefono skambučių žurnalą"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefonas"</string>
@@ -538,6 +541,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Leidžiama programai peržiūrėti „Bluetooth“ konfigūraciją planšetiniame kompiuteryje ir užmegzti bei priimti ryšius iš susietų įrenginių."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Programai leidžiama peržiūrėti „Bluetooth“ konfigūraciją „Android TV“ įrenginyje ir užmegzti bei priimti ryšius iš susietų įrenginių."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Leidžiama programai peržiūrėti „Bluetooth“ konfigūraciją telefone ir užmegzti bei priimti ryšius iš susietų įrenginių."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"„Bluetooth“ įr. netoliese aptikimas ir susiejimas"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Leidžiama programai aptikti ir susieti „Bluetooth“ įrenginius netoliese"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"prisijungimas prie susietų „Bluetooth“ įrenginių"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Leidžiama programai prisijungti prie susietų „Bluetooth“ įrenginių"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Pageidaujama ARL mokėjimo paslaugos informacija"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Programai leidžiama gauti pageidaujamą ARL mokamos paslaugos informaciją, pvz., užregistruotą pagalbą ir maršrutų tikslus."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"valdyti artimo lauko perdavimą (angl. „Near Field Communication“)"</string>
@@ -573,18 +580,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Autentifikuojant įvyko klaida"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Naudoti ekrano užraktą"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Jei norite tęsti, įveskite įrenginio prisijungimo duomenis"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Aptiktas dalinis piršto antspaudas. Bandykite dar kartą."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Nepavyko apdoroti piršto antspaudo. Bandykite dar kartą."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Piršto antspaudo jutiklis purvinas. Nuvalykite ir bandykite dar kartą."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Per greitai judinate pirštą. Bandykite dar kartą."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Per lėtai judinate pirštą. Bandykite dar kartą."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Piršto antspaudas autentifikuotas"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Veidas autentifikuotas"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Veidas autentifikuotas, paspauskite patvirtinimo mygtuką"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Piršto antspaudo aparatinė įranga nepasiekiama."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Negalima išsaugoti piršto antspaudo. Pašalinkite esamą piršto antspaudą."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Baigėsi piršto antspaudo nustatymo skirtasis laikas. Bandykite dar kartą."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Piršto antspaudo operacija atšaukta."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Piršto antspaudo operaciją atšaukė naudotojas."</string>
@@ -609,6 +626,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Atrakinimas pagal veidą"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Pakartotinis veido registravimas"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Kad patobulintumėte atpažinimą, iš naujo užregistruokite veidą"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Neužfiks. tikslūs veido duom. Bandykite dar kartą."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Per šviesu. Išbandykite mažesnį apšvietimą."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Per tamsu. Išbandykite šviesesnį apšvietimą."</string>
@@ -1012,6 +1037,12 @@
<string name="copied" msgid="4675902854553014676">"Nukopijuota"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"„<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>“ įklijuota iš „<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>“"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"„<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>“ įklijuota iš iškarpinės"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Daugiau"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Meniu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"„Meta“ +"</string>
@@ -2178,20 +2209,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Darbo"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Asmeninė peržiūra"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Darbo peržiūra"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Negalima bendrinti su darbo programomis"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT administratorius neleidžia bendrinti šio turinio naudojant programas jūsų darbo profilyje"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Negalima atidaryti naudojant darbo programas"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT administratorius neleidžia atidaryti šio turinio naudojant programas jūsų darbo profilyje"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Negalima bendrinti su asmeninėmis programomis"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT administratorius neleidžia bendrinti šio turinio naudojant programas jūsų asmeniniame profilyje"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Negalima atidaryti naudojant asmenines programas"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT administratorius neleidžia atidaryti šio turinio naudojant programas jūsų asmeniniame profilyje"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Darbo profilis pristabdytas"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Įjungti"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Jokios darbo programos nepalaiko šio turinio"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Jokiose darbo programose negalima atidaryti šio turinio"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Jokios asmeninės programos nepalaiko šio turinio"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Jokiose asmeninėse programose negalima atidaryti šio turinio"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM tinklo operatoriaus pasirinkimo ribojimo panaikinimo PIN kodas"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM tinklo poaibio operatoriaus pasirinkimo ribojimo panaikinimo PIN kodas"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM bendrojo operatoriaus pasirinkimo ribojimo panaikinimo PIN kodas"</string>
@@ -2304,8 +2346,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Ekrano dalies didinimas"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Dabar galite padidinti visą ekraną, konkrečią sritį ar perjungti abi parinktis."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Įjungti nustatymuose"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Atmesti"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Kad būtų galima tęsti, <b><xliff:g id="APP">%s</xliff:g></b> reikalinga prieiga prie įrenginio mikrofono."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index f011815..d4b2f7e8 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -297,7 +297,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Lietotne darbojas"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Lietotnes, kas patērē akumulatora jaudu"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Palielinājums"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Pieejamības drošības politika"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> izmanto akumulatoru"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> lietotne(-es) izmanto akumulatoru"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pieskarieties, lai skatītu detalizētu informāciju par akumulatora un datu lietojumu"</string>
@@ -322,6 +323,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"piekļūt jūsu fiziskajām aktivitātēm"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"uzņemt attēlus un ierakstīt videoklipus"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Tuvumā esošas Bluetooth ierīces"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"atrast tuvumā esošas Bluetooth ierīces un izveidot savienojumu ar tām"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Zvanu žurnāli"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"lasīt un rakstīt tālruņa zvanu žurnālu"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Tālrunis"</string>
@@ -535,6 +538,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Ļauj lietotnei skatīt Bluetooth konfigurāciju planšetdatorā, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Ļauj lietotnei skatīt Bluetooth konfigurāciju Android TV ierīcē, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Ļauj lietotnei skatīt Bluetooth konfigurāciju tālrunī, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"atrast un savienot pārī Bluetooth ierīces tuvumā"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Ļauj lietotnei atrast un savienot pārī tuvumā esošas Bluetooth ierīces."</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"piekļūt pārī savienotām Bluetooth ierīcēm"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Ļauj lietotnei piekļūt pārī savienotām Bluetooth ierīcēm."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informācija par vēlamo NFC maksājumu pakalpojumu"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Ļauj lietotnei iegūt informāciju par vēlamo NFC maksājumu pakalpojumu, piemēram, par reģistrētajiem lietojumprogrammu ID un maršruta galamērķi."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrolē tuvlauka saziņu"</string>
@@ -570,18 +577,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Autentifikācijas kļūda"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekrāna bloķēšanas metodes izmantošana"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Lai turpinātu, ievadiet savas ierīces akreditācijas datus"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Noteikts daļējs pirksta nospiedums. Lūdzu, mēģiniet vēlreiz."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Nevarēja apstrādāt pirksta nospiedumu. Lūdzu, mēģiniet vēlreiz."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Pirkstu nospiedumu sensors ir netīrs. Lūdzu, notīriet to un mēģiniet vēlreiz."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Pārāk ātra pirksta kustība. Lūdzu, mēģiniet vēlreiz."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Pārāk lēna pirksta kustība. Lūdzu, mēģiniet vēlreiz."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Pirksta nospiedums tika autentificēts."</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Seja autentificēta"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Seja ir autentificēta. Nospiediet pogu Apstiprināt."</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Nospieduma aparatūra nav pieejama."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Pirkstu nospiedumu nevar saglabāt. Lūdzu, noņemiet esošu pirksta nospiedumu."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Pirkstu nospiedumu nolasīšanas aparatūras noildze. Mēģiniet vēlreiz."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Nospieduma darbība neizdevās."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Lietotājs atcēla pirksta nospieduma darbību."</string>
@@ -606,6 +623,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Autorizācija pēc sejas"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Atkārtoti reģistrējiet seju"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Lai uzlabotu atpazīšanu, lūdzu, atkārtoti reģistrējiet savu seju"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Neizdevās tvert sejas datus. Mēģiniet vēlreiz."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Pārāk spilgts. Izmēģiniet maigāku apgaismojumu."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Pārāk tumšs. Izmēģiniet spožāku apgaismojumu."</string>
@@ -1009,6 +1034,12 @@
<string name="copied" msgid="4675902854553014676">"Nokopēts"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Lietotnē <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> tika ielīmēti dati no lietotnes <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>."</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Lietotnē <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> tika ielīmēti dati no starpliktuves."</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Vairāk"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Izvēlne+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta taustiņš +"</string>
@@ -2144,20 +2175,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Darba profils"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personisks skats"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Darba skats"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Šo saturu nevar kopīgot, izmantojot darba lietotnes"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Jūsu IT administrators neatļauj kopīgot šo saturu, izmantojot jūsu darba profila lietotnes."</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Šo saturu nevar atvērt, izmantojot darba lietotnes"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Jūsu IT administrators neatļauj atvērt šo saturu, izmantojot jūsu darba profila lietotnes."</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Šo saturu nevar kopīgot, izmantojot personīgās lietotnes"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Jūsu IT administrators neatļauj kopīgot šo saturu, izmantojot jūsu personīgā profila lietotnes."</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Šo saturu nevar atvērt, izmantojot personīgās lietotnes"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Jūsu IT administrators neatļauj atvērt šo saturu, izmantojot jūsu personīgā profila lietotnes."</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Darba profila darbība ir apturēta."</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Ieslēgt"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Darba lietotnes nevar atbalstīt šo saturu."</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Šo saturu nevar atvērt darba lietotnēs."</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Personīgās lietotnes nevar atbalstīt šo saturu."</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Šo saturu nevar atvērt personīgajās lietotnēs."</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM tīkla atbloķēšanas PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM tīkla apakškopas atbloķēšanas PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM Corporate atbloķēšanas PIN"</string>
@@ -2270,8 +2312,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Ekrāna daļas palielināšana"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Tagad varat palielināt visu ekrānu vai noteiktu apgabalu vai pāriet starp abām iespējām."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ieslēgt sadaļā Iestatījumi"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Nerādīt"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Lai turpinātu, lietotnei <b><xliff:g id="APP">%s</xliff:g></b> nepieciešama piekļuve jūsu ierīces mikrofonam."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index bbd9d9d..99a888d 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Апликацијата работи"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликации што ја трошат батеријата"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Зголемување"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Политика за безбедност на „Пристапност“"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерија"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апликации користат батерија"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Допрете за детали за батеријата и потрошениот сообраќај"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"пристапете до вашата физичка активност"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Камера"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"фотографира и снима видео"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Уреди со Bluetooth во близина"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"да открива и да се поврзува со уреди со Bluetooth во близина"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Евиденција на повици"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"чита и пишува евиденција на повици во телефонот"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Телефон"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Овозможува апликацијата да ја види конфигурацијата на Bluetooth на таблетот и да прави и да прифаќа врски со спарени уреди."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Дозволува апликацијата да ја прикажува конфигурацијата на Bluetooth на вашиот уред Android TV и да прави и прифаќа врски со спарените уреди."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Овозможува апликацијата да ја види конфигурацијата на Bluetooth на телефонот и да прави и да прифаќа врски со спарени уреди."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"да открива и спарува уреди со Bluetooth во близина"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Дозволува апликацијата да открива и да се поврзува со спарени уреди со Bluetooth во близина"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"да се поврзува со спарени уреди со Bluetooth"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Дозволува апликацијата да се поврзува со спарени уреди со Bluetooth"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Информации за претпочитаната услуга за плаќање преку NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дозволува апликацијата да добие информации за претпочитаната услуга за плаќање преку NFC, како регистрирани помагала и дестинација на маршрутата."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"контролирај комуникација на блиско поле"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Грешка при проверката"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Користи заклучување екран"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Внесете го акредитивот на уредот за да продолжите"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Откриен е делумен отпечаток. Обидете се повторно."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Отпечатокот не може да се обработи. Обидете се повторно."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Сензорот за отпечатоци е валкан. Исчистете го и обидете се повторно."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Прстот се движеше пребрзо. Обидете се повторно."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Прстот се движеше премногу бавно. Обидете се повторно."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Отпечатокот е проверен"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лицето е проверено"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицето е проверено, притиснете го копчето „Потврди“"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Хардверот за отпечатоци не е достапен."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Отпечатокот не може да се складира. Отстранете некој од постојните отпечатоци."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Се достигна времето на истекување на отпечатокот. Обидете се повторно."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Операцијата со отпечаток се откажа."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Корисникот ја откажа потврдата со отпечаток."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Отклучување со лик"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Повторно регистрирајте го ликот"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"За да се подобри препознавањето, повторно регистрирајте го ликот"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Не се сними прецизна слика. Обидете се повторно."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Премногу светла. Пробајте со послабо осветлување."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Премногу темна. Пробајте со посилно осветлување."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Копирано"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> залепи од <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> залепи од привремената меморија"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Повеќе"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Мени+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"копче Meta+"</string>
@@ -1949,8 +1980,8 @@
<string name="profile_encrypted_message" msgid="1128512616293157802">"Допрете за да го отклучите"</string>
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Поврзан на <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Допрете за да ги погледнете датотеките"</string>
- <string name="pin_target" msgid="8036028973110156895">"Прикачете"</string>
- <string name="pin_specific_target" msgid="7824671240625957415">"Прикачи <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="pin_target" msgid="8036028973110156895">"Закачи"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Закачи <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Откачете"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"Откачи <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Информации за апликација"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Службени"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Личен приказ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Работен приказ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Ова не може да се споделува со работни апликации"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT-администраторот не ви дозволува да ги споделувате овие содржини со апликации од вашиот работен профил"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Ова не може да се отвора со работни апликации"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT-администраторот не ви дозволува да ги отворате овие содржини со апликации од вашиот работен профил"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Ова не може да се споделува со лични апликации"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT-администраторот не ви дозволува да ги споделувате овие содржини со апликации од вашиот личен профил"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Ова не може да се отвора со лични апликации"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT-администраторот не ви дозволува да ги отворате овие содржини со апликации од вашиот личен профил"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Работниот профил е паузиран"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Вклучи"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Нема работни апликации што може да ги поддржат овие содржини"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Нема работни апликации што може да ги отворат овие содржини"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Нема лични апликации што може да ги поддржат овие содржини"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Нема лични апликации што може да ги отворат овие содржини"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN за отклучување на мрежата на SIM-картичката"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN за отклучување на подмножество на мрежата на SIM-картичката"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN за отклучување на корпоративната SIM-картичка"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Зголемете дел од екранот"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Отсега може да го зголемувате вашиот цел екран, конкретна област или да се префрлате помеѓу двете опции."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Вклучи во „Поставки“"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Отфрли"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"За да продолжи, на <b><xliff:g id="APP">%s</xliff:g></b> ѝ е потребен пристап до микрофонот на уредот."</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index cfc112a..45a99f1 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ആപ്പ് പ്രവർത്തിക്കുന്നു"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"മാഗ്നിഫിക്കേഷൻ"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"ഉപയോഗസഹായി സുരക്ഷാ നയം"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ബാറ്ററി, ഡാറ്റ ഉപയോഗം എന്നിവയുടെ വിശദാംശങ്ങളറിയാൻ ടാപ്പുചെയ്യുക"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ശാരീരിക പ്രവർത്തനം ആക്സസ് ചെയ്യുക"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"ക്യാമറ"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ചിത്രങ്ങളെടുത്ത് വീഡിയോ റെക്കോർഡുചെയ്യുക"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"സമീപമുള്ള Bluetooth ഉപകരണങ്ങൾ"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"സമീപമുള്ള Bluetooth ഉപകരണങ്ങൾ കണ്ടെത്തി കണക്റ്റ് ചെയ്യുക"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"കോൾ ലോഗ്"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ഫോൺ കോൾ ലോഗ് വായിക്കുകയും എഴുതുകയും ചെയ്യുക"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ഫോണ്"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ടാബ്ലെറ്റിലെ ബ്ലൂടൂത്ത് കോൺഫിഗറേഷൻ കാണാനും ജോടിയാക്കിയ ഉപകരണങ്ങളുമായി കണക്ഷനുകൾ നടത്തി അംഗീകരിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"നിങ്ങളുടെ Android TV-യിലെ Bluetooth കോൺഫിഗറേഷൻ കാണാനും ജോടിയാക്കിയ ഉപകരണങ്ങളുമായി കണക്ഷനുകൾ സൃഷ്ടിക്കാനും അംഗീകരിക്കാനും ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ഫോണിലെ ബ്ലൂടൂത്ത് കോൺഫിഗറേഷൻ കാണാനും ജോടിയാക്കിയ ഉപകരണങ്ങളുമായി കണക്ഷനുകൾ നടത്തി അംഗീകരിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"സമീപ Bluetooth ഉപകരണങ്ങൾ കണ്ടെത്തി കണക്റ്റ് ചെയ്യൂ"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"സമീപമുള്ള Bluetooth ഉപകരണങ്ങൾ കണ്ടെത്താനും ജോടിയാക്കാനും ആപ്പിനെ അനുവദിക്കുന്നു"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"ജോടിയായ Bluetooth ഉപകരണങ്ങളിലേക്ക് കണക്റ്റ് ചെയ്യൂ"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"ജോടിയാക്കിയ Bluetooth ഉപകരണങ്ങളിലേക്ക് കണക്റ്റ് ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"തിരഞ്ഞെടുത്ത NFC പേയ്മെന്റ് സേവനത്തെ സംബന്ധിച്ച വിവരങ്ങൾ"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"റൂട്ട് ലക്ഷ്യസ്ഥാനം, രജിസ്റ്റർ ചെയ്തിരിക്കുന്ന സഹായങ്ങൾ എന്നിവ പോലുള്ള, തിരഞ്ഞെടുത്ത NFC പേയ്മെന്റ് സേവനത്തെ സംബന്ധിച്ച വിവരങ്ങൾ ലഭിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"സമീപ ഫീൽഡുമായുള്ള ആശയവിനിമയം നിയന്ത്രിക്കുക"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"പിശക് പരിശോധിച്ചുറപ്പിക്കുന്നു"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"തുടരാൻ നിങ്ങളുടെ ഉപകരണ ക്രെഡൻഷ്യലുകൾ നൽകുക"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"ഫിംഗർപ്രിന്റ് ഭാഗികമായി തിരിച്ചറിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ഫിംഗർപ്രിന്റ് പ്രോസസ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെളിയുണ്ട്. അത് വൃത്തിയാക്കി വീണ്ടും ശ്രമിക്കുക."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"വിരൽ വളരെ വേഗത്തിൽ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"വിരൽ വളരെ പതുക്കെ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"ഫിംഗർപ്രിന്റ് പരിശോധിച്ചുറപ്പിച്ചു"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു, സ്ഥിരീകരിക്കുക അമർത്തുക"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ഫിംഗർപ്രിന്റ് ഹാർഡ്വെയർ ലഭ്യമല്ല."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ഫിംഗർപ്രിന്റ് സംഭരിക്കാനാവില്ല. നിലവിലുള്ള ഫിംഗർപ്രിന്റ് നീക്കംചെയ്യുക."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"ഫിംഗർപ്രിന്റ് നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ഫിംഗർപ്രിന്റ് പ്രവർത്തനം റദ്ദാക്കി."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ഉപയോക്താവ് റദ്ദാക്കിയ ഫിംഗർപ്രിന്റ് പ്രവർത്തനം."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക്"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"നിങ്ങളുടെ മുഖം വീണ്ടും എൻറോൾ ചെയ്യൂ"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"തിരിച്ചറിയൽ മെച്ചപ്പെടുത്താൻ, നിങ്ങളുടെ മുഖം ദയവായി വീണ്ടും എൻറോൾ ചെയ്യൂ"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"കൃത്യ മുഖ ഡാറ്റ എടുക്കാനായില്ല. വീണ്ടും ശ്രമിക്കൂ."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"വളരെയധികം തെളിച്ചം. സൗമ്യതയേറിയ പ്രകാശം ശ്രമിക്കൂ."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"വളരെ ഇരുണ്ടത്. തിളക്കമേറിയ ലൈറ്റിംഗ് പരീക്ഷിക്കുക."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"പകർത്തി"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> എന്നതിൽ നിന്ന് <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ഒട്ടിച്ചു"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"ക്ലിപ്ബോർഡിൽ നിന്ന് <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ഒട്ടിച്ചു"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"കൂടുതൽ"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"മെനു+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"മെറ്റ+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"ഔദ്യോഗികം"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"വ്യക്തിപര കാഴ്ച"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"ഔദ്യോഗിക കാഴ്ച"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"ഔദ്യോഗിക ആപ്പുകൾ ഉപയോഗിച്ച് ഇത് പങ്കിടാനാവില്ല"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫെെലിലെ ആപ്പുകൾ ഉപയോഗിച്ച് ഈ ഉള്ളടക്കം പങ്കിടാൻ ഐടി അഡ്മിൻ അനുവദിക്കുന്നില്ല"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"ഔദ്യോഗിക ആപ്പുകൾ ഉപയോഗിച്ച് ഇത് തുറക്കാനാവില്ല"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫെെലിലെ ആപ്പുകൾ ഉപയോഗിച്ച് ഈ ഉള്ളടക്കം തുറക്കാൻ ഐടി അഡ്മിൻ അനുവദിക്കുന്നില്ല"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"വ്യക്തിപര ആപ്പുകൾ ഉപയോഗിച്ച് ഇത് പങ്കിടാനാവില്ല"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"നിങ്ങളുടെ വ്യക്തിപര പ്രൊഫെെലിലെ ആപ്പുകൾ ഉപയോഗിച്ച് ഈ ഉള്ളടക്കം പങ്കിടാൻ ഐടി അഡ്മിൻ അനുവദിക്കുന്നില്ല"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"വ്യക്തിപര ആപ്പുകൾ ഉപയോഗിച്ച് ഇത് തുറക്കാനാവില്ല"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"നിങ്ങളുടെ വ്യക്തിപര പ്രൊഫെെലിലെ ആപ്പുകൾ ഉപയോഗിച്ച് ഈ ഉള്ളടക്കം തുറക്കാൻ ഐടി അഡ്മിൻ അനുവദിക്കുന്നില്ല"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"ഔദ്യോഗിക പ്രൊഫൈൽ തൽക്കാലം നിർത്തിയിരിക്കുന്നു"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ഓണാക്കുക"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"ഔദ്യോഗിക ആപ്പുകൾക്കൊന്നും ഈ ഉള്ളടക്കത്തെ പിന്തുണയ്ക്കാനാവില്ല"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ഔദ്യോഗിക ആപ്പുകൾക്കൊന്നും ഈ ഉള്ളടക്കം തുറക്കാനാവില്ല"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"വ്യക്തിപര ആപ്പുകൾക്കൊന്നും ഈ ഉള്ളടക്കത്തെ പിന്തുണയ്ക്കാനാവില്ല"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"വ്യക്തിപര ആപ്പുകൾക്കൊന്നും ഈ ഉള്ളടക്കം തുറക്കാനാവില്ല"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"സിം നെറ്റ്വർക്ക് അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"സിം നെറ്റ്വർക്ക് സബ്സെറ്റ് അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"സിം കോർപ്പറേറ്റ് അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"നിങ്ങളുടെ സ്ക്രീനിന്റെ ഒരു ഭാഗം മാഗ്നിഫൈ ചെയ്യുക"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"നിങ്ങൾക്ക് സ്ക്രീൻ പൂർണ്ണമായോ, ഒരു പ്രത്യേക ഭാഗമോ മാഗ്നിഫൈ ചെയ്യാം അല്ലെങ്കിൽ ഈ രണ്ട് ഓപ്ഷനുകൾക്കിടയിൽ പരസ്പരം മാറുക."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ക്രമീകരണത്തിൽ ഓണാക്കുക"</string>
<string name="dismiss_action" msgid="1728820550388704784">"ഡിസ്മിസ് ചെയ്യുക"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"തുടരാൻ, <b><xliff:g id="APP">%s</xliff:g></b> ആപ്പിന് നിങ്ങളുടെ ഉപകരണത്തിന്റെ മൈക്രോഫോണിലേക്ക് ആക്സസ് നൽകേണ്ടതുണ്ട്."</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 99c4628..bc07890 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Апп ажиллаж байна"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апп батарей ашиглаж байна"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Томруулах"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Хандалтын аюулгүй байдлын бодлого"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батерей ашиглаж байна"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апп батерей ашиглаж байна"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батерей, дата ашиглалтын талаар дэлгэрэнгүйг харахын тулд товшино уу"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"таны биеийн дасгал хөдөлгөөнд хандах"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Камер"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"зураг авах, бичлэг хийх"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Ойролцоох Bluetooth төхөөрөмжүүд"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"ойролцоох Bluetooth төхөөрөмжүүдийг илрүүлж, холбогдох"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Дуудлагын жагсаалт"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"утасны дуудлагын жагсаалтыг унших болон бичих"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Утас"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Апп нь таблет дээрх блютүүт тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Аппад таны Android TV төхөөрөмж дээрх Bluetooth-н тохируулгыг харах болон хослуулсан төхөөрөмжүүдтэй холболт хийж, холболтыг баталгаажуулахыг зөвшөөрнө."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Апп нь утсан дээрх Bluetooth тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"ойролцоох Bluetooth төхөөрөмжүүдийг илрүүлэх, хослуулах"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Aппыг ойролцоох Bluetooth төхөөрөмжүүдийг илрүүлж, хослуулахыг зөвшөөрдөг"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"хослуулсан Bluetooth төхөөрөмжүүдэд холбогдох"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Аппыг хослуулсан Bluetooth төхөөрөмжүүдэд холбогдохыг зөвшөөрдөг"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Сонгосон NFC төлбөрийн үйлчилгээний мэдээлэл"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Бүртгүүлсэн төхөөрөмж болон маршрутын хүрэх цэг зэрэг сонгосон nfc төлбөрийн үйлчилгээний мэдээллийг авахыг аппад зөвшөөрдөг."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ойролцоо талбарын холбоог удирдах"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Баталгаажуулахад алдаа гарлаа"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Дэлгэцийн түгжээг ашиглах"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Үргэлжлүүлэхийн тулд төхөөрөмжийнхөө мандат үнэмлэхийг оруулна уу"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Хурууны хээг дутуу уншуулсан байна. Дахин оролдоно уу."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Хурууны хээ боловсруулж чадахгүй байна. Дахин оролдоно уу."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Хурууны хээ мэдрэгч бохирдсон байна. Цэвэрлэсний дараа дахин оролдоно уу."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Хуруугаа хэт хурдан хөдөлгөсөн байна. Дахин оролдоно уу."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Хуруу хэт удаан хөдөлгөсөн байна. Дахин оролдоно уу."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Хурууны хээг нотолсон"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Царайг баталгаажууллаа"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Царайг баталгаажууллаа. Баталгаажуулах товчлуурыг дарна уу"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Хурууны хээний төхөөрөмж бэлэн бус байна."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Хурууны хээг хадгалах боломжгүй байна. Одоо байгаа хурууны хээг арилгана уу."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Хурууны хээ оруулах хугацаа өнгөрсөн байна. Дахин оруулна уу."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Хурууны хээний бүртгэл амжилтгүй боллоо."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Хэрэглэгч хурууны хээний баталгаажуулалтыг цуцалсан байна."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Царайгаар тайлах"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Царайгаа дахин бүртгүүлнэ үү"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Танилтыг сайжруулахын тулд царайгаа дахин бүртгүүлнэ үү"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Царайн өгөгдлийг зөв авч чадсангүй. Дахин оролдоно уу."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Хэт цайвар байна. Гэрэл багатай газар оролдоно уу."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Хэт харанхуй байна. Гэрэлтэй орчинд туршина уу."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Хуулсан"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>-с буулгасан <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Түр санах ойгоос буулгасан <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Илүү"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Цэс+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Мета+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Ажил"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Хувийн харагдах байдал"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Ажлын харагдах байдал"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Ажлын аппаар үүнийг хуваалцах боломжгүй"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Таны IT админ танд ажлын профайл дахь аппуудаа ашиглан энэ контентыг хуваалцахыг зөвшөөрөхгүй байна"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Ажлын аппаар үүнийг нээх боломжгүй"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Таны IT админ танд ажлын профайл дахь аппуудаа ашиглан энэ контентыг нээхийг зөвшөөрөхгүй байна"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Хувийн аппаар үүнийг хуваалцах боломжгүй"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Таны IT админ танд хувийн профайл дахь аппуудаа ашиглан энэ контентыг хуваалцахыг зөвшөөрөхгүй байна"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Хувийн аппаар үүнийг нээх боломжгүй"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Таны IT админ танд хувийн профайл дахь аппуудаа ашиглан энэ контентыг нээхийг зөвшөөрөхгүй байна"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Ажлын профайлыг түр зогсоосон"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Асаах"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Ажлын ямар ч апп энэ контентыг дэмжих боломжгүй"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Ажлын ямар ч апп энэ контентыг нээх боломжгүй"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Хувийн ямар ч апп энэ контентыг дэмжих боломжгүй"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Хувийн ямар ч апп энэ контентыг нээх боломжгүй"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Сүлжээний SIM-н түгжээг тайлах ПИН"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Сүлжээний дэд олонлогийн SIM-н түгжээг тайлах ПИН"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Байгууллагын SIM-н түгжээг тайлах ПИН"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Дэлгэцийнхээ хэсгийг томруулаарай"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Та одоо бүтэн дэлгэц, тодорхой хэсгээ томруулах эсвэл аль аль сонголтын хооронд сэлгэх боломжтой."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Тохиргоонд асаана уу"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Үл хэрэгсэх"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Үргэлжлүүлэхийн тулд, <b><xliff:g id="APP">%s</xliff:g></b> таны төхөөрөмжийн микрофонд хандах шаардлагатай."</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index adb86de..b63d6a7 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP चालत आहे"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"बॅटरी लवकर संपवणारी अॅप्स"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"मॅग्निफिकेशन"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"अॅक्सेसिबिलिटी सुरक्षा धोरण"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बॅटरी वापरत आहे"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> अॅप्स बॅटरी वापरत आहेत"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बॅटरी आणि डेटा वापराच्या तपशीलांसाठी टॅप करा"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"शारीरिक अॅक्टिव्हिटी अॅक्सेस करा"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"कॅमेरा"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"चित्रे काढण्याची आणि व्हिडिओ रेकॉर्ड करण्याची"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"जवळपासची ब्लूटूथ डिव्हाइस"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"जवळपासची ब्लूटूथ डिव्हाइस शोधा आणि ती कनेक्ट करा"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"कॉल लॉग"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"फोन कॉल लॉग वाचा आणि लिहा"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"फोन"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"टॅबलेटवर ब्लूटूथ चे कॉंफिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डीव्हाइससह कनेक्शन इंस्टॉल करण्यासाठी आणि स्वीकारण्यासाठी, अॅप ला अनुमती देते."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV डिव्हाइसवर ब्लूटूथ चे कॉंफिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डीव्हाइससह कनेक्शन तयार करण्यासाठी आणि स्वीकारण्यासाठी, ॲपला अनुमती देते."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"फोनवर ब्लूटूथ चे कॉंफिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डीव्हाइससह कनेक्शन इंस्टॉल करण्यासाठी आणि स्वीकारण्यासाठी, अॅप ला अनुमती देते."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"जवळपासची ब्लूटूथ डिव्हाइस शोधा आणि ती पेअर करा"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"ॲपला जवळपासची ब्लूटूथ डिव्हाइस शोधण्यासाठी आणि ती पेअर करण्यासाठी अनुमती देते"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"पेअर केलेल्या ब्लूटूथ डिव्हाइसशी कनेक्ट करा"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"पेअर केलेल्या ब्लूटूथ डिव्हाइसशी कनेक्ट करण्यासाठी ॲपला अनुमती द्या"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"प्राधान्यकृत NFC पेमेंट सेवा माहिती"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"नोंदणीकृत एड्स आणि मार्ग गंतव्यस्थान सारखी प्राधान्यकृत एनएफसी पेमेंट सेवेची माहिती मिळवण्यासाठी अॅपला अनुमती देते."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"फील्ड जवळील कम्युनिकेशन नियंत्रित करा"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"एरर ऑथेंटिकेट करत आहे"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"स्क्रीन लॉक वापरा"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"पुढे सुरू ठेवण्यासाठी तुमच्या डिव्हाइसचे क्रेडेंशियल एंटर करा"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"आंशिक फिंगरप्रिंट आढळली. कृपया पुन्हा प्रयत्न करा."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"फिंगरप्रिंटवर प्रक्रिया करणे शक्य झाले नाही. कृपया पुन्हा प्रयत्न करा."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"फिंगरप्रिंट सेन्सर खराब आहे. कृपया साफ करा आणि पुन्हा प्रयत्न करा."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"बोट खूप जलद हलविले. कृपया पुन्हा प्रयत्न करा."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"बोट खूप सावकाश हलविले. कृपया पुन्हा प्रयत्न करा."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"फिंगरप्रिंट ऑथेंटिकेट केली आहे"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"चेहरा ऑथेंटिकेशन केलेला आहे"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"चेहरा ऑथेंटिकेशन केलेला आहे, कृपया कंफर्म दाबा"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"फिंगरप्रिंट हार्डवेअर उपलब्ध नाही."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"फिंगरप्रिंट स्टोअर केले जाऊ शकत नाही. कृपया विद्यमान फिंगरप्रिंट काढा."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"फिंगरप्रिंट टाइमआउट झाले. पुन्हा प्रयत्न करा."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"फिंगरप्रिंट ऑपरेशन रद्द झाले."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"वापरकर्त्याने फिंगरप्रिंट ऑपरेशन रद्द केले."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"फेस अनलॉक"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"तुमच्या चेहऱ्याची पुन्हा नोंदणी करा"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ओळखण्यामध्ये सुधारणा करण्यासाठी, कृपया तुमच्या चेहऱ्याची पुन्हा नोंदणी करा"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"अचूक फेस डेटा कॅप्चर करता आला नाही. पुन्हा करा."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"खूप प्रखर. आणखी सौम्य प्रकाश वापरून पहा."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"खूप गडद. आणखी प्रखर प्रकाश वापरून पहा."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"कॉपी केले"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> वरून <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> पेस्ट केले"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"क्लिपबोर्डवरून <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> पेस्ट केले"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"अधिक"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"मेनू+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"कार्य"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"वैयक्तिक दृश्य"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"कार्य दृश्य"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"हे कार्य ॲप्ससोबत शेअर करू शकत नाही"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"तुमचा IT अॅडमिन तुम्हाला हा आशय तुमच्या ऑफिस प्रोफाइलमधील अॅप्ससोबत शेअर करू देत नाही"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"हे ऑफिस अॅप्ससोबत उघडू शकत नाही"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"तुमचा IT अॅडमिन तुम्हाला हा आशय तुमच्या कार्य प्रोफाइलमधील अॅप्सनी उघडू देत नाही"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"हे वैयक्तिक अॅप्ससोबत शेअर करू शकत नाही"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"तुमचा IT अॅडमिन तुम्हाला हा आशय तुमच्या वैयक्तिक प्रोफाइलमधील अॅप्ससोबत शेअर करू देत नाही"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"हे वैयक्तिक अॅप्ससोबत उघडू शकत नाही"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"तुमचा IT अॅडमिन तुम्हाला हा आशय तुमच्या वैयक्तिक प्रोफाइलमधील अॅप्ससोबत उघडू देत नाही"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"कार्य प्रोफाइल थांबवली आहे"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"सुरू करा"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"कार्य अॅप्स या आशयाला सपोर्ट करू शकत नाही"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"कार्य अॅप्स हा आशय उघडू शकत नाही"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"वैयक्तिक अॅप्स या आशयाला सपोर्ट करू शकत नाही"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"वैयक्तिक अॅप्स हा आशय उघडू शकत नाही"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"सिम नेटवर्क अनलॉक पिन"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM नेटवर्क सबसेट अनलॉक पिन"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM कॉर्पोरेट अनलॉक पिन"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"तुमच्या स्क्रीनचा काही भाग मॅग्निफाय करा"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"आता तुम्ही तुमची फुल स्क्रीन, विशिष्ट भाग मॅग्निफाय करू शकता किंवा दोन्ही पर्यायांमध्ये स्विच करू शकता."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिंग्ज मध्ये सुरू करा"</string>
<string name="dismiss_action" msgid="1728820550388704784">"डिसमिस करा"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"पुढे सुरू ठेवण्यासाठी, <b><xliff:g id="APP">%s</xliff:g></b> ला तुमच्या डिव्हाइसचा मायक्रोफोन अॅक्सेस करण्याची आवश्यकता आहे."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 9550abb..1a04741 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Apl berjalan"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apl yang menggunakan bateri"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pembesaran"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Dasar keselamatan kebolehaksesan"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan bateri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apl sedang menggunakan bateri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketik untuk mendapatkan butiran tentang penggunaan kuasa bateri dan data"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"akses aktiviti fizikal anda"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ambil gambar dan rakam video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Peranti Bluetooth yang Berdekatan"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"temukan dan sambung kepada peranti Bluetooth yang berdekatan"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Log panggilan"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"baca dan tulis log panggilan telefon"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Membenarkan apl melihat konfigurasi Bluetooth pada tablet dan untuk membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Membenarkan apl melihat konfigurasi Bluetooth pada peranti Android TV anda dan membuat serta menerima sambungan dengan peranti yang digandingkan."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Membenarkan apl melihat konfigurasi Bluetooth pada telefon dan membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"temukan dan gandingkan peranti Bluetooth yang berdekatan"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Membenarkan apl menemukan dan berganding dengan peranti Bluetooth yang berdekatan"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"sambung kepada peranti Bluetooth yang digandingkan"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Membenarkan apl untuk menyambung kepada peranti Bluetooth yang digandingkan"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Maklumat Perkhidmatan Pembayaran NFC Pilihan"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Membenarkan apl mendapatkan maklumat perkhidmatan pembayaran nfc pilihan seperti bantuan berdaftar dan destinasi laluan."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"mengawal Komunikasi Medan Dekat"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Ralat semasa membuat pengesahan"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gunakan kunci skrin"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Masukkan bukti kelayakan peranti anda untuk meneruskan"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Cap jari separa dikesan. Sila cuba lagi."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Tidak dapat memproses cap jari. Sila cuba lagi."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Penderia cap jari kotor. Sila bersihkan dan cuba lagi."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Jari digerakkan terlalu cepat. Sila cuba lagi."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Jari digerakkan terlalu perlahan. Sila cuba lagi."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Cap jari disahkan"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Wajah disahkan"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Wajah disahkan, sila tekan sahkan"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Perkakasan cap jari tidak tersedia."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Cap jari tidak dapat disimpan. Sila alih keluar cap jari sedia ada."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Sudah tamat masa untuk cap jari. Cuba lagi"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Pengendalian cap jari dibatalkan."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Pengendalian cap jari dibatalkan oleh pengguna."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Wajah buka kunci"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Daftarkan semula wajah anda"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Untuk meningkatkan pengecaman, sila daftarkan semula wajah anda"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Gagal menangkap data wajah dgn tepat. Cuba lagi."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Terlalu terang. Cuba pencahayaan yang lebih lembut."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Terlalu gelap. Cuba pencahayaan yang lebih cerah."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Disalin"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ditampalkan daripada <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ditampalkan daripada papan keratan"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Lagi"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Kerja"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Paparan peribadi"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Paparan kerja"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Tidak dapat berkongsi kandungan ini dengan apl kerja"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Pentadbir IT anda tidak membenarkan anda berkongsi kandungan ini dengan apl dalam profil kerja anda"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Tidak boleh membuka kandungan ini menggunakan apl kerja"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Pentadbir IT anda tidak membenarkan anda membuka kandungan ini menggunakan apl dalam profil kerja anda"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Tidak boleh berkongsi kandungan ini dengan apl peribadi"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Pentadbir IT anda tidak membenarkan anda berkongsi kandungan ini dengan apl dalam profil peribadi anda"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Tidak boleh membuka kandungan ini dengan apl peribadi"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Pentadbir IT anda tidak membenarkan anda membuka kandungan ini menggunakan apl dalam profil peribadi anda"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Profil kerja dijeda"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Hidupkan"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Tiada apl kerja yang boleh menyokong kandungan ini"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Tiada apl kerja yang boleh membuka kandungan ini"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Tiada apl peribadi yang boleh menyokong kandungan ini"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Tiada apl peribadi yang boleh membuka kandungan ini"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN buka kunci rangkaian SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN buka kunci subset rangkaian SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN buka kunci korporat SIM"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Besarkan sebahagian skrin anda"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Kini anda boleh membesarkan skrin penuh, kawasan tertentu atau beralih antara kedua-dua pilihan."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Hidupkan dalam Tetapan"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Tolak"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Untuk meneruskan proses, <b><xliff:g id="APP">%s</xliff:g></b> memerlukan akses kepada mikrofon peranti anda."</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 165db32..9e41ccd 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP လုပ်ဆောင်နေသည်"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"အက်ပ်များက ဘက်ထရီကုန်စေသည်"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ချဲ့ခြင်း"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"အများသုံးစွဲနိုင်မှုဆိုင်ရာ လုံခြုံရေးမူဝါဒ"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> က ဘက်ထရီကို အသုံးပြုနေသည်"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"အက်ပ် <xliff:g id="NUMBER">%1$d</xliff:g> ခုက ဘက်ထရီကို အသုံးပြုနေသည်"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ဘက်ထရီနှင့် ဒေတာအသုံးပြုမှု အသေးစိတ်ကို ကြည့်ရန် တို့ပါ"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"သင့်ကိုယ်လက်လှုပ်ရှားမှုကို ဝင်ကြည့်ရန်"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"ကင်မရာ"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ဓာတ်ပုံ ရိုက်ပြီးနောက် ဗွီဒီယို မှတ်တမ်းတင်ရန်"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"အနီးတစ်ဝိုက်ရှိ ဘလူးတုသ်သုံးစက်များ"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"အနီးတစ်ဝိုက်ရှိ ဘလူးတုသ်သုံးစက်များကို ရှာဖွေပြီးချိတ်ဆက်မည်"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"ခေါ်ဆိုမှတ်တမ်း"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ဖုန်းခေါ်ဆိုထားသော မှတ်တမ်း ဖတ်ပြီး ရေးရန်"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ဖုန်း"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"အပလီကေးရှင်းအား တက်ဘလက်ပေါ်မှ ဘလူးတုသ် အပြင်အဆင်အား ကြည့်ခွင့်၊ တခြားစက်များနဲ့ ဆက်သွယ်ခြင်း၊ ဆက်သွယ်ခြင်းကို လက်ခံခွင့်ပြုပါ။"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"သင့် Android TV စက်ပစ္စည်းပေါ်ရှိ ဘလူးတုသ် စီစဉ်သတ်မှတ်ချက်များကို ကြည့်ရှုခွင့်အပြင် တွဲချိတ်ထားသည့် စက်ပစ္စည်းများနှင့် ချိတ်ဆက်မှုပြုလုပ်ခြင်းနှင့် လက်ခံခြင်းတို့ကို အက်ပ်အား ပြုလုပ်ခွင့်ပေးသည်။"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"အပလီကေးရှင်းအား ဖုန်းမှဘလူးတု အပြင်အဆင်အား ကြည့်ခွင့်၊ တခြားစက်များနဲ့ ဆက်သွယ်ခြင်း၊ ဆက်သွယ်ခြင်းကို လက်ခံခွင့်ပြုပါ။"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"အနီးတစ်ဝိုက်ရှိ ဘလူးတုသ်စက်များရှာ၍ တွဲချိတ်ခြင်း"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"အနီးတစ်ဝိုက်ရှိ ဘလူးတုသ်သုံးစက်များကို ရှာဖွေပြီးတွဲချိတ်ရန် အက်ပ်ကိုခွင့်ပြုမည်"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"တွဲချိတ်ထားသော ဘလူးတုသ်စက်များနှင့် ချိတ်ဆက်ခြင်း"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"တွဲချိတ်ထားသော ဘလူးတုသ်သုံးစက်များနှင့် ချိတ်ဆက်ရန် အက်ပ်ကိုခွင့်ပြုမည်"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ဦးစားပေး NFC ငွေပေးချေမှုဆိုင်ရာ ဝန်ဆောင်မှု အချက်အလက်များ"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"အက်ပ်အား ဦစားပေး NFC ငွေပေးချေမှုဆိုင်ရာ ဝန်ဆောင်မှု အချက်အလက်များဖြစ်သည့် မှတ်ပုံတင်ထားသော အကူအညီများနှင့် သွားလာရာ လမ်းကြောင်းတို့ကို ရယူရန် ခွင့်ပြုသည်။"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communicationအား ထိန်းချုပ်ရန်"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"အထောက်အထားစိစစ်ရာတွင် အမှားအယွင်းရှိနေသည်"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ဖန်သားပြင်လော့ခ်ချခြင်းကို သုံးခြင်း"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"ရှေ့ဆက်ရန် သင့်စက်ပစ္စည်း၏ အထောက်အထားကို ထည့်သွင်းပါ"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"လက်ဗွေ တစ်ပိုင်းတစ်စ တွေ့ရှိသည်။ ကျေးဇူးပြု၍ ထပ်စမ်းကြည့်ပါ။"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"လက်ဗွေယူ၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"လက်ဗွေဖတ်ကိရိယာ ညစ်ပေနေသည်။ ကျေးဇူးပြု၍ သန့်ရှင်းလိုက်ပြီး ပြန်စမ်းကြည့်ပါ။"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"လက်ညှိုး အရွှေ့မြန်လွန်းသည်။ ထပ်စမ်းကြည့်ပါ။"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"လက်ညှိုးအလွန်နှေးကွေးစွာ ရွေ့ခဲ့သည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"လက်ဗွေကို အထောက်အထား စိစစ်ပြီးပါပြီ"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ၊ အတည်ပြုရန်ကို နှိပ်ပါ"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"လက်ဗွေ စက်ပစ္စည်းမရနိုင်ပါ။"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"လက်ဗွေ သိုလှောင်၍မရပါ။ လက်ရှိ လက်ဗွေကို ဖယ်ရှားပါ။"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"လက်ဗွေယူချိန်ကုန် သွားပါသည်။ ထပ်စမ်းကြည့်ပါ။"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"လက်ဗွေယူခြင်း ပယ်ဖျက်လိုက်သည်။"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"လက်ဗွေဖြင့် အထောက်အထားစိစစ်ခြင်းကို အသုံးပြုသူက ပယ်ဖျက်ထားသည်။"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"မျက်နှာမှတ် သော့ဖွင့်ခြင်း"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"သင့်မျက်နှာကို စာရင်းပြန်သွင်းပါ"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ပိုမှတ်မိစေရန် သင့်မျက်နှာကို စာရင်းပြန်သွင်းပါ"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"မျက်နှာဒေတာ အမှန် မရိုက်ယူနိုင်ပါ၊ ထပ်စမ်းကြည့်ပါ။"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"အလွန် လင်းသည်။ အလင်းလျှော့ကြည့်ပါ။"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"အလွန်မှောင်သည်။ ပိုလင်းအောင် လုပ်ကြည့်ပါ။"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"မိတ္တူကူးပြီးပါပြီ"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> မှ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> သို့ ကူးထည့်ထားသည်"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"ကလစ်ဘုတ်မှ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> သို့ ကူးထည့်ထားသည်"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"နောက်ထပ်"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"အလုပ်"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ပုဂ္ဂိုလ်ရေးဆိုင်ရာ မြင်ကွင်း"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"အလုပ် မြင်ကွင်း"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"၎င်းကို အလုပ်သုံးအက်ပ်များအား မျှဝေ၍ မရပါ"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"ဤအကြောင်းအရာကို သင့်အလုပ်ပရိုဖိုင်ရှိ အက်ပ်များအား မျှဝေရန် သင်၏ IT စီမံခန့်ခွဲသူက ခွင့်မပြုပါ"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"၎င်းကို အလုပ်သုံးအက်ပ်များဖြင့် ဖွင့်၍မရပါ"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"ဤအကြောင်းအရာကို သင့်အလုပ်ပရိုဖိုင်ရှိ အက်ပ်များဖြင့် ဖွင့်ရန် သင်၏ IT စီမံခန့်ခွဲသူက ခွင့်မပြုပါ"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"၎င်းကို ကိုယ်ပိုင်အက်ပ်များအား မျှဝေ၍ မရပါ"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"ဤအကြောင်းအရာကို သင့်ကိုယ်ပိုင်ပရိုဖိုင်ရှိ အက်ပ်များအား မျှဝေရန် သင်၏ IT စီမံခန့်ခွဲသူက ခွင့်မပြုပါ"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"၎င်းကို ကိုယ်ပိုင်အက်ပ်များဖြင့် ဖွင့်၍မရပါ"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"ဤအကြောင်းအရာကို သင့်ကိုယ်ပိုင်ပရိုဖိုင်ရှိ အက်ပ်များဖြင့် ဖွင့်ရန် သင်၏ IT စီမံခန့်ခွဲသူက ခွင့်မပြုပါ"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"အလုပ်ပရိုဖိုင် ခဏရပ်ထားသည်"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ဖွင့်ရန်"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"ဤအကြောင်းအရာကို အလုပ်သုံးအက်ပ်များက မပံ့ပိုးနိုင်ပါ"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ဤအကြောင်းအရာကို အလုပ်သုံးအက်ပ်များက ဖွင့်၍မရပါ"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"ဤအကြောင်းအရာကို ကိုယ်ပိုင်အက်ပ်များက မပံ့ပိုးနိုင်ပါ"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"ဤအကြောင်းအရာကို ကိုယ်ပိုင်အက်ပ်များက ဖွင့်၍မရပါ"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"ဆင်းမ်ကွန်ရက် လော့ခ်ဖွင့်ရန် ပင်နံပါတ်"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"ဆင်းမ်ကွန်ရက်ခွဲ လော့ခ်ဖွင့်ရန် ပင်နံပါတ်"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"ဆင်းမ်ကော်ပိုရိတ် လော့ခ်ဖွင့်ရန် ပင်နံပါတ်"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"သင့်ဖန်သားပြင်၏ တစ်စိတ်တစ်ပိုင်းကို ချဲ့ပါ"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"ဖန်သားပြင်အပြည့် ချဲ့ခြင်း၊ သတ်မှတ်ဧရိယာကို ချဲ့ခြင်း သို့မဟုတ် နည်းလမ်းနှစ်ခုလုံးကြား ပြောင်းခြင်းတို့ကို လုပ်နိုင်ပါပြီ။"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"\'ဆက်တင်များ\' တွင် ဖွင့်ရန်"</string>
<string name="dismiss_action" msgid="1728820550388704784">"ပယ်ရန်"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"ဆက်လက်လုပ်ဆောင်ရန် <b><xliff:g id="APP">%s</xliff:g></b> က သင့်စက်၏ မိုက်ခရိုဖုန်းကို အသုံးပြုခွင့်ရရန် လိုအပ်သည်။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b2b4675..0ca8b91 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App kjører"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apper bruker batteri"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Forstørring"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Sikkerhetsretningslinjer for tilgjengelighet"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruker batteri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apper bruker batteri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trykk for detaljer om batteri- og databruk"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"tilgang til den fysiske aktiviteten din"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ta bilder og ta opp video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Bluetooth-enheter i nærheten"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"oppdage og koble til Bluetooth-enheter i nærheten"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Samtalelogger"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"lese og skrive samtaleloggen"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Lar appen se Bluetooth-konfigurasjonen på nettbrettet, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Lar appen se Bluetooth-konfigurasjonen på Android TV-enheten din samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Lar appen se Bluetooth-konfigurasjonen på telefonen, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"oppdage og koble til Bluetooth-enheter i nærheten"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Lar appen oppdage og koble til Bluetooth-enheter i nærheten"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"koble til tilkoblede Bluetooth-enheter"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Lar appen koble til tilkoblede Bluetooth-enheter"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informasjon om prioritert NFC-betalingstjeneste"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Gir appen tilgang til informasjon om prioritert NFC-betalingstjeneste, for eksempel registrerte hjelpemidler og destinasjon."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontroller overføring av data med NFC-teknologi"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Feil under autentiseringen"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Bruk skjermlås"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Skriv inn enhetslegitimasjonen din for å fortsette"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Deler av fingeravtrykket er registrert. Prøv på nytt."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Kunne ikke registrere fingeravtrykket. Prøv på nytt."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Fingeravtrykksensoren er skitten. Rengjør den og prøv på nytt."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Du flyttet fingeren for raskt. Prøv på nytt."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Du flyttet fingeren for sakte. Prøv på nytt."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingeravtrykket er godkjent"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ansiktet er autentisert"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansiktet er autentisert. Trykk på Bekreft"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Maskinvare for fingeravtrykk er ikke tilgjengelig."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Fingeravtrykket kan ikke lagres. Fjern et eksisterende fingeravtrykk."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingeravtrykk-operasjonen ble avbrutt."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingeravtrykk-operasjonen ble avbrutt av brukeren."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Ansiktslås"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Registrer ansiktet ditt på nytt"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"For å forbedre gjenkjennelse, registrer ansiktet ditt på nytt"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Kunne ikke ta opp nøyaktige ansiktsdata Prøv igjen"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"For lyst. Prøv svakere belysning."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"For mørkt. Prøv sterkere belysning."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Kopiert"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> limte inn fra <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> limte inn fra utklippstavlen"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Mer"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"menyknapp+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Jobb"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personlig visning"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Jobbvisning"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Du kan ikke dele dette med jobbapper"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT-administratoren din tillater ikke at du deler dette innholdet med apper i jobbprofilen din"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Du kan ikke åpne dette med jobbapper"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT-administratoren din tillater ikke at du åpner dette innholdet med apper i jobbprofilen din"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Du kan ikke dele dette med personlige apper"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT-administratoren din tillater ikke at du deler dette innholdet med apper i den personlige profilen din"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Du kan ikke åpne dette med personlige apper"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT-administratoren din tillater ikke at du åpner dette innholdet med apper i den personlige profilen din"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Jobbprofilen er satt på pause"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Slå på"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Ingen jobbapper støtter dette innholdet"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Ingen jobbapper kan åpne dette innholdet"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Ingen personlige apper støtter dette innholdet"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Ingen personlige apper kan åpne dette innholdet"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-kode for å fjerne operatørlåser"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-kode for å fjerne bestemte operatørlåser"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-kode for å låse opp SIM-kort for bedrifter"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Forstørr en del av skjermen"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Nå kan du forstørre fullskjermen eller et bestemt område eller bytte mellom de to alternativene."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Slå på i innstillingene"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Avvis"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"For å fortsette må <b><xliff:g id="APP">%s</xliff:g></b> ha tilgang til enhetsmikrofonen."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 64d825c..6a0ba3b 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"एप चलिरहेको छ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"एपहरूले ब्याट्री खपत गर्दै छन्"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"जुम इन गर्ने सुविधा"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"सर्वसुलभताको सुरक्षासम्बन्धी नीति"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले ब्याट्री प्रयोग गर्दै छ"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> एपहरूले ब्याट्री प्रयोग गर्दै छन्"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ब्याट्री र डेटाका प्रयोग सम्बन्धी विवरणहरूका लागि ट्याप गर्नुहोस्"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"आफ्नो शारीरिक क्रियाकलापको डेटामाथि पहुँच राख्नु"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"क्यामेरा"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"फोटो खिच्नुका साथै भिडियो रेकर्ड गर्नुहोस्"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"नजिकै रहेका ब्लुटुथ चल्ने यन्त्रहरू"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"नजिकै रहेका ब्लुटुथ चल्ने यन्त्रहरू भेट्टाउने र ती यन्त्रहरूसँग कनेक्ट गर्ने"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"कलका लगहरू"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"फोन कलको लग पढ्नुहोस् र लेख्नुहोस्"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"फोन"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ट्याब्लेटमा ब्लुटुथको कन्फिगुरेसनलाई हेर्न र बनाउन र जोडी उपकरणहरूसँग जडानहरूलाई स्वीकार गर्न एपलाई अनुमति दिन्छ।"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"एपलाई तपाईंको Android टिभी यन्त्रको ब्लुटुथको कन्फिगुरेसन हेर्ने तथा जोडा बनाइएका यन्त्रहरूसँग जोडिने वा ती यन्त्रहरूले पठाएका जोडिने अनुरोध स्वीकार्ने अनुमति दिन्छ।"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"एपलाई फोनमा ब्लुटुथको कन्फिगरेसन हेर्न र जोडी भएका उपकरणहरूसँग जडानहरू बनाउन र स्वीकार गर्न अनुमति दिन्छ।"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"नजिकै रहेका ब्लुटुथ चल्ने यन्त्रहरू भेट्टाउने र ती यन्त्रहरूसँग कनेक्ट गर्ने"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"यो अनुमति दिइएमा एपले नजिकै रहेका ब्लुटुथ चल्ने यन्त्रहरू भेट्टाउन र ती यन्त्रहरूसँग कनेक्ट गर्न सक्छ"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"लिंक गरिएका ब्लुटुथ चल्ने यन्त्रहरूसँग कनेक्ट गर्ने"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"यो अनुमति दिइएमा एपले लिंक गरिएका ब्लुटुथ चल्ने यन्त्रहरूसँग कनेक्ट गर्न सक्छ"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"NFC भुक्तानी सेवासम्बन्धी रुचाइएको जानकारी"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"यसले एपलाई दर्ता गरिएका सहायता तथा मार्गको गन्तव्य जस्ता रुचाइएका NFC भुक्तानी सेवासम्बन्धी जानकारी प्राप्त गर्न दिन्छ।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"नजिक क्षेत्र संचार नियन्त्रणहरू"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"प्रमाणित गर्ने क्रममा त्रुटि भयो"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"स्क्रिन लक प्रयोग गर्नुहोस्"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"जारी राख्न आफ्नो यन्त्रको PIN, प्याटर्न वा पासवर्ड हाल्नुहोस्"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"आंशिक फिंगरप्रिन्ट पत्ता लाग्यो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"फिंगरप्रिन्ट प्रशोधन गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्।"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"फिंगरप्रिन्ट सेन्सर फोहोर छ। कृपया सफा गरेर फेरि प्रयास गर्नुहोस्।"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"औंला धेरै छिटो चलाइयो। पुन: प्रयास गर्नुहोस्।"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"औंला निकै सुस्त सारियो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"फिंगरप्रिन्ट प्रमाणीकरण गरियो"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"अनुहार प्रमाणीकरण गरियो"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"अनुहार प्रमाणीकरण गरियो, कृपया पुष्टि गर्नुहोस् थिच्नुहोस्"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"औँठाछाप हार्डवेयर उपलब्ध छैन।"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"फिंगरप्रिन्ट भण्डारण गर्न सकिँदैन। कृपया अहिलेको फिंगरप्रिन्ट हटाउनुहोस्।"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"फिंगरप्रिन्ट समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"फिंगरप्रिन्ट सञ्चालन रद्द गरियो।"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"प्रयोगकर्ताले फिंगरप्रिन्टसम्बन्धी कारबाही रद्द गर्नुभयो।"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"फेस अनलक"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"आफ्नो अनुहार पुनः दर्ता गर्नुहोस्"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"अनुहार पहिचानको गुणस्तर सुधार गर्न कृपया आफ्नो अनुहार पुनः दर्ता गर्नुहोस्"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"अनुहारको सटीक डेटा खिच्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"ज्यादै चम्किलो। अझ मधुरो प्रकाश प्रयोग गरी हेर्नु…"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"ज्यादै अँध्यारो छ। अझ बढी प्रकाशमा गई हेर्नुहोस्"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"प्रतिलिपि गरियो"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> मा रहेको डेटा कपी गरी <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> मा पेस्ट गरियो"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"क्लिपबोर्डमा रहेको डेटा कपी गरी <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> मा पेस्ट गरियो"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"बढी"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"मेनु+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,8 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"सर्टकट प्रयोग गर्नुहोस्"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"रङ्ग उल्टाउने सुविधा"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"रङ्ग सच्याउने सुविधा"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (3222994553174604132) -->
- <skip />
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"अझै मधुरो"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन भयो।"</string>
<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>
@@ -2111,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"काम"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"व्यक्तिगत दृश्य"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"कार्य दृश्य"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"यो सामग्री कामसम्बन्धी अनुप्रयोगहरूमार्फत सेयर गर्न मिल्दैन"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"तपाईंका IT एडमिनले तपाईंलाई तपाईंको कार्य प्रोफाइलमा रहेका अनुप्रयोगहरूमार्फत यो सामग्री सेयर गर्ने अनुमति दिनुभएको छैन"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"यो सामग्री कामसम्बन्धी अनुप्रयोगहरूमार्फत खोल्न मिल्दैन"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"तपाईंका IT एडमिनले तपाईंलाई तपाईंको कार्य प्रोफाइलमा रहेका अनुप्रयोगहरूमार्फत यो सामग्री खोल्ने अनुमति दिनुभएको छैन"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"यो सामग्री व्यक्तिगत अनुप्रयोगहरूमार्फत सेयर गर्न मिल्दैन"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"तपाईंका IT एडमिनले तपाईंलाई तपाईंको व्यक्तिगत प्रोफाइलमा रहेका अनुप्रयोगहरूमार्फत यो सामग्री सेयर गर्ने अनुमति दिनुभएको छैन"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"यो सामग्री व्यक्तिगत अनुप्रयोगहरूमार्फत खोल्न मिल्दैन"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"तपाईंका IT एडमिनले तपाईंलाई तपाईंको व्यक्तिगत प्रोफाइलमा रहेका अनुप्रयोगहरूमार्फत यो सामग्री खोल्ने अनुमति दिनुभएको छैन"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"कार्य प्रोफाइल पज गरिएको छ"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"सक्रिय गर्नुहोस्"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"यो सामग्री कामसम्बन्धी कुनै पनि अनुप्रयोगमार्फत सेयर गर्न मिल्दैन"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"यो सामग्री कामसम्बन्धी कुनै पनि अनुप्रयोगमार्फत खोल्न मिल्दैन"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"यो सामग्री कुनै पनि व्यक्तिगत अनुप्रयोगमार्फत सेयर गर्न मिल्दैन"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"यो सामग्री कुनै पनि व्यक्तिगत अनुप्रयोगमार्फत खोल्न मिल्दैन"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM को नेटवर्क अनलक गर्ने PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM को नेटवर्कको सबसेट अनलक गर्ने PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM को कर्पोरेट लक खोल्ने PIN"</string>
@@ -2237,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"आफ्नो स्क्रिनको केही भाग जुम इन गर्नुहोस्"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"तपाईं अब आफ्नो स्क्रिनको पूरै भाग वा केही भाग जुम इन गर्न सक्नुहुन्छ वा यी दुई विकल्प अदलबदल गर्न सक्नुहुन्छ।"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिङमा गई यो सुविधा अन गर्नुहोस्"</string>
<string name="dismiss_action" msgid="1728820550388704784">"हटाउनुहोस्"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"जारी राख्न <b><xliff:g id="APP">%s</xliff:g></b> लाई तपाईंको यन्त्रको माइक्रोफोन प्रयोग गर्ने अनुमति दिनु पर्ने हुन्छ।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index c0026b7..92cd82b 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -35,9 +35,9 @@
<string name="mmiError" msgid="2862759606579822246">"Verbindingsprobleem of ongeldige MMI-code."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Bewerking is beperkt tot vaste nummers."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Kan instellingen voor doorschakelen van gesprekken niet wijzigen vanaf je telefoon tijdens roaming."</string>
- <string name="serviceEnabled" msgid="7549025003394765639">"Service is ingeschakeld."</string>
- <string name="serviceEnabledFor" msgid="1463104778656711613">"Service is ingeschakeld voor:"</string>
- <string name="serviceDisabled" msgid="641878791205871379">"Service is uitgeschakeld."</string>
+ <string name="serviceEnabled" msgid="7549025003394765639">"Service staat aan."</string>
+ <string name="serviceEnabledFor" msgid="1463104778656711613">"Service staat aan voor:"</string>
+ <string name="serviceDisabled" msgid="641878791205871379">"Service staat uit."</string>
<string name="serviceRegistered" msgid="3856192211729577482">"De registratie is voltooid."</string>
<string name="serviceErased" msgid="997354043770513494">"Wissen uitgevoerd."</string>
<string name="passwordIncorrect" msgid="917087532676155877">"Onjuist wachtwoord."</string>
@@ -81,8 +81,8 @@
<string name="RestrictedOnEmergencyTitle" msgid="2852916906106191866">"Noodoproepen niet beschikbaar"</string>
<string name="RestrictedOnNormalTitle" msgid="7009474589746551737">"Geen belservice"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="3982069078579103087">"Geen spraakservice of noodoproepen"</string>
- <string name="RestrictedStateContent" msgid="7693575344608618926">"Tijdelijk uitgeschakeld door je provider"</string>
- <string name="RestrictedStateContentMsimTemplate" msgid="5228235722511044687">"Tijdelijk uitgeschakeld door je provider voor sim <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
+ <string name="RestrictedStateContent" msgid="7693575344608618926">"Tijdelijk uitgezet door je provider"</string>
+ <string name="RestrictedStateContentMsimTemplate" msgid="5228235722511044687">"Tijdelijk uitgezet door je provider voor sim <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Kan mobiel netwerk niet bereiken"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Probeer een ander voorkeursnetwerk. Tik om te wijzigen."</string>
<string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Noodoproepen niet beschikbaar"</string>
@@ -207,20 +207,20 @@
<string name="music_recognition_manager_service" msgid="7481956037950276359">"Beheerservice voor muziekherkenning"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Je apparaat wordt gewist"</string>
<string name="factory_reset_message" msgid="2657049595153992213">"De beheer-app kan niet worden gebruikt. Je apparaat wordt nu gewist.\n\nNeem contact op met de beheerder van je organisatie als je vragen hebt."</string>
- <string name="printing_disabled_by" msgid="3517499806528864633">"Afdrukken uitgeschakeld door <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
+ <string name="printing_disabled_by" msgid="3517499806528864633">"Afdrukken uitgezet door <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="personal_apps_suspension_title" msgid="7561416677884286600">"Schakel je werkprofiel in"</string>
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Je persoonlijke apps zijn geblokkeerd totdat je je werkprofiel inschakelt"</string>
- <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Apps die worden gebruikt voor persoonlijke doeleinden, worden geblokkeerd op <xliff:g id="DATE">%1$s</xliff:g> om <xliff:g id="TIME">%2$s</xliff:g>. Je IT-beheerder staat niet toe dat je werkprofiel langer dan <xliff:g id="NUMBER">%3$d</xliff:g> dagen is uitgeschakeld."</string>
- <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Inschakelen"</string>
+ <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Apps die worden gebruikt voor persoonlijke doeleinden, worden geblokkeerd op <xliff:g id="DATE">%1$s</xliff:g> om <xliff:g id="TIME">%2$s</xliff:g>. Je IT-beheerder staat niet toe dat je werkprofiel langer dan <xliff:g id="NUMBER">%3$d</xliff:g> dagen uitstaat."</string>
+ <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aanzetten"</string>
<string name="me" msgid="6207584824693813140">"Ik"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tabletopties"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opties voor Android TV"</string>
<string name="power_dialog" product="default" msgid="1107775420270203046">"Telefoonopties"</string>
<string name="silent_mode" msgid="8796112363642579333">"Stille modus"</string>
- <string name="turn_on_radio" msgid="2961717788170634233">"Draadloos inschakelen"</string>
- <string name="turn_off_radio" msgid="7222573978109933360">"Draadloos uitschakelen"</string>
+ <string name="turn_on_radio" msgid="2961717788170634233">"Draadloos aanzetten"</string>
+ <string name="turn_off_radio" msgid="7222573978109933360">"Draadloos uitzetten"</string>
<string name="screen_lock" msgid="2072642720826409809">"Schermvergrendeling"</string>
- <string name="power_off" msgid="4111692782492232778">"Uitschakelen"</string>
+ <string name="power_off" msgid="4111692782492232778">"Uitzetten"</string>
<string name="silent_mode_silent" msgid="5079789070221150912">"Belsoftware uit"</string>
<string name="silent_mode_vibrate" msgid="8821830448369552678">"Belsoftware op trillen"</string>
<string name="silent_mode_ring" msgid="6039011004781526678">"Belsoftware aan"</string>
@@ -230,21 +230,21 @@
<string name="reboot_to_update_reboot" msgid="4474726009984452312">"Opnieuw opstarten…"</string>
<string name="reboot_to_reset_title" msgid="2226229680017882787">"Terugzetten op fabrieksinstellingen"</string>
<string name="reboot_to_reset_message" msgid="3347690497972074356">"Opnieuw opstarten…"</string>
- <string name="shutdown_progress" msgid="5017145516412657345">"Uitschakelen..."</string>
- <string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"Je tablet wordt uitgeschakeld."</string>
- <string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"Je Android TV-apparaat wordt uitgeschakeld."</string>
- <string name="shutdown_confirm" product="watch" msgid="2977299851200240146">"Je horloge wordt uitgeschakeld."</string>
- <string name="shutdown_confirm" product="default" msgid="136816458966692315">"Je telefoon wordt uitgeschakeld."</string>
+ <string name="shutdown_progress" msgid="5017145516412657345">"Uitzetten…"</string>
+ <string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"Je tablet wordt uitgezet."</string>
+ <string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"Je Android TV-apparaat wordt uitgezet."</string>
+ <string name="shutdown_confirm" product="watch" msgid="2977299851200240146">"Je horloge wordt uitgezet."</string>
+ <string name="shutdown_confirm" product="default" msgid="136816458966692315">"Je telefoon wordt uitgezet."</string>
<string name="shutdown_confirm_question" msgid="796151167261608447">"Wil je afsluiten?"</string>
<string name="reboot_safemode_title" msgid="5853949122655346734">"Opnieuw opstarten in veilige modus"</string>
- <string name="reboot_safemode_confirm" msgid="1658357874737219624">"Wil je opnieuw opstarten in de veilige modus? Als u dit doet, worden alle geïnstalleerde applicaties van derden uitgeschakeld. Ze worden weer ingeschakeld als u weer opnieuw opstart."</string>
+ <string name="reboot_safemode_confirm" msgid="1658357874737219624">"Wil je opnieuw opstarten in de veilige modus? Als je dit doet, worden alle geïnstalleerde apps van derden uitgezet. Ze worden weer aangezet als je het apparaat opnieuw opstart."</string>
<string name="recent_tasks_title" msgid="8183172372995396653">"Recent"</string>
<string name="no_recent_tasks" msgid="9063946524312275906">"Geen recente apps."</string>
<string name="global_actions" product="tablet" msgid="4412132498517933867">"Tabletopties"</string>
<string name="global_actions" product="tv" msgid="3871763739487450369">"Opties voor Android TV"</string>
<string name="global_actions" product="default" msgid="6410072189971495460">"Telefoonopties"</string>
<string name="global_action_lock" msgid="6949357274257655383">"Schermvergrendeling"</string>
- <string name="global_action_power_off" msgid="4404936470711393203">"Uitschakelen"</string>
+ <string name="global_action_power_off" msgid="4404936470711393203">"Uitzetten"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"Aan/uit"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Opnieuw opstarten"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Noodgeval"</string>
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App actief"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps die de batterij gebruiken"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergroting"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Beveiligingsbeleid voor toegankelijkheid"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruikt de batterij"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps gebruiken de batterij"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik voor batterij- en datagebruik"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"toegang tot je fysieke activiteit"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Camera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"foto\'s maken en video opnemen"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Bluetooth-apparaten in de buurt"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"bluetooth-apparaten in de buurt vinden en er verbinding mee maken"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Gesprekslijsten"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"gesprekslijst lezen en schrijven"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefoon"</string>
@@ -327,7 +330,7 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"toegang krijgen tot sensorgegevens over je vitale functies"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Content van vensters ophalen"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"De content inspecteren van een venster waarmee je interactie hebt."</string>
- <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"\'Verkennen via aanraking\' inschakelen"</string>
+ <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Verkennen via aanraking aanzetten"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Aangetikte items worden hardop benoemd en het scherm kan worden verkend via gebaren."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"Tekst observeren die je typt"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"Omvat persoonsgegevens zoals creditcardnummers en wachtwoorden."</string>
@@ -339,8 +342,8 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebaren registreren die op de vingerafdruksensor van het apparaat worden getekend."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot maken"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan een screenshot van het scherm maken."</string>
- <string name="permlab_statusBar" msgid="8798267849526214017">"statusbalk uitschakelen of wijzigen"</string>
- <string name="permdesc_statusBar" msgid="5809162768651019642">"Hiermee kan de app de statusbalk uitschakelen of systeempictogrammen toevoegen en verwijderen."</string>
+ <string name="permlab_statusBar" msgid="8798267849526214017">"statusbalk uitzetten of wijzigen"</string>
+ <string name="permdesc_statusBar" msgid="5809162768651019642">"Hiermee kan de app de statusbalk uitzetten of systeemiconen toevoegen en verwijderen."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"de statusbalk zijn"</string>
<string name="permdesc_statusBarService" msgid="6652917399085712557">"Hiermee kan de app de statusbalk zijn."</string>
<string name="permlab_expandStatusBar" msgid="1184232794782141698">"statusbalk uitvouwen/samenvouwen"</string>
@@ -381,8 +384,8 @@
<string name="permdesc_manageProfileAndDeviceOwners" msgid="7304240671781989283">"Apps toestaan de profieleigenaren en apparaateigenaar in te stellen."</string>
<string name="permlab_reorderTasks" msgid="7598562301992923804">"actieve apps opnieuw rangschikken"</string>
<string name="permdesc_reorderTasks" msgid="8796089937352344183">"Hiermee kan de app taken naar de voor- en achtergrond verplaatsen. De app kan dit doen zonder om je bevestiging te vragen."</string>
- <string name="permlab_enableCarMode" msgid="893019409519325311">"automodus inschakelen"</string>
- <string name="permdesc_enableCarMode" msgid="56419168820473508">"Hiermee kan de app de automodus inschakelen."</string>
+ <string name="permlab_enableCarMode" msgid="893019409519325311">"automodus aanzetten"</string>
+ <string name="permdesc_enableCarMode" msgid="56419168820473508">"Hiermee kan de app de automodus aanzetten."</string>
<string name="permlab_killBackgroundProcesses" msgid="6559320515561928348">"andere apps sluiten"</string>
<string name="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"Hiermee kan de app achtergrondprocessen van andere apps beëindigen. Hierdoor kunnen andere apps worden gestopt."</string>
<string name="permlab_systemAlertWindow" msgid="5757218350944719065">"Deze app kan op de voorgrond vóór andere apps worden weergegeven"</string>
@@ -436,9 +439,9 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"toegang tot extra opdrachten van locatieaanbieder"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Hiermee kan de app toegang krijgen tot extra opdrachten voor de locatieprovider. De app kan hiermee de werking van gps of andere locatiebronnen te verstoren."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"alleen toegang tot precieze locatie op de voorgrond"</string>
- <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Deze app kan je precieze locatie opvragen bij de locatieservices terwijl de app wordt gebruikt. De app kan de locatie alleen opvragen als de locatieservices voor je apparaat zijn ingeschakeld. Hierdoor kan het batterijgebruik toenemen."</string>
+ <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Deze app kan je precieze locatie opvragen bij de locatieservices terwijl de app wordt gebruikt. De app kan de locatie alleen opvragen als de locatieservices voor je apparaat aanstaan. Hierdoor kan het batterijgebruik toenemen."</string>
<string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"alleen toegang tot geschatte locatie op de voorgrond"</string>
- <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Deze app kan je geschatte locatie opvragen bij de locatieservices terwijl de app wordt gebruikt. De app kan de locatie alleen opvragen als de locatieservices voor je apparaat zijn ingeschakeld."</string>
+ <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Deze app kan je geschatte locatie opvragen bij de locatieservices terwijl de app wordt gebruikt. De app kan de locatie alleen opvragen als de locatieservices voor je apparaat aanstaan."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"toegang tot locatie op de achtergrond"</string>
<string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Deze app heeft altijd toegang tot de locatie, ook als de app niet wordt gebruikt."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"je audio-instellingen wijzigen"</string>
@@ -478,11 +481,11 @@
<string name="permdesc_acceptHandovers" msgid="7129026180128626870">"Hiermee kan de app een gesprek voortzetten dat is gestart in een andere app."</string>
<string name="permlab_readPhoneNumbers" msgid="5668704794723365628">"telefoonnummers lezen"</string>
<string name="permdesc_readPhoneNumbers" msgid="7368652482818338871">"Hiermee kan de app toegang krijgen tot de telefoonnummers van het apparaat."</string>
- <string name="permlab_wakeLock" product="automotive" msgid="1904736682319375676">"autoscherm ingeschakeld houden"</string>
+ <string name="permlab_wakeLock" product="automotive" msgid="1904736682319375676">"autoscherm aan laten"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1527660973931694000">"voorkomen dat tablet overschakelt naar slaapmodus"</string>
<string name="permlab_wakeLock" product="tv" msgid="2856941418123343518">"voorkomen dat je Android TV overschakelt naar slaapstand"</string>
<string name="permlab_wakeLock" product="default" msgid="569409726861695115">"voorkomen dat telefoon overschakelt naar slaapmodus"</string>
- <string name="permdesc_wakeLock" product="automotive" msgid="5995045369683254571">"Hiermee kan de app het autoscherm ingeschakeld houden."</string>
+ <string name="permdesc_wakeLock" product="automotive" msgid="5995045369683254571">"Hiermee kan de app het autoscherm aan laten."</string>
<string name="permdesc_wakeLock" product="tablet" msgid="2441742939101526277">"Hiermee kan de app voorkomen dat de tablet overschakelt naar de slaapmodus."</string>
<string name="permdesc_wakeLock" product="tv" msgid="2329298966735118796">"Hiermee kan de app voorkomen dat het Android TV-apparaat overschakelt naar de slaapstand."</string>
<string name="permdesc_wakeLock" product="default" msgid="3689523792074007163">"Hiermee kan de app voorkomen dat de telefoon overschakelt naar de slaapmodus."</string>
@@ -523,7 +526,7 @@
<string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Hiermee kan de app Bluetooth op je Android TV-apparaat isntellen en externe apparaten zoeken en koppelen."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"Hiermee kan de app de lokale bluetooth-telefoon instellen en externe apparaten zoeken en koppelen."</string>
<string name="permlab_accessWimaxState" msgid="7029563339012437434">"WiMAX-verbinding maken en verbreken"</string>
- <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"Hiermee kan de app bepalen of WiMAX is ingeschakeld en informatie bekijken over alle WiMAX-netwerken waarmee verbinding is gemaakt."</string>
+ <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"Hiermee kan de app bepalen of WiMAX aanstaat en informatie bekijken over alle WiMAX-netwerken waarmee verbinding is gemaakt."</string>
<string name="permlab_changeWimaxState" msgid="6223305780806267462">"WiMAX-status wijzigen"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"Hiermee kan de app de tablet verbinden met WiMAX-netwerken en de verbinding daarmee verbreken."</string>
<string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"Hiermee kan de app verbinding maken met je Android TV-apparaat en je Android TV-apparaat loskoppelen van WiMAX-netwerken."</string>
@@ -532,12 +535,16 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Hiermee kan de app de Bluetooth-configuratie van de tablet bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Hiermee kan de app de Bluetooth-configuratie van het Android TV-apparaat bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Hiermee kan de app de Bluetooth-configuratie van de telefoon bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"bluetooth-apparaten in de buurt vinden en koppelen"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Hiermee kan de app bluetooth-apparaten in de buurt vinden en koppelen"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"verbinding maken met gekoppelde bluetooth-apparaten"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Hiermee kan de app verbinding maken met gekoppelde bluetooth-apparaten"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informatie over voorkeursservice voor NFC-betaling"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Hiermee kun je zorgen dat de app informatie krijgt over de voorkeursservice voor NFC-betaling, zoals geregistreerde hulpmiddelen en routebestemmingen."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communication regelen"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Hiermee kan de app communiceren met NFC-tags (Near Field Communication), kaarten en lezers."</string>
- <string name="permlab_disableKeyguard" msgid="3605253559020928505">"je schermvergrendeling uitschakelen"</string>
- <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Hiermee kan de app de toetsenblokkering en bijbehorende wachtwoordbeveiliging uitschakelen. Zo kan de telefoon de toetsenblokkering uitschakelen wanneer je wordt gebeld en de toetsenblokkering weer inschakelen als het gesprek is beëindigd."</string>
+ <string name="permlab_disableKeyguard" msgid="3605253559020928505">"je schermvergrendeling uitzetten"</string>
+ <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Hiermee kan de app de toetsenblokkering en bijbehorende wachtwoordbeveiliging uitzetten. Zo kan de telefoon de toetsenblokkering uitzetten als je wordt gebeld en de toetsenblokkering weer aanzetten als het gesprek is beëindigd."</string>
<string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"complexiteit van schermvergrendeling opvragen"</string>
<string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Hiermee krijgt de app toestemming om het complexiteitsniveau van de schermvergrendeling te achterhalen (hoog, midden, laag of geen). Dat geeft een indicatie van het mogelijke lengtebereik en type van de schermvergrendeling. De app kan gebruikers ook voorstellen de schermvergrendeling naar een bepaald niveau te updaten, maar gebruikers kunnen dit altijd negeren en de app verlaten. De schermvergrendeling wordt niet opgeslagen als platte tekst, zodat de app het precieze wachtwoord niet weet."</string>
<string name="permlab_useBiometric" msgid="6314741124749633786">"biometrische hardware gebruiken"</string>
@@ -567,23 +574,33 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Fout bij verificatie"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Schermvergrendeling gebruiken"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Geef de inloggegevens van je apparaat op om door te gaan"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Gedeeltelijke vingerafdruk gedetecteerd. Probeer het opnieuw."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Kan vingerafdruk niet verwerken. Probeer het opnieuw."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"De vingerafdruksensor moet worden schoongemaakt. Probeer het daarna opnieuw."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Vinger te snel bewogen. Probeer het opnieuw."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Vinger te langzaam bewogen. Probeer het opnieuw."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Vingerafdruk geverifieerd"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Gezicht geverifieerd"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gezicht geverifieerd. Druk op Bevestigen."</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware voor vingerafdruk niet beschikbaar."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Vingerafdruk kan niet worden opgeslagen. Verwijder een bestaande vingerafdruk."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Time-out bereikt voor vingerafdruk. Probeer het opnieuw."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Vingerafdrukbewerking geannuleerd."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Vingerafdrukverificatie geannuleerd door gebruiker."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Te veel pogingen. Probeer het later opnieuw."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Te veel pogingen. Vingerafdruksensor uitgeschakeld."</string>
+ <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Te veel pogingen. Vingerafdruksensor staat uit."</string>
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Probeer het opnieuw."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Geen vingerafdrukken geregistreerd."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Dit apparaat heeft geen vingerafdruksensor."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Ontgrendelen via gezichtsherkenning"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Je gezicht opnieuw registreren"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Registreer je gezicht opnieuw om de herkenning te verbeteren"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Geen accurate gegevens. Probeer het nog eens."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Overbelicht. Probeer een minder felle belichting."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Te donker. Probeer een fellere verlichting."</string>
@@ -631,7 +656,7 @@
<string name="face_error_canceled" msgid="2164434737103802131">"Bewerking voor gezichtsherkenning geannuleerd."</string>
<string name="face_error_user_canceled" msgid="8553045452825849843">"Ontgrendelen via gezichtsherkenning geannuleerd door gebruiker."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Te veel pogingen. Probeer het later opnieuw."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Te veel pogingen. Ontgrendelen via gezichtsherkenning uitgeschakeld."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Te veel pogingen. Ontgrendelen via gezichtsherkenning staat uit."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Kan gezicht niet verifiëren. Probeer het nog eens."</string>
<string name="face_error_not_enrolled" msgid="7369928733504691611">"Je hebt ontgrendelen via gezichtsherkenning niet ingesteld."</string>
<string name="face_error_hw_not_present" msgid="1070600921591729944">"Ontgrendelen via gezichtsherkenning wordt niet ondersteund op dit apparaat."</string>
@@ -646,7 +671,7 @@
<string name="face_icon_content_description" msgid="465030547475916280">"Gezichtspictogram"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"synchronisatie-instellingen lezen"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Hiermee kan de app de synchronisatie-instellingen voor een account lezen. Dit kan bijvoorbeeld bepalen of de app Personen wordt gesynchroniseerd met een account."</string>
- <string name="permlab_writeSyncSettings" msgid="6583154300780427399">"synchronisatie in- en uitschakelen"</string>
+ <string name="permlab_writeSyncSettings" msgid="6583154300780427399">"synchronisatie aan- of uitzetten"</string>
<string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"Hiermee kan een app de synchronisatie-instellingen aanpassen voor een account. Deze toestemming kan bijvoorbeeld worden gebruikt om synchronisatie van de app Personen in te schakelen voor een account."</string>
<string name="permlab_readSyncStats" msgid="3747407238320105332">"synchronisatiestatistieken lezen"</string>
<string name="permdesc_readSyncStats" msgid="3867809926567379434">"Hiermee kan een app de synchronisatiestatistieken voor een account lezen, inclusief de geschiedenis van synchronisatie-activiteiten en hoeveel gegevens zijn gesynchroniseerd."</string>
@@ -731,9 +756,9 @@
<string name="policydesc_expirePassword" msgid="9136524319325960675">"Wijzigen hoe vaak het wachtwoord, de pincode of het patroon voor schermvergrendeling moet worden gewijzigd."</string>
<string name="policylab_encryptedStorage" msgid="9012936958126670110">"Codering voor opslag instellen"</string>
<string name="policydesc_encryptedStorage" msgid="1102516950740375617">"Vereisen dat opgeslagen appgegevens kunnen worden gecodeerd."</string>
- <string name="policylab_disableCamera" msgid="5749486347810162018">"Camera\'s uitschakelen"</string>
+ <string name="policylab_disableCamera" msgid="5749486347810162018">"Camera\'s uitzetten"</string>
<string name="policydesc_disableCamera" msgid="3204405908799676104">"Het gebruik van alle apparaatcamera\'s voorkomen."</string>
- <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"Bepaalde functies voor schermvergrendeling uitschakelen"</string>
+ <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"Bepaalde functies voor schermvergrendeling uitzetten"</string>
<string name="policydesc_disableKeyguardFeatures" msgid="6641673177041195957">"Gebruik van bepaalde functies voor schermvergrendeling voorkomen."</string>
<string-array name="phoneTypes">
<item msgid="8996339953292723951">"Thuis"</item>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Gekopieerd"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> geplakt vanuit <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> geplakt vanaf het klembord"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Meer"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -1025,8 +1056,8 @@
<string name="searchview_description_submit" msgid="6771060386117334686">"Zoekopdracht verzenden"</string>
<string name="searchview_description_voice" msgid="42360159504884679">"Gesproken zoekopdrachten"</string>
<string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"\'Verkennen via aanraking\' aan?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wil \'Verkennen via aanraking\' inschakelen. Wanneer \'Verkennen via aanraking\' is ingeschakeld, kunt u beschrijvingen beluisteren of bekijken van wat er onder je vinger staat of aanraakbewerkingen uitvoeren op de tablet."</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wil \'Verkennen via aanraking\' inschakelen. Wanneer \'Verkennen via aanraking\' is ingeschakeld, kunt u beschrijvingen beluisteren of bekijken van wat er onder je vinger staat of aanraakbewerkingen uitvoeren op de telefoon."</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wil Verkennen via aanraking aanzetten. Als Verkennen via aanraking aanstaat, kun je beschrijvingen beluisteren of bekijken van wat er onder je vinger staat of aanraakbewerkingen uitvoeren op de tablet."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wil Verkennen via aanraking aanzetten. Als Verkennen via aanraking aanstaat, kun je beschrijvingen beluisteren of bekijken van wat er onder je vinger staat of aanraakbewerkingen uitvoeren op de telefoon."</string>
<string name="oneMonthDurationPast" msgid="4538030857114635777">"1 maand geleden"</string>
<string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Meer dan 1 maand geleden"</string>
<plurals name="last_num_days" formatted="false" msgid="687443109145393632">
@@ -1217,7 +1248,7 @@
<string name="launch_warning_original" msgid="3332206576800169626">"<xliff:g id="APP_NAME">%1$s</xliff:g> was het eerst gestart."</string>
<string name="screen_compat_mode_scale" msgid="8627359598437527726">"Schaal"</string>
<string name="screen_compat_mode_show" msgid="5080361367584709857">"Altijd tonen"</string>
- <string name="screen_compat_mode_hint" msgid="4032272159093750908">"U kunt dit opnieuw inschakelen via Systeeminstellingen > Apps > Gedownload."</string>
+ <string name="screen_compat_mode_hint" msgid="4032272159093750908">"Je kunt dit opnieuw aanzetten via Systeeminstellingen > Apps > Gedownload."</string>
<string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> biedt geen ondersteuning voor de huidige instelling voor weergavegrootte en kan onverwacht gedrag vertonen."</string>
<string name="unsupported_display_size_show" msgid="980129850974919375">"Altijd tonen"</string>
<string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g> is gemaakt voor een niet-geschikte versie van het Android-besturingssysteem en kan onverwacht gedrag vertonen. Mogelijk is er een geüpdatete versie van de app beschikbaar."</string>
@@ -1336,10 +1367,10 @@
<string name="dlg_ok" msgid="5103447663504839312">"OK"</string>
<string name="usb_charging_notification_title" msgid="1674124518282666955">"Dit apparaat wordt opgeladen via USB"</string>
<string name="usb_supplying_notification_title" msgid="5378546632408101811">"Verbonden apparaat wordt opgeladen via USB"</string>
- <string name="usb_mtp_notification_title" msgid="1065989144124499810">"USB-bestandsoverdracht ingeschakeld"</string>
- <string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB ingeschakeld"</string>
- <string name="usb_tether_notification_title" msgid="8828527870612663771">"USB-tethering ingeschakeld"</string>
- <string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB ingeschakeld"</string>
+ <string name="usb_mtp_notification_title" msgid="1065989144124499810">"USB-bestandsoverdracht staat aan"</string>
+ <string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB staat aan"</string>
+ <string name="usb_tether_notification_title" msgid="8828527870612663771">"USB-tethering staat aan"</string>
+ <string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB staat aan"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB-accessoire verbonden"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Tik voor meer opties."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Verbonden apparaat wordt opgeladen. Tik voor meer opties."</string>
@@ -1351,12 +1382,12 @@
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Draadloze foutopsporing verbonden"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Tik om draadloze foutopsporing uit te schakelen"</string>
<string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Selecteer deze optie om draadloze foutopsporing uit te schakelen."</string>
- <string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Test harness-modus is ingeschakeld"</string>
+ <string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Test harness-modus staat aan"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Reset de fabrieksinstellingen om de test harness-modus uit te schakelen."</string>
- <string name="console_running_notification_title" msgid="6087888939261635904">"Seriële console ingeschakeld"</string>
+ <string name="console_running_notification_title" msgid="6087888939261635904">"Seriële console staat aan"</string>
<string name="console_running_notification_message" msgid="7892751888125174039">"Dit is van invloed op de prestaties. Controleer de bootloader om dit uit te schakelen."</string>
<string name="usb_contaminant_detected_title" msgid="4359048603069159678">"Vloeistof of vuil in USB-poort"</string>
- <string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB-poort is automatisch uitgeschakeld. Tik voor meer informatie."</string>
+ <string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB-poort is automatisch uitgezet. Tik voor meer informatie."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"USB-poort kan worden gebruikt"</string>
<string name="usb_contaminant_not_detected_message" msgid="892863190942660462">"De telefoon detecteert geen vloeistof of vuil meer."</string>
<string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"Bugrapport genereren…"</string>
@@ -1376,7 +1407,7 @@
<string name="alert_windows_notification_channel_name" msgid="3437528564303192620">"<xliff:g id="NAME">%s</xliff:g> wordt weergegeven over andere apps"</string>
<string name="alert_windows_notification_title" msgid="6331662751095228536">"<xliff:g id="NAME">%s</xliff:g> wordt weergegeven vóór andere apps"</string>
<string name="alert_windows_notification_message" msgid="6538171456970725333">"Als je niet wilt dat <xliff:g id="NAME">%s</xliff:g> deze functie gebruikt, tik je om de instellingen te openen en schakel je de functie uit."</string>
- <string name="alert_windows_notification_turn_off_action" msgid="7805857234839123780">"Uitschakelen"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="7805857234839123780">"Uitzetten"</string>
<string name="ext_media_checking_notification_title" msgid="8299199995416510094">"<xliff:g id="NAME">%s</xliff:g> controleren…"</string>
<string name="ext_media_checking_notification_message" msgid="2231566971425375542">"Huidige content controleren"</string>
<string name="ext_media_checking_notification_message" product="tv" msgid="7986154434946021415">"Mediaopslag analyseren"</string>
@@ -1634,7 +1665,7 @@
<string name="kg_password_wrong_pin_code" msgid="9013856346870572451">"Onjuiste pincode."</string>
<string name="kg_invalid_sim_pin_hint" msgid="4821601451222564077">"Voer een pincode van 4 tot 8 cijfers in."</string>
<string name="kg_invalid_sim_puk_hint" msgid="2539364558870734339">"De pukcode is acht cijfers lang."</string>
- <string name="kg_invalid_puk" msgid="4809502818518963344">"Geef de juiste pukcode opnieuw op. Bij herhaalde pogingen wordt de simkaart permanent uitgeschakeld."</string>
+ <string name="kg_invalid_puk" msgid="4809502818518963344">"Geef de juiste pukcode opnieuw op. Bij herhaalde pogingen wordt de simkaart permanent uitgezet."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"Pincodes komen niet overeen"</string>
<string name="kg_login_too_many_attempts" msgid="699292728290654121">"Te veel patroonpogingen"</string>
<string name="kg_login_instructions" msgid="3619844310339066827">"Als u wilt ontgrendelen, moet u inloggen op je Google-account."</string>
@@ -1660,14 +1691,14 @@
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwijderen"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Volume verhogen tot boven het aanbevolen niveau?\n\nAls je langere tijd op hoog volume naar muziek luistert, raakt je gehoor mogelijk beschadigd."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Snelkoppeling toegankelijkheid gebruiken?"</string>
- <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Als de snelkoppeling is ingeschakeld, kun je drie seconden op beide volumeknoppen drukken om een toegankelijkheidsfunctie te starten."</string>
- <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Snelkoppeling voor toegankelijkheidsfuncties inschakelen?"</string>
+ <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Als de snelkoppeling aanstaat, houd je beide volumeknoppen 3 seconden ingedrukt om een toegankelijkheidsfunctie te starten."</string>
+ <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Snelkoppeling voor toegankelijkheidsfuncties aanzetten?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Als je beide volumetoetsen een paar seconden ingedrukt houdt, schakel je de toegankelijkheidsfuncties in. Hierdoor kan de manier veranderen waarop je apparaat werkt.\n\nHuidige functies:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nJe kunt de geselecteerde functies wijzigen via Instellingen > Toegankelijkheid."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
- <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Snelkoppeling voor <xliff:g id="SERVICE">%1$s</xliff:g> inschakelen?"</string>
- <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Als je beide volumetoetsen een paar seconden ingedrukt houdt, wordt de toegankelijkheidsfunctie <xliff:g id="SERVICE">%1$s</xliff:g> ingeschakeld. Hierdoor kan de manier veranderen waarop je apparaat werkt.\n\nJe kunt deze sneltoets op een andere functie instellen via Instellingen > Toegankelijkheid."</string>
- <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Inschakelen"</string>
- <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Niet inschakelen"</string>
+ <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Snelkoppeling voor <xliff:g id="SERVICE">%1$s</xliff:g> aanzetten?"</string>
+ <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Als je beide volumetoetsen een paar seconden ingedrukt houdt, wordt de toegankelijkheidsfunctie <xliff:g id="SERVICE">%1$s</xliff:g> aangezet. Hierdoor kan de manier veranderen waarop je apparaat werkt.\n\nJe kunt deze sneltoets op een andere functie instellen via Instellingen > Toegankelijkheid."</string>
+ <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aanzetten"</string>
+ <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Niet aanzetten"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"AAN"</string>
<string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"UIT"</string>
<string name="accessibility_enable_service_title" msgid="3931558336268541484">"Toestaan dat <xliff:g id="SERVICE">%1$s</xliff:g> volledige controle over je apparaat heeft?"</string>
@@ -1682,16 +1713,16 @@
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tik op een functie om deze te gebruiken:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Functies kiezen voor gebruik met de knop Toegankelijkheid"</string>
<string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Functies kiezen voor gebruik met de sneltoets via de volumeknop"</string>
- <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> is uitgeschakeld"</string>
+ <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> staat uit"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Snelkoppelingen bewerken"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klaar"</string>
- <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Sneltoets uitschakelen"</string>
+ <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Sneltoets uitzetten"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sneltoets gebruiken"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Kleurinversie"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Kleurcorrectie"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra gedimd"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> is ingeschakeld."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> uitgeschakeld."</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> staat aan."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> staat uit."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Houd beide volumetoetsen drie seconden ingedrukt om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruiken"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Kies een functie om te gebruiken als je op de knop Toegankelijkheid tikt:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Kies een functie om te gebruiken met het toegankelijkheidsgebaar (met twee vingers omhoog swipen vanaf de onderkant van het scherm):"</string>
@@ -1794,7 +1825,7 @@
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"Geannuleerd"</string>
<string name="write_fail_reason_cannot_write" msgid="432118118378451508">"Fout bij schrijven van content"</string>
<string name="reason_unknown" msgid="5599739807581133337">"onbekend"</string>
- <string name="reason_service_unavailable" msgid="5288405248063804713">"Afdrukservice niet ingeschakeld"</string>
+ <string name="reason_service_unavailable" msgid="5288405248063804713">"Afdrukservice staat niet aan"</string>
<string name="print_service_installed_title" msgid="6134880817336942482">"<xliff:g id="NAME">%s</xliff:g>-service geïnstalleerd"</string>
<string name="print_service_installed_message" msgid="7005672469916968131">"Tik om in te schakelen"</string>
<string name="restr_pin_enter_admin_pin" msgid="1199419462726962697">"Beheerderspincode invoeren"</string>
@@ -1832,11 +1863,11 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Geüpdatet door je beheerder"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Verwijderd door je beheerder"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Batterijbesparing doet het volgende om de batterijduur te verlengen:\n\n• Het donkere thema inschakelen\n• Achtergrondactiviteit, bepaalde visuele effecten en andere functies (zoals \'Hey Google\') uitschakelen of beperken\n\n"<annotation id="url">"Meer informatie"</annotation></string>
- <string name="battery_saver_description" msgid="6794188153647295212">"Batterijbesparing doet het volgende om de batterijduur te verlengen:\n\n• Het donkere thema inschakelen.\n• Achtergrondactiviteit, bepaalde visuele effecten en andere functies (zoals \'Hey Google\') uitschakelen of beperken."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Batterijbesparing doet het volgende om de batterijduur te verlengen:\n\n• Donkere thema aanzetten\n• Achtergrondactiviteit, bepaalde visuele effecten en andere functies (zoals \'Hey Google\') uitzetten of beperken\n\n"<annotation id="url">"Meer informatie"</annotation></string>
+ <string name="battery_saver_description" msgid="6794188153647295212">"Batterijbesparing doet het volgende om de batterijduur te verlengen:\n\n• Donker thema aanzetten.\n• Achtergrondactiviteit, bepaalde visuele effecten en andere functies (zoals \'Hey Google\') uitzetten of beperken."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Databesparing beperkt het datagebruik door te voorkomen dat sommige apps gegevens sturen of ontvangen op de achtergrond. De apps die je open hebt, kunnen nog steeds data verbruiken, maar doen dit minder vaak. Afbeeldingen worden dan bijvoorbeeld niet weergegeven totdat je erop tikt."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Databesparing aanzetten?"</string>
- <string name="data_saver_enable_button" msgid="4399405762586419726">"Inschakelen"</string>
+ <string name="data_saver_enable_button" msgid="4399405762586419726">"Aanzetten"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
<item quantity="other">%1$d minuten (tot <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="one">Eén minuut (tot <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
@@ -1899,7 +1930,7 @@
<string name="notification_verified_content_description" msgid="6401483602782359391">"Geverifieerd"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Uitvouwen"</string>
<string name="expand_button_content_description_expanded" msgid="7484217944948667489">"Samenvouwen"</string>
- <string name="expand_action_accessibility" msgid="1947657036871746627">"uitvouwen in-/uitschakelen"</string>
+ <string name="expand_action_accessibility" msgid="1947657036871746627">"uitvouwen aan- of uitzetten"</string>
<string name="usb_midi_peripheral_name" msgid="490523464968655741">"Poort voor Android-USB-randapparatuur"</string>
<string name="usb_midi_peripheral_manufacturer_name" msgid="7557148557088787741">"Android"</string>
<string name="usb_midi_peripheral_product_name" msgid="2836276258480904434">"Poort voor USB-randapparatuur"</string>
@@ -1935,9 +1966,9 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is nu niet beschikbaar. Dit wordt beheerd door <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Meer info"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"App niet meer onderbreken"</string>
- <string name="work_mode_off_title" msgid="5503291976647976560">"Werkprofiel inschakelen?"</string>
- <string name="work_mode_off_message" msgid="8417484421098563803">"Je werk-apps, meldingen, gegevens en andere functies van je werkprofiel worden uitgeschakeld"</string>
- <string name="work_mode_turn_on" msgid="3662561662475962285">"Inschakelen"</string>
+ <string name="work_mode_off_title" msgid="5503291976647976560">"Werkprofiel aanzetten?"</string>
+ <string name="work_mode_off_message" msgid="8417484421098563803">"Je werk-apps, meldingen, gegevens en andere functies van je werkprofiel worden uitgezet"</string>
+ <string name="work_mode_turn_on" msgid="3662561662475962285">"Aanzetten"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"App is niet beschikbaar"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is momenteel niet beschikbaar."</string>
<string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Deze app is ontwikkeld voor een oudere versie van Android en werkt mogelijk niet op de juiste manier. Controleer op updates of neem contact op met de ontwikkelaar."</string>
@@ -1957,7 +1988,7 @@
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demo starten…"</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"Apparaat resetten…"</string>
- <string name="suspended_widget_accessibility" msgid="6331451091851326101">"<xliff:g id="LABEL">%1$s</xliff:g> uitgeschakeld"</string>
+ <string name="suspended_widget_accessibility" msgid="6331451091851326101">"<xliff:g id="LABEL">%1$s</xliff:g> staat uit"</string>
<string name="conference_call" msgid="5731633152336490471">"Telefonische vergadering"</string>
<string name="tooltip_popup_title" msgid="7863719020269945722">"Knopinfo"</string>
<string name="app_category_game" msgid="4534216074910244790">"Games"</string>
@@ -2028,7 +2059,7 @@
<string name="shortcut_restore_not_supported" msgid="4763198938588468400">"Kan snelkoppeling niet herstellen omdat de app geen ondersteuning biedt voor \'Back-up maken en terugzetten\'"</string>
<string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"Kan snelkoppeling niet herstellen vanwege een niet-overeenkomende app-ondertekening"</string>
<string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"Kan snelkoppeling niet herstellen"</string>
- <string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"Snelkoppeling is uitgeschakeld"</string>
+ <string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"Snelkoppeling staat uit"</string>
<string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"VERWIJDEREN"</string>
<string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"TOCH OPENEN"</string>
<string name="harmful_app_warning_title" msgid="8794823880881113856">"Schadelijke app gevonden"</string>
@@ -2056,7 +2087,7 @@
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"De batterij raakt mogelijk leeg voordat deze normaal gesproken wordt opgeladen"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batterijbesparing is geactiveerd om de batterijduur te verlengen"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterijbesparing"</string>
- <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterijbesparing is uitgeschakeld"</string>
+ <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterijbesparing staat uit"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefoon is voldoende opgeladen. Functies worden niet meer beperkt."</string>
<string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet is voldoende opgeladen. Functies worden niet meer beperkt."</string>
<string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Apparaat is voldoende opgeladen. Functies worden niet meer beperkt."</string>
@@ -2078,7 +2109,7 @@
<string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-spreadsheet"</string>
<string name="mime_type_presentation" msgid="1145384236788242075">"Presentatie"</string>
<string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-presentatie"</string>
- <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth blijft ingeschakeld in de vliegtuigmodus"</string>
+ <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth blijft aan in de vliegtuigmodus"</string>
<string name="car_loading_profile" msgid="8219978381196748070">"Laden"</string>
<plurals name="file_count" formatted="false" msgid="7063513834724389247">
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> bestanden</item>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Werk"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Persoonlijke weergave"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Werkweergave"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Kan deze content niet delen met werk-apps"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Je IT-beheerder staat niet toe dat je deze content deelt met apps in je werkprofiel"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Kan deze content niet openen met werk-apps"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Je IT-beheerder staat niet toe dat je deze content opent met apps in je werkprofiel"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Kan deze content niet delen met persoonlijke apps"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Je IT-beheerder staat niet toe dat je deze content deelt met apps in je persoonlijke profiel"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Kan deze content niet openen met persoonlijke apps"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Je IT-beheerder staat niet toe dat je deze content opent met apps in je persoonlijke profiel"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Werkprofiel is onderbroken"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Inschakelen"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Er zijn geen werk-apps die deze content kunnen ondersteunen"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Er zijn geen werk-apps die deze content kunnen openen"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Er zijn geen persoonlijke apps die deze content kunnen ondersteunen"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Er zijn geen persoonlijke apps die deze content kunnen openen"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Ontgrendelingspincode voor SIM-netwerk"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Ontgrendelingspincode voor subset van SIM-netwerk"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Ontgrendelingspincode voor zakelijke simkaart"</string>
@@ -2236,9 +2278,11 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Een gedeelte van het scherm vergroten"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Je kunt nu je volledige scherm of een specifiek gedeelte vergroten of schakelen tussen beide opties."</string>
- <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Inschakelen in Instellingen"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aanzetten in Instellingen"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Sluiten"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"<b><xliff:g id="APP">%s</xliff:g></b> heeft toegang tot de microfoon van je apparaat nodig om door te gaan."</string>
<string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"<b><xliff:g id="APP">%s</xliff:g></b> heeft toegang tot de camera van je apparaat nodig om door te gaan."</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 770e4f0..e392f64 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ଆପ୍ ଚାଲୁଛି"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ଆପ୍ଗୁଡ଼ିକ ବ୍ୟାଟେରୀ ଖର୍ଚ୍ଚ କରିଥା\'ନ୍ତି"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ମ୍ୟାଗ୍ନିଫିକେସନ୍"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"ଆକ୍ସେସିବିଲିଟୀ ସୁରକ୍ଷା ନୀତି"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛି"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>ଟି ଆପ୍ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛନ୍ତି"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ବ୍ୟାଟେରୀ ଏବଂ ଡାଟା ବ୍ୟବହାର ଉପରେ ବିବରଣୀ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ଆପଣଙ୍କ ଶାରୀରିକ କାର୍ଯ୍ୟକଳାପ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"କ୍ୟାମେରା"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ଫଟୋ ନିଏ ଓ ଭିଡିଓ ରେକର୍ଡ କରେ"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"ଆଖପାଖର ବ୍ଲୁଟୁଥ୍ ଡିଭାଇସଗୁଡ଼ିକ"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"ଆଖପାଖର ବ୍ଲୁଟୁଥ୍ ଡିଭାଇସଗୁଡ଼ିକୁ ଖୋଜି ସଂଯୋଗ କରନ୍ତୁ"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"କଲ୍ ଲଗ୍"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ଫୋନ୍ କଲ୍ ଲଗ୍ ପଢ଼ନ୍ତୁ ଓ ଲେଖନ୍ତୁ"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ଫୋନ୍"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ଟାବଲେଟ୍ରେ ଥିବା ବ୍ଲୁ-ଟୁଥ୍ର କନଫିଗରେଶନ୍ ଦେଖିବାକୁ ଏବଂ ପେୟାର୍ କରାଯାଇଥିବା ଡିଭାଇସ୍ ସହିତ ସଂଯୋଗ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ରେ ବ୍ଲୁଟୁଥ୍ର କନଫିଗ୍ରେସନ୍ ଦେଖିବା ପାଇଁ ଏବଂ ପେୟାର୍ କରାଯାଇଥିବା ଡିଭାଇସ୍ଗୁଡ଼ିକ ସହ ସଂଯୋଗଗୁଡ଼ିକୁ ତିଆରି ଏବଂ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ଫୋନ୍ରେ ଥିବା ବ୍ଲୁ-ଟୁଥ୍ର କନଫିଗରେଶନ୍ ଦେଖିବାକୁ ଏବଂ ପେୟାର୍ କରାଯାଇଥିବା ଡିଭାଇସ୍ ସହିତ ସଂଯୋଗ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"ଆଖପାଖର ବ୍ଲୁଟୁଥ୍ ଡିଭାଇସଗୁଡ଼ିକୁ ଖୋଜି ପେୟାର୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"ଆଖପାଖର ବ୍ଲୁଟୁଥ୍ ଡିଭାଇସଗୁଡ଼ିକୁ ଖୋଜି ପେୟାର୍ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"ପେୟାର୍ କରାଯାଇଥିବା ବ୍ଲୁଟୁଥ୍ ଡିଭାଇସଗୁଡ଼ିକ ସହ ସଂଯୋଗ କର"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"ପେୟାର୍ କରାଯାଇଥିବା ବ୍ଲୁଟୁଥ୍ ଡିଭାଇସଗୁଡ଼ିକ ସହ ସଂଯୋଗ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ପସନ୍ଦର NFC ପେମେଣ୍ଟ ସେବା ସୂଚନା"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ପଞ୍ଜିକୃତ ଯନ୍ତ୍ର ଏବଂ ମାର୍ଗ ଲକ୍ଷସ୍ଥଳ ପରି ପସନ୍ଦର nfc ପେମେଣ୍ଟ ସେବା ସୂଚନା ପାଇବାକୁ ଆପ୍ ଅନୁମତି କରିଥାଏ।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ନିଅର୍ ଫିଲ୍ଡ କମ୍ୟୁନିକେଶନ୍ ଉପରେ ନିୟନ୍ତ୍ରଣ ରଖନ୍ତୁ"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"ପ୍ରାମାଣିକରଣ କରିବା ସମୟରେ ତ୍ରୁଟି"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଡିଭାଇସର କ୍ରେଡେନ୍ସିଆଲ୍ ଲେଖନ୍ତୁ"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"ଆଂଶିକ ଟିପଚିହ୍ନ ଚିହ୍ନଟ ହେଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ଟିପଚିହ୍ନ ପ୍ରୋସେସ୍ କରାଯାଇପାରିଲା ନାହିଁ। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"ଟିପଚିହ୍ନ ସେନ୍ସର୍ ମଇଳା ହୋଇଯାଇଛି। ଦୟାକରି ସଫା କରନ୍ତୁ ଓ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"ଆଙ୍ଗୁଠି ବହୁତ ଜୋର୍ରେ ଚଲାଗଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ଆଙ୍ଗୁଠି ଖୁବ୍ ଧୀରେ ନିଆଗଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"ଟିପଚିହ୍ନ ପ୍ରମାଣିତ ହେଲା"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି, ଦୟାକରି ସୁନିଶ୍ଚିତ ଦବାନ୍ତୁ"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ଟିପଚିହ୍ନ ହାର୍ଡୱେର୍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ଟିପଚିହ୍ନ ଷ୍ଟୋର୍ କରାଯାଇପାରିବ ନାହିଁ। ଦୟାକରି ପୂର୍ବରୁ ଥିବା ଟିପଚିହ୍ନକୁ କାଢ଼ି ଦିଅନ୍ତୁ।"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"ଟିପଚିହ୍ନର ସମୟ ଶେଷ ହେଲା । ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ଟିପଚିହ୍ନ କାର୍ଯ୍ୟ ବାତିଲ୍ କରାଗଲା।"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ଉପଯୋଗକର୍ତ୍ତା ଟିପଚିହ୍ନ କାର୍ଯ୍ୟ ବାତିଲ୍ କରିଛନ୍ତି।"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ଫେସ୍ ଅନ୍ଲକ୍"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ଆପଣଙ୍କର ମୁହଁ ପୁଣି-ଏନ୍ରୋଲ୍ କରନ୍ତୁ"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ଚିହ୍ନଟକରଣକୁ ଉନ୍ନତ କରିବା ପାଇଁ, ଦୟାକରି ଆପଣଙ୍କର ମୁହଁ ପୁଣି-ଏନ୍ରୋଲ୍ କରନ୍ତୁ।"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"ମୁହଁର ଡାଟା କ୍ୟାପଚର୍ ହେଲାନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"ଅତ୍ୟଧିକ ଉଜ୍ଵଳ। କମ୍ ଉଜ୍ବଳକରଣରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"ଅତ୍ୟଧିକ ଅନ୍ଧକାର। ଉଜ୍ବଳ ଲାଇଟ୍ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"କପି କରାଗଲା"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>ରୁ ପେଷ୍ଟ କରିଛି"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> କ୍ଲିପବୋର୍ଡରୁ ପେଷ୍ଟ କରିଛି"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"ଅଧିକ"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"ମେନୁ"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"ୱାର୍କ"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ବ୍ୟକ୍ତିଗତ ଭ୍ୟୁ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"କାର୍ଯ୍ୟସ୍ଥଳୀ ସମ୍ବନ୍ଧିତ ଭ୍ୟୁ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପଗୁଡ଼ିକ ମାଧ୍ୟମରେ ଏହା ସେୟାର୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"ଆପଣଙ୍କ IT ଆଡମିନ୍ ଆପଣଙ୍କୁ ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲରେ ଆପଗୁଡ଼ିକ ମାଧ୍ୟମରେ ଏହି ବିଷୟବସ୍ତୁକୁ ସେୟାର୍ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତି ନାହିଁ"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପଗୁଡ଼ିକ ମାଧ୍ୟମରେ ଏହି ଆପ୍ ଖୋଲାଯାଇ ପାରିବ ନାହିଁ"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"ଆପଣଙ୍କ IT ଆଡମିନ୍ ଆପଣଙ୍କୁ ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲରେ ଆପଗୁଡ଼ିକ ମାଧ୍ୟମରେ ଏହି ବିଷୟବସ୍ତୁ ଖୋଲିବାକୁ ଅନୁମତି ଦିଅନ୍ତି ନାହିଁ"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"ବ୍ୟକ୍ତିଗତ ଆପଗୁଡ଼ିକ ମାଧ୍ୟମରେ ଏହା ସେୟାର୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"ଆପଣଙ୍କ IT ଆଡମିନ୍ ଆପଣଙ୍କୁ ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ ପ୍ରୋଫାଇଲରେ ଆପଗୁଡ଼ିକ ମାଧ୍ୟମରେ ଏହି ବିଷୟବସ୍ତୁ ସେୟାର୍ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତି ନାହିଁ"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"ବ୍ୟକ୍ତିଗତ ଆପଗୁଡ଼ିକୁ ଖୋଲାଯାଇ ପାରିବ ନାହିଁ"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"ଆପଣଙ୍କ IT ଆଡମିନ୍ ଆପଣଙ୍କୁ ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ ପ୍ରୋଫାଇଲରେ ଆପଗୁଡ଼ିକ ମାଧ୍ୟମରେ ଏହି ବିଷୟବସ୍ତୁକୁ ଖୋଲିବାକୁ ଅନୁମତି ଦିଅନ୍ତି ନାହିଁ"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"ୱାର୍କ ପ୍ରୋଫାଇଲକୁ ବିରତ କରାଯାଇଛି"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ଚାଲୁ କରନ୍ତୁ"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"କୌଣସି କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପ୍ ଏହି ବିଷୟବସ୍ତୁକୁ ସମର୍ଥନ କରିପାରିବ ନାହିଁ"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"କୌଣସି କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପ୍ ଏହି ବିଷୟବସ୍ତୁକୁ ଖୋଲିପାରିବ ନାହିଁ"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"କୌଣସି ବ୍ୟକ୍ତିଗତ ଆପ୍ ଏହି ବିଷୟବସ୍ତୁକୁ ସମର୍ଥନ କରିପାରିବ ନାହିଁ"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"କୌଣସି ବ୍ୟକ୍ତିଗତ ଆପ୍ ଏହି ବିଷୟବସ୍ତୁକୁ ଖୋଲିପାରିବ ନାହିଁ"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ନେଟୱାର୍କ ଅନଲକ୍ PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ନେଟୱାର୍କର ସବସେଟ୍ ଅନଲକ୍ PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM କର୍ପୋରେଟ୍ ଅନଲକ୍ PIN"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"ଆପଣଙ୍କ ସ୍କ୍ରିନର ଏକ ଅଂଶକୁ ମ୍ୟାଗ୍ନିଫାଏ କରନ୍ତୁ"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"ଆପଣ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ବା ଏହାର ଏକ ନିର୍ଦ୍ଦିଷ୍ଟ ଅଞ୍ଚଳକୁ ମ୍ୟାଗ୍ନିଫାଏ କରିପାରିବେ କିମ୍ବା ଉଭୟ ବିକଳ୍ପ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିପାରିବେ।"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ସେଟିଂସରେ ଚାଲୁ କରନ୍ତୁ"</string>
<string name="dismiss_action" msgid="1728820550388704784">"ଖାରଜ କରନ୍ତୁ"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"ଜାରି ରଖିବାକୁ, <b><xliff:g id="APP">%s</xliff:g></b> ଆପଣଙ୍କ ଡିଭାଇସର ମାଇକ୍ରୋଫୋନକୁ ଆକ୍ସେସ୍ ଆବଶ୍ୟକ କରେ।"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index c9267e4..5daf8c88 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ਚੱਲ ਰਹੀ ਐਪ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ਬੈਟਰੀ ਦੀ ਖਪਤ ਕਰਨ ਵਾਲੀਆਂ ਐਪਾਂ"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ਵੱਡਦਰਸ਼ੀਕਰਨ"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"ਪਹੁੰਚਯੋਗਤਾ ਸੁਰੱਖਿਆ ਨੀਤੀ"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ਐਪਾਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ਬੈਟਰੀ ਅਤੇ ਡਾਟਾ ਵਰਤੋਂ ਸਬੰਧੀ ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ਆਪਣੀ ਸਰੀਰਕ ਸਰਗਰਮੀ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"ਕੈਮਰਾ"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ਤਸਵੀਰਾਂ ਲੈਣ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰਨ"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"ਨਜ਼ਦੀਕੀ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"ਨਜ਼ਦੀਕੀ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨੂੰ ਖੋਜੋ ਅਤੇ ਉਹਨਾਂ ਨਾਲ ਕਨੈਕਟ ਕਰੋ"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"ਕਾਲ ਲੌਗ"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ਫ਼ੋਨ ਦੇ ਕਾਲ ਲੌਗ ਨੂੰ ਪੜ੍ਹੋ ਅਤੇ ਲਿਖੋ"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ਫ਼ੋਨ"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ਐਪ ਨੂੰ ਟੈਬਲੈੱਟ ਤੇ ਬਲੂਟੁੱਥ ਦਾ ਸੰਰੂਪਣ ਦੇਖਣ, ਜੋੜਾਬੱਧ ਕੀਤੇ ਡੀਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਸ਼ਨ ਬਣਾਉਣ ਅਤੇ ਸਵੀਕਾਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ \'ਤੇ ਬਲੂਟੁੱਥ ਦਾ ਸੰਰੂਪਣ ਦੇਖਣ, ਜੋੜਾਬੱਧ ਕੀਤੇ ਡੀਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਸ਼ਨ ਬਣਾਉਣ ਅਤੇ ਸਵੀਕਾਰ ਕਰਨ ਦਿੰਦੀ ਹੈ।"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ਐਪ ਨੂੰ ਬਲੂਟੁੱਥ ਤੇ ਬਲੂਟੁੱਥ ਦਾ ਸੰਰੂਪਣ ਦੇਖਣ, ਜੋੜਾਬੱਧ ਕੀਤੇ ਡੀਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਸ਼ਨ ਬਣਾਉਣ ਅਤੇ ਸਵੀਕਾਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"ਨਜ਼ਦੀਕੀ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨੂੰ ਖੋਜੋ ਅਤੇ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"ਐਪ ਨੂੰ ਨਜ਼ਦੀਕੀ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨੂੰ ਖੋਜਣ ਅਤੇ ਉਹਨਾਂ ਨਾਲ ਜੋੜਾਬੱਧ ਕਰਨ ਦਿੰਦੀ ਹੈ"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"ਜੋੜਾਬੱਧ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਟ ਕਰੋ"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"ਐਪਾਂ ਨੂੰ ਜੋੜਾਬੱਧ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਦਿੰਦੀ ਹੈ"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ਤਰਜੀਹੀ NFC ਭੁਗਤਾਨਸ਼ੁਦਾ ਸੇਵਾ ਜਾਣਕਾਰੀ"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ਐਪ ਨੂੰ ਤਰਜੀਹੀ NFC ਭੁਗਤਾਨਸ਼ੁਦਾ ਸੇਵਾ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਕਿ ਰਜਿਸਟਰ ਕੀਤੇ ਸਾਧਨ ਅਤੇ ਮੰਜ਼ਿਲ ਰਸਤਾ।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ਨਜ਼ਦੀਕੀ ਖੇਤਰ ਸੰਚਾਰ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"ਗੜਬੜ ਨੂੰ ਪ੍ਰਮਾਣਿਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣੇ ਡੀਵਾਈਸ ਦੇ ਕ੍ਰੀਡੈਂਸ਼ੀਅਲ ਨੂੰ ਦਾਖਲ ਕਰੋ"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"ਅਧੂਰਾ ਫਿੰਗਰਪ੍ਰਿਟ ਮਿਲਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ਫਿੰਗਰਪ੍ਰਿੰਟ \'ਤੇ ਪ੍ਰਕਿਰਿਆ ਨਹੀਂ ਹੋ ਸਕੀ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਗੰਦਾ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਇਸਨੂੰ ਸਾਫ਼ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"ਉਂਗਲ ਨੂੰ ਬਹੁਤ ਤੇਜ਼ ਲੈ ਜਾਇਆ ਗਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ਉਂਗਲ ਕਾਫ਼ੀ ਹੌਲੀ ਮੂਵ ਹੋਈ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ, ਕਿਰਪਾ ਕਰਕੇ \'ਪੁਸ਼ਟੀ ਕਰੋ\' ਦਬਾਓ"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਮੌਜੂਦਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਟਾਓ।"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ਚਿਹਰਾ ਅਣਲਾਕ"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ਆਪਣਾ ਚਿਹਰਾ ਮੁੜ-ਦਰਜ ਕਰੋ"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ਪਛਾਣ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ, ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਚਿਹਰੇ ਨੂੰ ਮੁੜ-ਦਰਜ ਕਰੋ"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"ਸਟੀਕ ਚਿਹਰਾ ਡਾਟਾ ਕੈਪਚਰ ਨਹੀਂ ਹੋਇਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਚਮਕ। ਹਲਕੀ ਚਮਕ ਵਰਤ ਕੇ ਦੇਖੋ।"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"ਬਹੁਤ ਗੂੜ੍ਹਾ। ਤੇਜ਼ ਰੋਸ਼ਨੀ ਕਰਕੇ ਦੇਖੋ।"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"ਕਾਪੀ ਕੀਤੀ ਗਈ"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> ਤੋਂ ਕਾਪੀ ਕੀਤੇ ਡਾਟੇ ਨੂੰ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ਵਿੱਚ ਪੇਸਟ ਕੀਤਾ ਗਿਆ"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"ਕਲਿੱਪਬੋਰਡ ਦੇ ਡਾਟੇ ਨੂੰ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ਵਿੱਚ ਪੇਸਟ ਕੀਤਾ ਗਿਆ"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"ਹੋਰ"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"ਮੀਨੂ+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,8 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ਸ਼ਾਰਟਕੱਟ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ਰੰਗ ਪਲਟਨਾ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ਰੰਗ ਸੁਧਾਈ"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (3222994553174604132) -->
- <skip />
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ਜ਼ਿਆਦਾ ਘੱਟ ਚਮਕ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string>
<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> ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਕੁੰਜੀਆਂ ਨੂੰ 3 ਸਕਿੰਟਾਂ ਲਈ ਦਬਾਈ ਰੱਖੋ"</string>
@@ -2111,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"ਕੰਮ"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ਵਿਅਕਤੀਗਤ ਦ੍ਰਿਸ਼"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"ਕਾਰਜ ਦ੍ਰਿਸ਼"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"ਇਹ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਨਾਲ ਸਾਂਝਾ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"ਤੁਹਾਡਾ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਨੂੰ ਤੁਹਾਡੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਐਪਾਂ ਨਾਲ ਇਸ ਸਮੱਗਰੀ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੰਦਾ"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਨਾਲ ਇਸ ਨੂੰ ਖੋਲ੍ਹਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"ਤੁਹਾਡਾ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਨੂੰ ਤੁਹਾਡੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਐਪਾਂ ਨਾਲ ਇਸ ਸਮੱਗਰੀ ਨੂੰ ਖੋਲ੍ਹਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੰਦਾ"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"ਇਸ ਨੂੰ ਨਿੱਜੀ ਐਪਾਂ ਨਾਲ ਸਾਂਝਾ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"ਤੁਹਾਡਾ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਨੂੰ ਤੁਹਾਡੀ ਨਿੱਜੀ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਐਪਾਂ ਨਾਲ ਇਸ ਸਮੱਗਰੀ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੰਦਾ"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"ਨਿੱਜੀ ਐਪਾਂ ਨਾਲ ਇਸ ਨੂੰ ਖੋਲ੍ਹਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"ਤੁਹਾਡਾ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਨੂੰ ਤੁਹਾਡੀ ਨਿੱਜੀ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਐਪਾਂ ਨਾਲ ਇਸ ਸਮੱਗਰੀ ਨੂੰ ਖੋਲ੍ਹਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੰਦਾ"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਰੋਕਿਆ ਗਿਆ ਹੈ"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ਚਾਲੂ ਕਰੋ"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"ਕੋਈ ਕੰਮ ਸੰਬੰਧੀ ਐਪ ਇਸ ਸਮੱਗਰੀ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰ ਸਕਦੀ"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ਕੋਈ ਕੰਮ ਸੰਬੰਧੀ ਐਪ ਇਸ ਸਮੱਗਰੀ ਨੂੰ ਨਹੀਂ ਖੋਲ੍ਹ ਸਕਦੀ"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"ਕੋਈ ਨਿੱਜੀ ਐਪ ਇਸ ਸਮੱਗਰੀ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰ ਸਕਦੀ"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"ਕੋਈ ਨਿੱਜੀ ਐਪ ਇਸ ਸਮੱਗਰੀ ਨੂੰ ਨਹੀਂ ਖੋਲ੍ਹ ਸਕਦੀ"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"ਸਿਮ ਨੈੱਟਵਰਕ ਅਣਲਾਕ ਪਿੰਨ"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"ਸਿਮ ਨੈੱਟਵਰਕ ਸਬਸੈੱਟ ਅਣਲਾਕ ਪਿੰਨ"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"ਸਿਮ ਕਾਰਪੋਰੇਟ ਅਣਲਾਕ ਪਿੰਨ"</string>
@@ -2237,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਕਿਸੇ ਹਿੱਸੇ ਨੂੰ ਵੱਡਦਰਸ਼ੀ ਕਰੋ"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"ਤੁਸੀਂ ਹੁਣ ਆਪਣੀ ਪੂਰੀ ਸਕ੍ਰੀਨ ਜਾਂ ਸਕ੍ਰੀਨ ਦੇ ਕਿਸੇ ਖਾਸ ਹਿੱਸੇ ਨੂੰ ਵੱਡਦਰਸ਼ੀ ਕਰ ਸਕਦੇ ਹੋ, ਜਾਂ ਇਹਨਾਂ ਦੋਨਾਂ ਵਿਕਲਪਾਂ ਵਿਚਾਲੇ ਸਵਿੱਚ ਕਰ ਸਕਦੇ ਹੋ।"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਾਲੂ ਕਰੋ"</string>
<string name="dismiss_action" msgid="1728820550388704784">"ਖਾਰਜ ਕਰੋ"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"ਜਾਰੀ ਰੱਖਣ ਲਈ, <b><xliff:g id="APP">%s</xliff:g></b> ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਤੱਕ ਪਹੁੰਚ ਦੀ ਲੋੜ ਹੈ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index c78efd7..c07b40f 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -300,7 +300,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Działa aplikacja"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacje zużywające baterię"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Powiększenie"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Zasady bezpieczeństwa związane z ułatwieniami dostępu"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> zużywa baterię"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Liczba aplikacji zużywających baterię: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i użycia danych"</string>
@@ -325,6 +326,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"dostęp do aktywności fizycznej"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Aparat"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"robienie zdjęć i nagrywanie filmów"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Urządzenia Bluetooth w pobliżu"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"wykrywanie urządzeń Bluetooth w pobliżu i łączenie się z nimi"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Rejestry połączeń"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"odczytywanie i zapisywanie rejestru połączeń telefonicznych"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -538,6 +541,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Pozwala aplikacji na dostęp do konfiguracji Bluetooth na tablecie oraz na nawiązywanie i akceptowanie połączeń ze sparowanych urządzeń."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Pozwala aplikacji odczytywać konfigurację Bluetootha na urządzeniu z Androidem TV oraz nawiązywać i akceptować połączenia ze sparowanymi urządzeniami."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Pozwala aplikacji na dostęp do konfiguracji Bluetooth na telefonie oraz na nawiązywanie i akceptowanie połączeń ze sparowanych urządzeń."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"wykrywanie i parowanie urządzeń Bluetooth w pobliżu"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Zezwala na wykrywanie i parowanie przez aplikację urządzeń Bluetooth w pobliżu"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"łączenie ze sparowanymi urządzeniami Bluetooth"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Zezwala na łączenie aplikacji ze sparowanymi urządzeniami Bluetooth"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informacje o preferowanych usługach płatniczych NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Pozwala aplikacji uzyskiwać informacje o preferowanych usługach płatniczych NFC, np. zarejestrowanych pomocach i miejscach docelowych tras."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrolowanie łączności Near Field Communication"</string>
@@ -573,18 +580,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Podczas uwierzytelniania wystąpił błąd"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Używaj blokady ekranu"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Podaj dane logowania do urządzenia, aby kontynuować"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Odcisk palca został odczytany tylko częściowo. Spróbuj ponownie."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Nie udało się przetworzyć odcisku palca. Spróbuj ponownie."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Czytnik linii papilarnych jest zabrudzony. Wyczyść go i spróbuj ponownie."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Palec został podniesiony zbyt wcześnie. Spróbuj jeszcze raz."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Palec został obrócony zbyt wolno. Spróbuj ponownie."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Uwierzytelniono odciskiem palca"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Twarz rozpoznana"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Twarz rozpoznana, kliknij Potwierdź"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Czytnik linii papilarnych nie jest dostępny."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Nie można zapisać odcisku palca. Usuń istniejący odcisk palca."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Osiągnięto limit czasu odczytu odcisków palców. Spróbuj ponownie."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Odczyt odcisku palca został anulowany."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Odczyt odcisku palca został anulowany przez użytkownika."</string>
@@ -609,6 +626,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Rozpoznawanie twarzy"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Zarejestruj swoją twarz ponownie"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Aby poprawić rozpoznawanie, ponownie zarejestruj swoją twarz"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Nie udało się zarejestrować danych twarzy. Spróbuj ponownie."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Zbyt jasno. Spróbuj przy słabszym świetle."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Zbyt ciemno. Spróbuj w jaśniejszym świetle."</string>
@@ -1012,6 +1037,12 @@
<string name="copied" msgid="4675902854553014676">"Skopiowano"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Aplikacja <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> wkleiła dane z aplikacji <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Aplikacja <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> wkleiła dane ze schowka"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Więcej"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2178,20 +2209,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Służbowe"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Widok osobisty"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Widok służbowy"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Nie można udostępnić aplikacjom służbowym"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Administrator IT nie pozwala na udostępnianie tej zawartości w profilu służbowym"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Nie można otworzyć w aplikacjach służbowych"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Administrator IT nie pozwala na otwieranie tej zawartości w profilu służbowym"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Nie można udostępnić aplikacjom osobistym"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Administrator IT nie pozwala na udostępnianie tej zawartości w profilu osobistym"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Nie można otworzyć w aplikacjach osobistych"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Administrator IT nie pozwala na otwieranie tej zawartości w profilu osobistym"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Działanie profilu służbowego jest wstrzymane"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Włącz"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Brak aplikacji służbowych, które obsługują tę zawartość"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Brak aplikacji służbowych, które mogą otworzyć tę zawartość"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Brak aplikacji osobistych, które obsługują tę zawartość"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Brak aplikacji osobistych, które mogą otworzyć tę zawartość"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Kod PIN do karty SIM odblokowujący sieć"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Kod PIN odblokowujący podzbiór sieci na karcie SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Kod PIN odblokowujący dane korporacyjne na karcie SIM"</string>
@@ -2304,8 +2346,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Powiększ część ekranu"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Możesz powiększyć ekran lub konkretny obszar bądź przełączać się między tymi opcjami."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Włącz w Ustawieniach"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Odrzuć"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Aby kontynuować, musisz przyznać aplikacji „<xliff:g id="APP">%s</xliff:g>” dostęp do mikrofonu urządzenia."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 5962304..c286e23 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App em execução"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que estão consumindo a bateria"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliação"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Política de segurança de acessibilidade"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo a bateria"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps estão consumindo a bateria"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"acessar sua atividade física"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Câmera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"tire fotos e grave vídeos"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Dispositivos Bluetooth por perto"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"descobrir e se conectar a dispositivos Bluetooth por perto"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Registro de chamadas"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ler e gravar o registro de chamadas telefônicas"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefone"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que o app acesse a configuração do Bluetooth no tablet, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que o app acesse a configuração do Bluetooth no dispositivo Android TV, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que o app acesse a configuração do Bluetooth no telefone, além de fazer e aceitar conexões com dispositivos pareados."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"descobrir e se parear a disp. Bluetooth por perto"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permite que o app descubra e se pareie a dispositivos Bluetooth por perto"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"conecte-se a dispositivos Bluetooth pareados"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permite que o app se conecte a dispositivos Bluetooth pareados"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informações preferidas de serviço de pagamento por NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que o app acesse as informações preferidas de serviço de pagamento por NFC, como auxílios registrados ou destinos de trajetos."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar a comunicação a curta distância"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Erro na autenticação"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueio de tela"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Insira as credenciais do dispositivo para continuar"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Impressão digital parcial detectada. Tente novamente."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Não foi possível processar a impressão digital. Tente novamente."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"O sensor de impressão digital está sujo. Limpe-o e tente novamente."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"O dedo foi retirado rápido demais. Tente novamente."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"O movimento do dedo está muito lento. Tente novamente."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Impressão digital autenticada"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Rosto autenticado"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado, pressione \"Confirmar\""</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware de impressão digital não disponível."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Não foi possível armazenar a impressão digital. Remova uma impressão digital já existente."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operação de impressão digital cancelada."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operação de impressão digital cancelada pelo usuário."</string>
@@ -603,6 +620,10 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Desbloqueio facial"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Registre seu rosto novamente"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Para melhorar o reconhecimento, registre seu rosto novamente"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Configure o desbloqueio facial"</string>
+ <string name="face_setup_notification_content" msgid="5463999831057751676">"Desbloqueie o smartphone olhando para ele"</string>
+ <string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Configure mais formas de desbloquear a tela"</string>
+ <string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Toque para adicionar uma impressão digital"</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Dados precisos não capturados. Tente novamente."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Muito iluminado. Diminua a iluminação."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Muito escuro. Use uma iluminação mais clara."</string>
@@ -1006,6 +1027,9 @@
<string name="copied" msgid="4675902854553014676">"Copiado"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Dados do app <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> colados no app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Dados da área de transferência colados no app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
+ <string name="pasted_text" msgid="4298871641549173733">"O app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou o texto copiado"</string>
+ <string name="pasted_image" msgid="4729097394781491022">"O app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou uma imagem copiada"</string>
+ <string name="pasted_content" msgid="646276353060777131">"O app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou o conteúdo copiado"</string>
<string name="more_item_label" msgid="7419249600215749115">"Mais"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2134,19 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Trabalho"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Visualização pessoal"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Visualização de trabalho"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Não é possível compartilhar este conteúdo com apps de trabalho"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Seu administrador de TI não permite que você compartilhe este conteúdo com apps no seu perfil de trabalho"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Não é possível abrir usando apps de trabalho"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Seu administrador de TI não permite que você abra este conteúdo usando apps do seu perfil de trabalho"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Não é possível compartilhar este conteúdo com apps pessoais"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Seu administrador de TI não permite que você compartilhe este conteúdo com apps no seu perfil pessoal"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Não é possível abrir este conteúdo com apps pessoais"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Seu administrador de TI não permite que você abra este conteúdo usando apps do seu perfil pessoal"</string>
+ <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"Compartilhamento bloqueado pelo administrador de TI"</string>
+ <string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"Não é possível compartilhar esse conteúdo com apps de trabalho"</string>
+ <string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"Não é possível abrir esse conteúdo com apps de trabalho"</string>
+ <string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"Não é possível compartilhar esse conteúdo com apps pessoais"</string>
+ <string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"Não é possível abrir esse conteúdo com apps pessoais"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"O perfil de trabalho está pausado"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Ativar"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Apps de trabalho não são compatíveis com este conteúdo"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Apps de trabalho não podem abrir este conteúdo"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Apps pessoais não são compatíveis com este conteúdo"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Apps pessoais não podem abrir este conteúdo"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"Toque para ativar"</string>
+ <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nenhum app de trabalho"</string>
+ <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nenhum app pessoal"</string>
+ <string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Abrir no perfil pessoal do app <xliff:g id="APP">%s</xliff:g>?"</string>
+ <string name="miniresolver_open_in_work" msgid="152208044699347924">"Abrir no perfil de trabalho de app <xliff:g id="APP">%s</xliff:g>?"</string>
+ <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar o navegador pessoal"</string>
+ <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar o navegador de trabalho"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN para desbloqueio da rede do chip"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN para desbloqueio do subconjunto de rede do chip"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN para desbloqueio do chip corporativo"</string>
@@ -2236,8 +2259,9 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Ampliar parte da tela"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Agora você pode ampliar toda a tela, uma área específica ou alternar entre as duas opções."</string>
+ <string name="window_magnification_prompt_title" msgid="2876703640772778215">"Novas configurações de ampliação"</string>
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ativar nas Configurações"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Dispensar"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Para continuar, o app <b><xliff:g id="APP">%s</xliff:g></b> precisa acessar o microfone do dispositivo."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 54d0a2e..80b0f03 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicação em execução"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que estão a consumir bateria"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliação"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Política de segurança de acessibilidade"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a consumir bateria."</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicações estão a consumir bateria."</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toque para obter detalhes acerca da utilização da bateria e dos dados"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"aceder à sua atividade física"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Câmara"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"tirar fotos e gravar vídeos"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Dispositivos Bluetooth próximos"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"descubra e ligue-se a dispositivos Bluetooth próximos"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Registos de chamadas"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ler e escrever o registo de chamadas do telemóvel"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telemóvel"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que a app visualize a configuração do Bluetooth no tablet e que estabeleça e aceite ligações com dispositivos emparelhados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que a app visualize a configuração do Bluetooth no seu dispositivo Android TV e que estabeleça e aceite ligações com dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que a app visualize a configuração do Bluetooth no telemóvel e que estabeleça e aceite ligações com dispositivos emparelhados."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"descobrir e sincronizar disp. Bluetooth próximos"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permite que a app descubra e sincronize com dispositivos Bluetooth próximos"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"ligar-se a dispositivos Bluetooth sincronizados"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permite que a app se ligue a dispositivos Bluetooth sincronizados"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informações de serviços de pagamento com NFC preferenciais"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que a app obtenha informações de serviços de pagamento com NFC preferenciais, como apoios registados e destino da rota."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlo Near Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Erro ao autenticar."</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utilizar o bloqueio de ecrã"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Introduza a credencial do dispositivo para continuar."</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Impressão digital parcial detetada. Tente novamente."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Não foi possível processar a impressão digital. Tente novamente."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"O sensor de impressões digitais está sujo. Limpe-o e tente novamente."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"O dedo moveu-se demasiado rápido. Tente novamente."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Moveu o dedo demasiado lentamente. Tente novamente."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"A impressão digital foi autenticada."</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Rosto autenticado."</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado. Prima Confirmar."</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware de impressão digital não disponível."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Não é possível armazenar a impressão digital. Remova uma impressão digital existente."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Foi atingido o limite de tempo da impressão digital. Tente novamente."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operação de impressão digital cancelada."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operação de impressão digital cancelada pelo utilizador."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Desbloqueio facial"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Volte a inscrever o seu rosto"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Para melhorar o reconhecimento, volte a inscrever o seu rosto."</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Imp. capt. dados rosto precisos. Tente novamente."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Demasiado clara. Experimente uma luz mais suave."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Demasiado escura. Experimente local com mais luz."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Copiado"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"A app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou da app <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"A app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou da área de transferência"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Mais"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Trabalho"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Vista pessoal"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Vista de trabalho"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Não é possível partilhar este conteúdo com apps de trabalho"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"O seu administrador de TI não lhe permite partilhar este conteúdo com apps no seu perfil de trabalho."</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Não é possível abrir este conteúdo com apps de trabalho"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"O seu administrador de TI não lhe permite abrir este conteúdo com apps no seu perfil de trabalho."</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Não é possível partilhar este conteúdo com apps pessoais"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"O seu administrador de TI não lhe permite partilhar este conteúdo com apps no seu perfil pessoal."</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Não é possível abrir este conteúdo com apps pessoais"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"O seu administrador de TI não lhe permite abrir este conteúdo com apps no seu perfil pessoal."</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Perfil de trabalho em pausa"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Ativar"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Este conteúdo não é suportado por nenhuma app de trabalho."</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Este conteúdo não pode ser aberto por nenhuma app de trabalho."</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Este conteúdo não é suportado por nenhuma app pessoal."</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Este conteúdo não pode ser aberto por nenhuma app pessoal."</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN para desbloqueio de rede do cartão SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN para desbloqueio do subconjunto da rede do cartão SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN para desbloqueio empresarial do cartão SIM"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Amplie parte do ecrã"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Já pode ampliar o ecrã inteiro, uma área específica ou alternar entre as duas opções."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ativar nas Definições"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Ignorar"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Para continuar, a app <b><xliff:g id="APP">%s</xliff:g></b> precisa de acesso ao microfone do dispositivo."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 5962304..c286e23 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App em execução"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que estão consumindo a bateria"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliação"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Política de segurança de acessibilidade"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo a bateria"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps estão consumindo a bateria"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"acessar sua atividade física"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Câmera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"tire fotos e grave vídeos"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Dispositivos Bluetooth por perto"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"descobrir e se conectar a dispositivos Bluetooth por perto"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Registro de chamadas"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ler e gravar o registro de chamadas telefônicas"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefone"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que o app acesse a configuração do Bluetooth no tablet, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que o app acesse a configuração do Bluetooth no dispositivo Android TV, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que o app acesse a configuração do Bluetooth no telefone, além de fazer e aceitar conexões com dispositivos pareados."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"descobrir e se parear a disp. Bluetooth por perto"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permite que o app descubra e se pareie a dispositivos Bluetooth por perto"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"conecte-se a dispositivos Bluetooth pareados"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permite que o app se conecte a dispositivos Bluetooth pareados"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informações preferidas de serviço de pagamento por NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que o app acesse as informações preferidas de serviço de pagamento por NFC, como auxílios registrados ou destinos de trajetos."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar a comunicação a curta distância"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Erro na autenticação"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueio de tela"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Insira as credenciais do dispositivo para continuar"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Impressão digital parcial detectada. Tente novamente."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Não foi possível processar a impressão digital. Tente novamente."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"O sensor de impressão digital está sujo. Limpe-o e tente novamente."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"O dedo foi retirado rápido demais. Tente novamente."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"O movimento do dedo está muito lento. Tente novamente."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Impressão digital autenticada"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Rosto autenticado"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado, pressione \"Confirmar\""</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware de impressão digital não disponível."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Não foi possível armazenar a impressão digital. Remova uma impressão digital já existente."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operação de impressão digital cancelada."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operação de impressão digital cancelada pelo usuário."</string>
@@ -603,6 +620,10 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Desbloqueio facial"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Registre seu rosto novamente"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Para melhorar o reconhecimento, registre seu rosto novamente"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Configure o desbloqueio facial"</string>
+ <string name="face_setup_notification_content" msgid="5463999831057751676">"Desbloqueie o smartphone olhando para ele"</string>
+ <string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Configure mais formas de desbloquear a tela"</string>
+ <string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Toque para adicionar uma impressão digital"</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Dados precisos não capturados. Tente novamente."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Muito iluminado. Diminua a iluminação."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Muito escuro. Use uma iluminação mais clara."</string>
@@ -1006,6 +1027,9 @@
<string name="copied" msgid="4675902854553014676">"Copiado"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Dados do app <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> colados no app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Dados da área de transferência colados no app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
+ <string name="pasted_text" msgid="4298871641549173733">"O app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou o texto copiado"</string>
+ <string name="pasted_image" msgid="4729097394781491022">"O app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou uma imagem copiada"</string>
+ <string name="pasted_content" msgid="646276353060777131">"O app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou o conteúdo copiado"</string>
<string name="more_item_label" msgid="7419249600215749115">"Mais"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2134,19 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Trabalho"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Visualização pessoal"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Visualização de trabalho"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Não é possível compartilhar este conteúdo com apps de trabalho"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Seu administrador de TI não permite que você compartilhe este conteúdo com apps no seu perfil de trabalho"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Não é possível abrir usando apps de trabalho"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Seu administrador de TI não permite que você abra este conteúdo usando apps do seu perfil de trabalho"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Não é possível compartilhar este conteúdo com apps pessoais"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Seu administrador de TI não permite que você compartilhe este conteúdo com apps no seu perfil pessoal"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Não é possível abrir este conteúdo com apps pessoais"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Seu administrador de TI não permite que você abra este conteúdo usando apps do seu perfil pessoal"</string>
+ <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"Compartilhamento bloqueado pelo administrador de TI"</string>
+ <string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"Não é possível compartilhar esse conteúdo com apps de trabalho"</string>
+ <string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"Não é possível abrir esse conteúdo com apps de trabalho"</string>
+ <string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"Não é possível compartilhar esse conteúdo com apps pessoais"</string>
+ <string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"Não é possível abrir esse conteúdo com apps pessoais"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"O perfil de trabalho está pausado"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Ativar"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Apps de trabalho não são compatíveis com este conteúdo"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Apps de trabalho não podem abrir este conteúdo"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Apps pessoais não são compatíveis com este conteúdo"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Apps pessoais não podem abrir este conteúdo"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"Toque para ativar"</string>
+ <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nenhum app de trabalho"</string>
+ <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nenhum app pessoal"</string>
+ <string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Abrir no perfil pessoal do app <xliff:g id="APP">%s</xliff:g>?"</string>
+ <string name="miniresolver_open_in_work" msgid="152208044699347924">"Abrir no perfil de trabalho de app <xliff:g id="APP">%s</xliff:g>?"</string>
+ <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar o navegador pessoal"</string>
+ <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar o navegador de trabalho"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN para desbloqueio da rede do chip"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN para desbloqueio do subconjunto de rede do chip"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN para desbloqueio do chip corporativo"</string>
@@ -2236,8 +2259,9 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Ampliar parte da tela"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Agora você pode ampliar toda a tela, uma área específica ou alternar entre as duas opções."</string>
+ <string name="window_magnification_prompt_title" msgid="2876703640772778215">"Novas configurações de ampliação"</string>
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ativar nas Configurações"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Dispensar"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Para continuar, o app <b><xliff:g id="APP">%s</xliff:g></b> precisa acessar o microfone do dispositivo."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 2d7d149..a3435a3 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -297,7 +297,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicația rulează"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicațiile consumă bateria"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Mărire"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Politica de securitate privind accesibilitatea"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> folosește bateria"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicații folosesc bateria"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Atingeți pentru mai multe detalii privind bateria și utilizarea datelor"</string>
@@ -322,6 +323,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"accesați activitatea fizică"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Camera foto"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"fotografieze și să înregistreze videoclipuri"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Dispozitive Bluetooth din apropiere"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"să descopere și să se conecteze la dispozitive Bluetooth din apropiere"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Jurnale de apeluri"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"să citească și să scrie jurnalul de apeluri telefonice"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -535,6 +538,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite aplicației să vadă configurația tabletei Bluetooth, să efectueze și să accepte conexiuni cu dispozitive împerecheate."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite aplicației să vadă configurația conexiunii prin Bluetooth a dispozitivului Android TV, să efectueze și să accepte conexiuni cu dispozitive împerecheate."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite aplicației să vadă configurația telefonului Bluetooth, să efectueze și să accepte conexiuni cu dispozitive împerecheate."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"să descopere și să asocieze dispozitive Bluetooth din apropiere"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permite aplicației să descopere și să asocieze dispozitive Bluetooth din apropiere"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"să se conecteze la dispozitive Bluetooth asociate"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permite aplicației să se conecteze la dispozitive Bluetooth asociate"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informații despre serviciul de plăți NFC preferat"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite aplicației să obțină informații despre serviciul de plăți NFC preferat, de exemplu, identificatorii de aplicație înregistrați și destinația traseului."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlare schimb de date prin Near Field Communication"</string>
@@ -570,18 +577,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Eroare la autentificare"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Folosiți blocarea ecranului"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Introduceți datele de conectare ale dispozitivului pentru a continua"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"S-a detectat parțial amprenta. Încercați din nou."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Amprenta nu a putut fi procesată. Încercați din nou."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Senzorul pentru amprente este murdar. Curățați-l și încercați din nou."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Ați mișcat degetul prea repede. Încercați din nou."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Ați mișcat degetul prea lent. Încercați din nou."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Amprentă autentificată"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Chip autentificat"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Chip autentificat, apăsați Confirmați"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware-ul pentru amprentă nu este disponibil."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Amprenta nu poate fi stocată. Eliminați o amprentă existentă."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Timpul pentru amprentare a expirat. Încercați din nou."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operațiunea privind amprenta a fost anulată."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operațiunea privind amprenta a fost anulată de utilizator."</string>
@@ -606,6 +623,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Deblocare facială"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Reînregistrați-vă chipul"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Pentru a îmbunătăți recunoașterea, reînregistrați-vă chipul"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Nu s-a putut fotografia fața cu precizie. Încercați din nou."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Prea luminos. Încercați o lumină mai slabă."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Prea întunecat. Încercați o lumină mai puternică."</string>
@@ -1009,6 +1034,12 @@
<string name="copied" msgid="4675902854553014676">"Copiat"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a inserat date din <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a inserat date din clipboard"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Mai multe"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Meniu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2144,20 +2175,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Serviciu"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Afișarea conținutului personal"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Afișarea conținutului de lucru"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Nu se poate trimite către aplicații pentru lucru"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Administratorul IT nu vă permite să trimiteți acest conținut către aplicațiile din profilul de serviciu"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Nu se poate deschide cu aplicații pentru lucru"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Administratorul IT nu vă permite să deschideți acest conținut cu aplicațiile din profilul de serviciu"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Nu se poate trimite către aplicații personale"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Administratorul IT nu vă permite să trimiteți acest conținut cu aplicațiile din profilul personal"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Nu se poate deschide cu aplicații personale"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Administratorul IT nu vă permite să deschideți acest conținut cu aplicațiile din profilul personal"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Profilul de serviciu este întrerupt"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Activați"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Aplicațiile pentru lucru nu acceptă acest conținut"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Aplicațiile pentru lucru nu pot deschide acest conținut"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Aplicațiile personale nu acceptă acest conținut"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Aplicațiile personale nu pot deschide acest conținut"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Codul PIN de deblocare SIM privind rețeaua"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Codul PIN de deblocare SIM privind subsetul de rețea"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Codul PIN de deblocare SIM corporativă"</string>
@@ -2270,8 +2312,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Măriți o parte a ecranului"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Acum puteți să măriți tot ecranul sau o anumită zonă ori să comutați între cele două opțiuni."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activați din Setări"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Respingeți"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Pentru a continua, <b><xliff:g id="APP">%s</xliff:g></b> necesită acces la microfonul dispozitivului."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index a980750..58e86a7 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -300,7 +300,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Приложение активно"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, расходующие заряд"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увеличение"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Политика безопасности для специальных возможностей"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" расходует заряд"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Несколько приложений (<xliff:g id="NUMBER">%1$d</xliff:g>) расходуют заряд"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Нажмите, чтобы проверить энергопотребление и трафик"</string>
@@ -325,6 +326,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"доступ к данным о физической активности"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Камера"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"снимать фото и видео"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Устройства Bluetooth поблизости"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"находить устройства Bluetooth поблизости и подключаться к ним"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Список вызовов"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"чтение и запись телефонных звонков"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Телефон"</string>
@@ -538,6 +541,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Приложение сможет просматривать конфигурацию Bluetooth на планшетном ПК, а также запрашивать и подтверждать соединение с другими устройствами."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Приложение сможет просматривать конфигурацию Bluetooth на устройстве Android TV, а также запрашивать и подтверждать соединение с другими устройствами."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Приложение сможет просматривать конфигурацию Bluetooth на телефоне, а также запрашивать и подтверждать соединение с другими устройствами."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"находить устройства Bluetooth поблизости и подключаться к ним"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Приложение сможет находить устройства Bluetooth поблизости и подключаться к ним."</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"доступ к подключенным устройствам Bluetooth"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"У приложения будет доступ к подключенным устройствам Bluetooth."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Сведения о предпочтительном платежном сервисе NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Приложение сможет получать сведения о предпочтительном платежном сервисе NFC (например, зарегистрированные идентификаторы AID и конечный пункт маршрута)."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Управление NFC-модулем"</string>
@@ -573,18 +580,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Ошибка аутентификации."</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Использовать блокировку экрана"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Чтобы продолжить, введите учетные данные устройства."</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Отсканирована только часть отпечатка. Повторите попытку."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Не удалось распознать отпечаток. Повторите попытку."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Очистите сканер и повторите попытку."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Вы слишком быстро убрали палец. Повторите попытку."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Вы перемещали палец слишком медленно. Повторите попытку."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Отпечаток пальца проверен"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лицо распознано"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицо распознано, нажмите кнопку \"Подтвердить\""</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Сканер недоступен"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Чтобы сохранить новый отпечаток, удалите существующий."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Превышено время ожидания. Повторите попытку."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Операция с отпечатком отменена."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Операция с отпечатком пальца отменена пользователем."</string>
@@ -609,6 +626,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Фейсконтроль"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Зарегистрируйте лицо ещё раз"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Чтобы улучшить распознавание лица, зарегистрируйте его ещё раз"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Не удалось собрать данные. Повторите попытку."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Слишком светло. Сделайте освещение менее ярким."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Слишком темно. Сделайте освещение ярче."</string>
@@ -1012,6 +1037,12 @@
<string name="copied" msgid="4675902854553014676">"Скопировано"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Данные из приложения \"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>\" вставлены в приложение \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\"."</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Данные из буфера обмена вставлены в приложение \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\"."</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Ещё"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Меню+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -1207,10 +1238,10 @@
<string name="whichViewApplication" msgid="5733194231473132945">"Открыть с помощью приложения:"</string>
<string name="whichViewApplicationNamed" msgid="415164730629690105">"Открыть с помощью приложения \"%1$s\""</string>
<string name="whichViewApplicationLabel" msgid="7367556735684742409">"Открыть"</string>
- <string name="whichOpenHostLinksWith" msgid="7645631470199397485">"Открывать ссылки вида <xliff:g id="HOST">%1$s</xliff:g> с помощью:"</string>
+ <string name="whichOpenHostLinksWith" msgid="7645631470199397485">"Открывать ссылки <xliff:g id="HOST">%1$s</xliff:g> с помощью:"</string>
<string name="whichOpenLinksWith" msgid="1120936181362907258">"Открывать ссылки с помощью:"</string>
<string name="whichOpenLinksWithApp" msgid="6917864367861910086">"Открывать ссылки в браузере <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
- <string name="whichOpenHostLinksWithApp" msgid="2401668560768463004">"Открывать ссылки вида <xliff:g id="HOST">%1$s</xliff:g> в браузере <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
+ <string name="whichOpenHostLinksWithApp" msgid="2401668560768463004">"Открывать ссылки <xliff:g id="HOST">%1$s</xliff:g> в браузере <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
<string name="whichGiveAccessToApplicationLabel" msgid="7805857277166106236">"Открыть доступ"</string>
<string name="whichEditApplication" msgid="6191568491456092812">"Редактировать с помощью приложения:"</string>
<string name="whichEditApplicationNamed" msgid="8096494987978521514">"Редактировать с помощью приложения \"%1$s\""</string>
@@ -2178,20 +2209,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Рабочее"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Просмотр личных данных"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Просмотр рабочих данных"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Этим контентом нельзя делиться с рабочими приложениями"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Системный администратор запретил делиться этим контентом с приложениями из рабочего профиля."</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Этот контент нельзя открывать в рабочих приложениях"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Системный администратор запретил открывать этот контент, используя приложения из рабочего профиля."</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Этим контентом нельзя делиться с личными приложениями"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Системный администратор запретил делиться этим контентом с приложениями из личного профиля."</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Этот контент нельзя открывать в личных приложениях"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Системный администратор запретил открывать этот контент, используя приложения из личного профиля."</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Действие рабочего профиля приостановлено."</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Включить"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Нет рабочих приложений, поддерживающих этот контент."</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Нет рабочих приложений, с помощью которых можно открыть этот контент."</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Нет личных приложений, поддерживающих этот контент."</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Нет личных приложений, с помощью которых можно открыть этот контент."</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-код для разблокировки сети SIM-карты"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-код для разблокировки подмножества сети SIM-карты"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-код для разблокировки корпоративной SIM-карты"</string>
@@ -2304,8 +2346,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Увеличьте часть экрана"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Теперь вы можете увеличить весь экран или его часть либо переключаться между этими вариантами."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Включить в настройках"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Закрыть"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Чтобы продолжить, предоставьте приложению <b><xliff:g id="APP">%s</xliff:g></b> доступ к микрофону устройства."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index a1e3b4a..97da7bd 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"යෙදුම ධාවනය කරමින්"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"බැටරිය භාවිත කරන යෙදුම්"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"විශාලනය"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"ප්රවේශ්යතා ආරක්ෂක ප්රතිපත්තිය"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> බැටරිය භාවිත කරයි"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"යෙදුම් <xliff:g id="NUMBER">%1$d</xliff:g>ක් බැටරිය භාවිත කරයි"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"බැටරි හා දත්ත භාවිතය පිළිබඳව විස්තර සඳහා තට්ටු කරන්න"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ඔබේ ශාරීරික ක්රියාකාරකමට ප්රවේශ වන්න"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"කැමරාව"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"පින්තූර ගැනීම සහ වීඩියෝ පටිගත කිරීම"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"අවට බ්ලූටූත් උපාංග"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"අවට ඇති බ්ලූටූත් උපාංග සොයා ගන්න සහ සම්බන්ධ වන්න"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"ඇමතුම් ලොග"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"දුරකථන ඇමතුම් ලොගය කියවන්න සහ ලියන්න"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"දුරකථනය"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ටැබ්ලටයේ බ්ලූටූත් වින්යාසය බැලිමට, සැකසීමට සහ යුගල කළ උපාංග සමඟ සම්බන්ධතාවන් පිළිගැනීමට යෙදුමට අවසර දෙන්න."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ඔබගේ Android TV උපාංගයේ බ්ලූටූත් හි වින්යාසකරණය බැලීමට, සහ යුගල කළ උපාංග සමඟ සම්බන්ධතා ඇති කර ගැනීමට සහ පිළිගැනීමට යෙදුමට ඉඩ දෙයි."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"දුරකථනයේ බ්ලූටූත් වින්යාසය දැකීමට, යුගල උපාංග සමඟ සම්බන්ධතාවන් සැකසීමට සහ භාරගැනීමට යෙදුමට අවසර දෙයි."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"අවට ඇති බ්ලූටූත් උපාංග සොයා ගන්න සහ යුගල කරන්න"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"අවට ඇති බ්ලූටූත් උපාංග සොයා ගැනීමට සහ යුගල කිරීමට යෙදුමට ඉඩ දෙයි"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"යුගල කළ බ්ලූටූත් උපාංගවලට සම්බන්ධ වන්න"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"යුගල කළ බ්ලූටූත් උපාංග සමඟ සම්බන්ධ වීමට යෙදුමට ඉඩ දෙයි"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"කැමති NFC ගෙවීම් සේවා තොරතුරු"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ලියාපදිංචි කළ ආධාර සහ ගමන් මාර්ග ගමනාන්ත වැනි කැමති nfc ගෙවීම් සේවා තොරතුරු ලබා ගැනීමට යෙදුමට ඉඩ දෙයි."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ආසන්න ක්ෂේත්ර සන්නිවේදනය පාලනය කරන්න"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"සත්යාපනය කිරීමේ දෝෂයකි"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"තිර අගුල භාවිත කරන්න"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"ඉදිරියට යාමට ඔබගේ උපාංග අක්තපත්ර ඇතුළු කරන්න"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"ඇඟිලි සලකුණ අඩ වශයෙන් අනාවරණය කර ගැනිණි. කරුණාකර නැවත උත්සාහ කරන්න."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ඇඟිලි සලකුණ පිරිසැකසීමට නොහැකි විය. කරුණාකර නැවත උත්සාහ කරන්න."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"ඇඟිලි සලකුණු සංවේදකය අපිරිසිදුයි. කරුණාකර පිරිසිදු කර නැවත උත්සාහ කරන්න."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"ඇඟිල්ල ඉතා වේගයෙන් ගෙන යන ලදී. කරුණාකර නැවත උත්සාහ කරන්න."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ඇඟිල්ල වඩා සෙමෙන් ගෙන යන ලදි. කරුණාකර නැවත උත්සාහ කරන්න."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"ඇඟිලි සලකුණ සත්යාපනය කරන ලදී"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"මුහුණ සත්යාපනය කරන ලදී"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"මුහුණ සත්යාපනය කරන ලදී, කරුණාකර තහවුරු කරන්න ඔබන්න"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ඇඟිලි සලකුණු දෘඪාංගය ලද නොහැකිය."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ඇඟිලි සලකුණ ගබඩා කළ නොහැක. දැනට පවතින ඇඟිලි සලකුණක් ඉවත් කරන්න."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"ඇඟිලි සලකුණු කාල නිමාව ළඟා විය. නැවත උත්සාහ කරන්න."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ඇඟිලි සලකුණු මෙහෙයුම අවලංගු කරන ලදී."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"පරිශීලක විසින් ඇඟිලි සලකුණු මෙහෙයුම අවසන් කරන ලදී."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"මුහුණු අඟුලු ඇරීම"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ඔබේ මුහුණ යළි ලියාපදිංචි කරන්න"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"හඳුනා ගැනීම වැඩිදියුණු කිරීමට, ඔබේ මුහුණ යළි-ලියාපදිංචි කරන්න"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"නිරවද්ය මුහුණු දත්ත ගත නොහැකි විය. නැවත උත්සාහ කරන්න."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"දීප්තිය වැඩියි. තවත් මඳ ආලෝකය උත්සාහ කරන්න."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"ඉතා අඳුරුයි. තවත් දීප්තිමත් ආලෝකය උත්සාහ කරන්න."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"පිටපත් කළා"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> වෙතින් අලවන ලදි"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> පසුරු පුවරුව වෙතින් අලවන ලදි"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"තව"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"මෙනුව+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"කාර්යාල"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"පෞද්ගලික දසුන"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"කාර්යාල දසුන"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"මෙය කාර්යාල යෙදුම් සමග බෙදා ගැනීමට නොහැකිය"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"ඔබේ IT පරිපාලක ඔබට ඔබේ කාර්යාල පැතිකඩේ ඇති යෙදුම්වලින් මෙම අන්තර්ගතය බෙදා ගැනීමට ඉඩ නොදේ"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"මෙය කාර්යාල යෙදුමෙන් විවෘත කළ නොහැකිය"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"ඔබේ IT පරිපාලක ඔබට ඔබේ කාර්යාල පැතිකඩේ ඇති යෙදුම්වලින් මෙම අන්තර්ගතය විවෘත කිරීමට ඉඩ නොදේ"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"මෙය පෞද්ගලික යෙදුම් සමග බෙදා ගැනීමට නොහැකිය"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"ඔබේ IT පරිපාලක ඔබට ඔබේ පෞද්ගලික පැතිකඩේ ඇති යෙදුම්වලින් මෙම අන්තර්ගතය බෙදා ගැනීමට ඉඩ නොදේ"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"මෙය පෞද්ගලික යෙදුම්වලින් විවෘත කළ නොහැකිය"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"ඔබේ IT පරිපාලක ඔබට ඔබේ පෞද්ගලික පැතිකඩේ ඇති යෙදුම්වලින් මෙම අන්තර්ගතය විවෘත කිරීමට ඉඩ නොදේ"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"කාර්යාල පැතිකඩ විරාම කර ඇත"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ක්රියාත්මක කරන්න"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"කාර්යාල යෙදුම් කිසිවකට මෙම අන්තර්ගතයට සහාය දැක්විය නොහැකිය"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"කාර්යාල යෙදුම් කිසිවකට මෙම අන්තර්ගතය විවෘත කළ නොහැකිය"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"පෞද්ගලික යෙදුම් කිසිවකට මෙම අන්තර්ගතයට සහාය දැක්විය නොහැකිය"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"පෞද්ගලික යෙදුම් කිසිවකට මෙම අන්තර්ගතය විවෘත කළ නොහැකිය"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ජාල අගුලු හැරීමේ PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ජාල උප කට්ටල අගුලු හැරීමේ PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM සමාගම් අගුලු හැරීමේ PIN"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"ඔබගේ තිරයේ කොටසක් විශාලනය කරන්න"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"ඔබට දැන් ඔබගේ පූර්ණ තිරය, විශේෂිත ප්රදේශයක් විශාලනය කළ හැකිය, නැතහොත් විකල්ප දෙක අතර මාරු විය හැකිය."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"සැකසීම් තුළ ක්රියාත්මක කරන්න"</string>
<string name="dismiss_action" msgid="1728820550388704784">"ඉවත ලන්න"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"දිගටම කර ගෙන යාමට, <b><xliff:g id="APP">%s</xliff:g></b> හට ඔබගේ උපාංගයෙහි මයික්රෆෝනයට ප්රවේශය අවශ්යයි."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index f22317e..ca71551 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -300,7 +300,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikácia je spustená"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikácie spotrebúvajúce batériu"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zväčšenie"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Pravidlá pre zabezpečenie dostupnosti"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> používa batériu"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikácie (<xliff:g id="NUMBER">%1$d</xliff:g>) používajú batériu"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o batérii a spotrebe dát"</string>
@@ -325,6 +326,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"prístup k vašej fyzickej aktivite"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Fotoaparát"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"fotenie a natáčanie videí"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Zariadenia Bluetooth nablízku"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"objaviť a pripojiť sa k zariadeniam s rozhraním Bluetooth nablízku"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Zoznam hovorov"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"čítať a zapisovať do zoznamu hovorov"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefón"</string>
@@ -538,6 +541,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na tablete. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Umožňuje aplikácii zobraziť konfiguráciu rozhrania Bluetooth v zariadení Android TV, ako aj nadväzovať a prijímať pripojenia so spárovanými zariadeniami."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na telefóne. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"objaviť zariad. Bluetooth nablízku a spárovať sa"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Umožňuje aplikácii objaviť zariadenia s rozhraním Bluetooth nablízku a spárovať sa s nimi"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"pripojiť sa k spárovaným zariadeniam Bluetooth"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Umožňuje aplikácii pripojiť sa k spárovaným zariadeniam s rozhraním Bluetooth"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferované informácie platenej služby NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Umožňuje aplikácii získavať preferované informácie platenej služby NFC, napríklad o registrovanej pomoci a trasách k cieľu."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ovládať technológiu NFC"</string>
@@ -573,18 +580,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Chyba overenia"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Použiť zámku obrazovky"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Ak chcete pokračovať, zadajte prihlasovacie údaje zariadenia"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Podarilo sa rozpoznať iba časť odtlačku prsta. Skúste to znova."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Odtlačok prsta sa nepodarilo spracovať. Skúste to znova."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Očistite senzor odtlačkov prstov a skúste to znova."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Pohli ste prstom príliš rýchlo. Skúste to znova."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Pohli ste prstom príliš pomaly. Skúste to znova."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Odtlačok prsta bol overený"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Tvár bola overená"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Tvár bola overená, stlačte tlačidlo potvrdenia"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardvér na snímanie odtlačku prsta nie je k dispozícii"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Odtlačok prsta nie je možné uložiť. Odstráňte existujúci odtlačok."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Časový limit rozpoznania odtlačku prsta vypršal. Skúste to znova."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Overenie odtlačku prsta zrušil používateľ."</string>
@@ -609,6 +626,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Odomknutie tvárou"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Znova zaregistrujte svoju tvár"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Znova zaregistrujte svoju tvár, aby sa zlepšilo rozpoznávanie"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Nepodarilo sa nasnímať presné údaje o tvári. Skúste to znova."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Príliš veľa svetla. Skúste jemnejšie osvetlenie."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Príliš veľká tma. Skúste lepšie osvetlenie."</string>
@@ -1012,6 +1037,12 @@
<string name="copied" msgid="4675902854553014676">"Skopírované"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Aplikácia <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> prilepila údaje z aplikácie <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Aplikácia <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> prilepila údaje zo schránky"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Viac"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2178,20 +2209,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Práca"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Osobné zobrazenie"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Pracovné zobrazenie"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Nedá sa zdieľať s pracovnými aplikáciami"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Váš správca IT vám zakázal zdieľať tento obsah pomocou aplikácií v pracovnom profile"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Nedá sa otvoriť pomocou pracovných aplikácií"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Váš správca IT vám zakázal otvárať tento obsah pomocou aplikácií v pracovnom profile"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Nedá sa zdieľať pomocou osobných aplikácií"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Váš správca IT vám zakázal zdieľať tento obsah pomocou aplikácií v osobnom profile"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Nedá sa otvoriť pomocou osobných aplikácií"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Váš správca IT vám zakázal otvárať tento obsah pomocou aplikácií v osobnom profile"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Pracovný profil je pozastavený"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Zapnúť"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Tento obsah nepodporujú žiadne pracovné aplikácie"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Tento obsah neotvoria žiadne pracovné aplikácie"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Tento obsah nepodporujú žiadne osobné aplikácie"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Tento obsah neotvoria žiadne osobné aplikácie"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN na odomknutie siete pre SIM kartu"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN na odomknutie podmnožiny siete pre SIM kartu"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN na odomknutie podnikovej SIM karty"</string>
@@ -2304,8 +2346,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Zväčšite časť obrazovky"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Teraz môžete zväčšiť celú obrazovku, jej konkrétnu časť alebo prepínať medzi oboma možnosťami."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Zapnúť v Nastaveniach"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Zavrieť"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Ak chcete pokračovať, <b><xliff:g id="APP">%s</xliff:g></b> požaduje prístup k mikrofónu zariadenia."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 220d802..0da1ec6 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -300,7 +300,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikacija se izvaja"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije, ki porabljajo energijo baterije"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Povečava"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Varnostni pravilnik o funkcijah za ljudi s posebnimi potrebami"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> porablja energijo baterije"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Toliko aplikacij porablja energijo baterije: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dotaknite se za prikaz podrobnosti porabe baterije in prenosa podatkov"</string>
@@ -325,6 +326,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"dostop do vaše telesne dejavnosti"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Fotoaparat"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"fotografiranje in snemanje videoposnetkov"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Naprave Bluetooth v bližini"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"odkrivanje naprav Bluetooth v bližini in povezovanje z njimi"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Dnevniki klicev"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"branje in zapisovanje dnevnika klicev v telefonu"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -538,6 +541,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Aplikaciji omogoča ogled konfiguracije Bluetootha tabličnega računalnika ter vzpostavljanje in sprejemanje povezave s seznanjenimi napravami."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Aplikaciji dovoljuje ogled konfiguracije vmesnika Bluetooth v napravi Android TV ter ustvarjanje in sprejemanje povezav s seznanjenimi napravami."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Aplikaciji omogoča ogled konfiguracije Bluetootha telefona ter ustvarjanje in sprejemanje povezave s seznanjenimi napravami."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"odkrivanje naprav Bluetooth v bližini in seznanjanje z njimi"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Aplikaciji omogoča odkrivanje naprav Bluetooth v bližini in seznanjanje z njimi."</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"povezovanje s seznanjenimi napravami Bluetooth"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Aplikaciji omogoča povezovanje s seznanjenimi napravami Bluetooth."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Podatki o prednostni storitvi za plačevanje prek povezave NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Aplikaciji omogoča pridobivanje podatkov o prednostni storitvi za plačevanje prek povezave NFC, kot so registrirani pripomočki in cilj preusmeritve."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"nadzor nad komunikacijo s tehnologijo bližnjega polja"</string>
@@ -573,18 +580,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Napaka pri preverjanju pristnosti"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Uporaba odklepanja s poverilnico"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Za nadaljevanje vnesite poverilnico za napravo."</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Zaznan delni prstni odtis. Poskusite znova."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Prstnega odtisa ni bilo mogoče obdelati. Poskusite znova."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Tipalo prstnih odtisov je umazano. Očistite ga in poskusite znova."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Prehiter premik prsta. Poskusite znova."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Prepočasen premik prsta. Poskusite znova."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Pristnost prstnega odtisa je preverjena"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Pristnost obraza je potrjena"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Pristnost obraza je preverjena. Pritisnite gumb »Potrdi«."</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Strojna oprema za prstne odtise ni na voljo."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Prstnega odtisa ni mogoče shraniti. Odstranite obstoječi prstni odtis."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Dosežena časovna omejitev za prstni odtis. Poskusite znova."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Dejanje s prstnim odtisom je bilo preklicano."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Dejanje s prstnim odtisom je preklical uporabnik."</string>
@@ -609,6 +626,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Odklepanje z obrazom"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Znova registrirajte obraz"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Za izboljšanje prepoznavanja znova registrirajte svoj obraz"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Točnih podatkov o obrazu ni bilo mogoče zajeti. Poskusite znova."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Presvetlo. Poskusite z blažjo osvetlitvijo."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Pretemno. Poskusite z močnejšo osvetlitvijo."</string>
@@ -1012,6 +1037,12 @@
<string name="copied" msgid="4675902854553014676">"Kopirano"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je prilepila iz aplikacije <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>."</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je prilepila iz odložišča."</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Več"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Meni+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -2178,20 +2209,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Služba"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Pogled osebnega profila"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Pogled delovnega profila"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Tega ne smete deliti z delovnimi aplikacijami"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Skrbnik za IT vam ne dovoli deljenja te vsebine z aplikacijami v delovnem profilu"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Tega ne smete odpreti z delovnimi aplikacijami"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Skrbnik za IT vam ne dovoli odpiranja te vsebine z aplikacijami v delovnem profilu"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Tega ne smete deliti z osebnimi aplikacijami"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Skrbnik za IT vam ne dovoli deljenja te vsebine z aplikacijami v osebnem profilu"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Tega ne smete odpreti z osebnimi aplikacijami"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Skrbnik za IT vam ne dovoli odpiranja te vsebine z aplikacijami v osebnem profilu"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Delovni profil je začasno zaustavljen"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Vklop"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Nobena delovna aplikacija ne podpira te vsebine"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Nobena delovna aplikacija ne more odpreti te vsebine"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Nobena osebna aplikacija ne podpira te vsebine"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Nobena osebna aplikacija ne more odpreti te vsebine"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Koda PIN za odklepanje omrežja kartice SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Koda PIN za odklepanje podnabora omrežja kartice SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Koda PIN za odklepanje kartice SIM za podjetje"</string>
@@ -2304,8 +2346,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Povečanje dela zaslona"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Zdaj lahko povečate celoten zaslon, določen del zaslona ali preklapljate med obema možnostma."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Vklopite v nastavitvah"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Opusti"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Za nadaljevanje potrebuje aplikacija <b><xliff:g id="APP">%s</xliff:g></b> dostop do mikrofona v napravi."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index c2c1bb4..07be4ee 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikacioni është në ekzekutim"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacionet që konsumojnë baterinë"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zmadhimi"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Politika e sigurisë e qasshmërisë"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> po përdor baterinë"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikacione po përdorin baterinë"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trokit për detaje mbi baterinë dhe përdorimin e të dhënave"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"qasje në aktivitetin tënd fizik"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"bëj fotografi dhe regjistro video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Pajisjet me Bluetooth në afërsi"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"të zbulojë dhe të lidhet me pajisjet me Bluetooth në afërsi"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Evidencat e telefonatave"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"lexo dhe shkruaj evidencën e telefonatave"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefoni"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Lejon aplikacionin të shikojë konfigurimin e \"bluetooth-it\" në tablet, të kryejë dhe të pranojë lidhje me pajisjet e çiftuara."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Lejon aplikacionin të shikojë konfigurimin e Bluetooth-it në pajisjen tënde Android TV dhe të kryejë dhe të pranojë lidhje me pajisjet e çiftuara."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Lejon aplikacionin të shohë konfigurimin e \"bluetooth-it\" në telefon dhe të kryejë e pranojë lidhje me pajisjet e çiftuara."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"të zbulojë dhe të çiftohet me pajisjet me Bluetooth në afërsi"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Lejon që aplikacioni të zbulojë dhe të çiftohet me pajisjet me Bluetooth në afërsi"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"të lidhet me pajisjet e çiftuara me Bluetooth"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Lejon që aplikacioni të lidhet me pajisjet e çiftuara me Bluetooth"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informacionet për shërbimin e preferuar të pagesës me NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Lejon aplikacionin të marrë informacione për shërbimin e preferuar të pagesës me NFC si p.sh. ndihmat e regjistruara dhe destinacionin e itinerarit."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrollo \"Komunikimin e fushës në afërsi\" NFC"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Gabim gjatë vërtetimit"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Përdor kyçjen e ekranit"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Fut kredencialet e pajisjes për të vazhduar"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"U zbulua një gjurmë gishti e pjesshme. Provo përsëri."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Gjurma e gishtit nuk mund të përpunohej. Provo përsëri."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Sensori i gjurmës së gishtit nuk është i pastër. Pastroje dhe provo përsëri."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Gishti lëvizi shumë shpejt. Provo përsëri."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Gishti lëvizi shumë ngadalë. Provo përsëri."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Gjurma e gishtit u vërtetua"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Fytyra u vërtetua"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Fytyra u vërtetua, shtyp \"Konfirmo\""</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardueri i gjurmës së gishtit nuk mundësohet."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Gjurma e gishtit nuk mund të ruhet. Hiq një gjurmë gishti ekzistuese."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Koha e veprimit për gjurmën e gishtit skadoi. Provo përsëri."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operacioni i gjurmës së gishtit u anulua."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Veprimi i gjurmës së gishtit u anulua nga përdoruesi."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Shkyçja me fytyrë"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Regjistro përsëri fytyrën tënde"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Për të përmirësuar njohjen, regjistro përsëri fytyrën tënde"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"S\'mund të regjistroheshin të dhëna të sakta të fytyrës. Provo përsëri."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Me shumë ndriçim. Provo një ndriçim më të butë."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Shumë i errët. Provo një ndriçim më të fortë."</string>
@@ -702,7 +727,7 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Lejon aplikacionin të lexojë dhe shkruajë konfigurimin e \"Mos shqetëso\"."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"nis përdorimin e lejes për shikimin"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Lejon që mbajtësi të nisë përdorimin e lejeve për një aplikacion. Nuk duhet të nevojitet asnjëherë për aplikacionet normale."</string>
- <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"qasu te të dhënat e sensorit me një shpejtësi më të lartë shembulli"</string>
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"qasu te të dhënat e sensorit me një shpejtësi kampionimi më të lartë"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Lejon aplikacionin të mbledhë shembujt e të dhënave të sensorit me shpejtësi më të lartë se 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Cakto rregullat e fjalëkalimit"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrollo gjatësinë dhe karakteret e lejuara në fjalëkalimet dhe kodet PIN të kyçjes së ekranit."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"U kopjua"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> u ngjit nga <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> u ngjit nga kujtesa e fragmenteve"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Më shumë"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menyja+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,7 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Përdor shkurtoren"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Kthimi i ngjyrës"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Korrigjimi i ngjyrës"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Tejet i errët"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Shumë më i zbehtë"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tastet e volumit të mbajtura shtypur. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> i aktivizuar."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tastet e volumit të mbajtura shtypur. U çaktivizua \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Shtyp dhe mbaj shtypur të dy butonat e volumit për tre sekonda për të përdorur <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Puna"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Pamja personale"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Pamja e punës"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Nuk mund ta ndash këtë me aplikacionet e punës"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Administratori yt i teknologjisë së informacionit nuk të lejon ta ndash këtë përmbajtje me aplikacionet në profilin tënd të punës"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Nuk mund ta hapësh këtë me aplikacionet e punës"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Administratori yt i teknologjisë së informacionit nuk të lejon ta hapësh këtë përmbajtje me aplikacionet në profilin tënd të punës"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Nuk mund ta ndash këtë me aplikacionet personale"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Administratori yt i teknologjisë së informacionit nuk të lejon ta ndash këtë përmbajtje me aplikacionet në profilin tënd personal"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Nuk mund ta hapësh këtë me aplikacionet personale"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Administratori yt i teknologjisë së informacionit nuk të lejon ta hapësh këtë përmbajtje me aplikacionet në profilin tënd personal"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Profili i punës është në pauzë"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Aktivizo"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Asnjë aplikacion pune nuk mund ta mbështesë këtë përmbajtje"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Asnjë aplikacion pune nuk mund ta hapë këtë përmbajtje"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Asnjë aplikacion personal nuk mund ta mbështesë këtë përmbajtje"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Asnjë aplikacion personal nuk mund ta hapë këtë përmbajtje"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Kodi PIN i shkyçjes së rrjetit të kartës SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Kodi PIN i shkyçjes së nënrenditjes së rrjetit të kartës SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Kodi PIN i shkyçjes së kartës SIM të korporatës"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Zmadho pjesën e ekranit tënd"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Tani mund të zmadhosh ekranin tënd të plotë, një zonë specifike ose kalo mes dy opsioneve."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivizo te \"Cilësimet\""</string>
<string name="dismiss_action" msgid="1728820550388704784">"Hiq"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Për të vazhduar, <b><xliff:g id="APP">%s</xliff:g></b> ka nevojë të qaset në mikrofonin e pajisjes sate."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 922c95ba..27ffe44 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -297,7 +297,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Активна апликација"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликације које троше батерију"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увећање"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Безбедносне смернице за приступачност"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерију"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Апликације (<xliff:g id="NUMBER">%1$d</xliff:g>) користе батерију"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Додирните за детаље о батерији и потрошњи података"</string>
@@ -322,6 +323,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"приступ физичким активностима"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Камера"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"снима слике и видео"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Bluetooth уређаји у близини"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"откривање и повезивање са Bluetooth уређајима у близини"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Евиденције позива"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"читање и писање евиденције позива на телефону"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Телефон"</string>
@@ -535,6 +538,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Дозвољава апликацији да прегледа конфигурацију Bluetooth-а на таблету, као и да успоставља и прихвата везе са упареним уређајима."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Дозвољава апликацији да прегледа конфигурацију Bluetooth-а на Android TV уређају и да успоставља и прихвата везе са упареним уређајима."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Дозвољава апликацији да прегледа конфигурацију Bluetooth-а на телефону, као и да успоставља и прихвата везе са упареним уређајима."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"откривање и упаривање са оближњим Bluetooth уређ."</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Дозвољава апликацији да открива Bluetooth уређаје у близини и упарује се са њима"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"повезивање са упареним Bluetooth уређајима"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Дозвољава апликацији да се повезује са упареним Bluetooth уређајима"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Информације о жељеној NFC услузи за плаћање"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дозвољава апликацији да преузима информације о жељеној NFC услузи за плаћање, попут регистрованих идентификатора апликација и одредишта преусмеравања."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"контрола комуникације у ужем пољу (Near Field Communication)"</string>
@@ -570,18 +577,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Грешка при потврди идентитета"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Користите закључавање екрана"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Унесите акредитив за уређај да бисте наставили"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Откривен је делимични отисак прста. Пробајте поново."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Није успела обрада отиска прста. Пробајте поново."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Сензор за отиске прстију је прљав. Очистите га и покушајте поново."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Пребрзо сте померили прст. Пробајте поново."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Превише споро сте померили прст. Пробајте поново."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Отисак прста је потврђен"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лице је потврђено"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лице је потврђено. Притисните Потврди"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Хардвер за отиске прстију није доступан."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Није могуће сачувати отисак прста. Уклоните неки од постојећих отисака прстију."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Временско ограничење за отисак прста је истекло. Пробајте поново."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Радња са отиском прста је отказана."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Корисник је отказао радњу са отиском прста."</string>
@@ -606,6 +623,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Откључавање лицем"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Поново региструјте лице"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Да бисте побољшали препознавање, поново региструјте лице"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Снимање лица није успело. Пробајте поново."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Превише је светло. Пробајте са слабијим осветљењем."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Претамно је. Пробајте са јачим осветљењем."</string>
@@ -1009,6 +1034,12 @@
<string name="copied" msgid="4675902854553014676">"Копирано је"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Апликација<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> је налепила податке из апликације <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Апликација<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> налепила податке из привремене меморије"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Још"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Мени+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2144,20 +2175,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Пословно"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Лични приказ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Приказ за посао"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Не можете да делите овај садржај помоћу апликација за посао"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"ИТ администратор вам не дозвољава да делите овај садржај помоћу апликација на пословном профилу"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Не можете да отворите овај садржај помоћу апликација за посао"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"ИТ администратор вам не дозвољава да отворите овај садржај помоћу апликација на пословном профилу"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Не можете да делите овај садржај помоћу личних апликација"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"ИТ администратор вам не дозвољава да делите овај садржај помоћу апликација на личном профилу"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Не можете да отворите овај садржај помоћу личних апликација"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"ИТ администратор вам не дозвољава да отворите овај садржај помоћу апликација на личном профилу"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Пословни профил је паузиран"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Укључи"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Ниједна апликација за посао не подржава овај садржај"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Ниједна апликација за посао не може да отвори овај садржај"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Ниједна лична апликација не може да подржава овај садржај"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Ниједна лична апликација не може да отвори овај садржај"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN за откључавање SIM мреже"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN за откључавање подскупа SIM мреже"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN за откључавање пословне SIM картице"</string>
@@ -2270,8 +2312,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Увећајте приказ дела екрана"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Сада можете да увећате цео екран, одређену област или да прелазите са једне опције на другу."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Укључите у Подешавањима"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Одбаци"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"<b><xliff:g id="APP">%s</xliff:g></b> захтева приступ микрофону уређаја ради настављања."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index cf44ee0..ed5b746 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App körs"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Appar som drar batteri"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Förstoring"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Säkerhetspolicy för tillgänglighet"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> drar batteri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> appar drar batteri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryck för information om batteri- och dataanvändning"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"åtkomst till data om fysisk aktivitet"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ta bilder och spela in video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Bluetooth-enheter i närheten"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"hitta och ansluta till Bluetooth-enheter i närheten"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Samtalsloggar"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"läsa och skriva samtalslogg"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tillåter att appen kommer åt pekdatorns Bluetooth-konfiguration och upprättar och godkänner anslutningar till parkopplade enheter."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Tillåter att appen läser Android TV-enhetens Bluetooth-konfiguration och upprättar och godkänner anslutningar till parkopplade enheter."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Tillåter att appen kommer åt mobilens Bluetooth-konfiguration och upprättar och godkänner anslutningar till parkopplade enheter."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"hitta och parkoppla Bluetooth-enheter i närheten"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Tillåter appen att hitta och parkoppla Bluetooth-enheter i närheten"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"ansluta till parkopplade Bluetooth-enheter"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Tillåter appen att ansluta till parkopplade Bluetooth-enheter"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Information kopplad till standardtjänsten för NFC-betalning"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Tillåter att appen hämtar information kopplad till standardtjänsten för NFC-betalning, till exempel registrerade hjälpmedel och ruttdestinationer."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrollera närfältskommunikationen"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Ett fel uppstod vid autentiseringen"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Använd skärmlåset"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Fortsätt genom att ange enhetens autentiseringsuppgifter"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Ofullständigt fingeravtryck. Försök igen."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Det gick inte att bearbeta fingeravtrycket. Försök igen."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Fingeravtryckssensorn är smutsig. Rengör den och försök igen."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Du rörde fingret för snabbt. Försök igen."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Du rörde fingret för långsamt. Försök igen."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingeravtrycket har autentiserats"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ansiktet har autentiserats"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansiktet har autentiserats. Tryck på Bekräfta"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Det finns ingen maskinvara för fingeravtryck."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Fingeravtrycket kan inte lagras. Ta bort ett befintligt fingeravtryck."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Tidsgränsen för fingeravtrycket har uppnåtts. Försök igen."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingeravtrycksåtgärden avbröts."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingeravtrycksåtgärden avbröts av användaren."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Ansiktslås"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Registrera ansiktet på nytt"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Gör om registreringen av ansiktet så att ansiktsigenkänningen ska fungera bättre"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Det gick inte att fånga ansiktsdata. Försök igen."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Det är för ljust. Testa lägre belysning."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Det är för mörkt. Testa med bättre belysning."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Kopierat"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> klistrade in från <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> klistrade in från urklipp"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Mer"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta + "</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Jobb"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personlig vy"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Jobbvy"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Det går inte att dela detta med jobbappar"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT-administratören tillåter inte att du delar innehållet med appar i din jobbprofil"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Det går inte att öppna detta med jobbappar"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT-administratören tillåter inte att du öppnar innehållet med appar i din jobbprofil"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Det går inte att dela detta med privata appar"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT-administratören tillåter inte att du delar innehållet med appar i din privata profil"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Det går inte att öppna detta med privata appar"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT-administratören tillåter inte att du öppnar innehållet med appar i din privata profil"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Jobbprofilen är pausad"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Aktivera"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Inga jobbappar har stöd för det här innehållet"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Det går inte att öppna innehållet med några jobbappar"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Inga privata appar har stöd för det här innehållet"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Det går inte att öppna innehållet med några privata appar"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Pinkod för upplåsning av nätverk för SIM-kort"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Pinkod för upplåsning av delnätverk för SIM-kort"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Pinkod för upplåsning av företag för SIM-kort"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Förstora en del av skärmen"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Nu kan du förstora hela skärmen, ett visst område eller växla mellan båda alternativen."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivera i inställningarna"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Stäng"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"<b><xliff:g id="APP">%s</xliff:g></b> behöver behörighet till enhetens mikrofon för att fortsätta."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index f715948..21998ed 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Programu inaendelea kutekelezwa"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programu zinazotumia betri"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ukuzaji"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Sera ya usalama wa ufikivu"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumia betri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programu <xliff:g id="NUMBER">%1$d</xliff:g> zinatumia betri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Gusa ili upate maelezo kuhusu betri na matumizi ya data"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ifikie shughuli zako za kimwili"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ipige picha na kurekodi video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Vifaa vyenye Bluetooth Vilivyo Karibu"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"kutambua na kuunganisha kwenye vifaa vyenye Bluetooth vilivyo karibu"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Rekodi ya nambari za simu"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"kusoma na kuandika rekodi ya nambari za simu"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Simu"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Huruhusu programu kuona usanidi wa Bluetooth kwenye kompyuta kibao, na kutuma na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Huruhusu programu iangalie mipangilio iliyowekwa ya Bluetooth kwenye kifaa chako cha Android TV na kufanya na kukubali miunganisho na vifaa vilivyooanishwa."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Huruhusu programu kuona usanidi wa Bluetooth kwenye simu, na kutuma na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"kutambua na kuoanisha vifaa vyenye Bluetooth vilivyo karibu"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Huruhusu programu itambue na kuoanisha kwenye vifaa vyenye Bluetooth vilivyo karibu"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"kuunganisha kwenye vifaa vyenye Bluetooth vilivyooanishwa"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Huruhusu programu iunganishe kwenye vifaa vyenye Bluetooth vilivyooanishwa"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Maelezo ya Huduma Inayopendelewa ya Malipo ya NFC"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Huruhusu programu kupata maelezo ya huduma inayopendelewa ya malipo ya nfc kama vile huduma zilizosajiliwa na njia."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kudhibiti Mawasiliano ya Vifaa Vilivyokaribu (NFC)"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Hitilafu imetokea wakati wa uthibitishaji"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Tumia mbinu ya kufunga skrini"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Weka kitambulisho cha kifaa chako ili uendelee."</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Kitambua alama kimetambua sehemu ya alama. Tafadhali jaribu tena."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Imeshindwa kuchakata alama ya kidole. Tafadhali jaribu tena."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Kitambua alama ya kidole ni kichafu. Tafadhali kisafishe na ujaribu tena."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Ulisogeza kidole kwa kasi mno. Tafadhali jaribu tena."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Kidole kilisogezwa polepole zaidi. Tafadhali jaribu tena."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Imethibitisha alama ya kidole"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Uso umethibitishwa"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Uso umethibitishwa, tafadhali bonyeza thibitisha"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Maunzi ya alama ya kidole hayapatikani."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Alama ya kidole haiwezi kuhifadhiwa. Tafadhali ondoa alama ya kidole iliyopo."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Muda wa kuweka alama ya kidole umekwisha. Jaribu tena."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Mchakato wa alama ya kidole umeghairiwa."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Mtumiaji ameghairi uthibitishaji wa alama ya kidole."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Kufungua kwa uso"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Sajili uso wako tena"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Ili kuimarisha utambuzi, tafadhali sajili uso wako tena"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Imeshindwa kunasa data sahihi ya uso. Jaribu tena."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Inang\'aa mno. Jaribu mwangaza hafifu"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Hakuna mwangaza wa kutosha. Jaribu kuongeza mwangaza."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Umenakili"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> imebandika kutoka <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> imebandika kutoka ubao wa kunakili"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Zaidi"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menyu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Kazini"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Mwonekano wa binafsi"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Mwonekano wa kazini"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Huwezi kushiriki maudhui haya na programu za kazini"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Msimamizi wako wa TEHAMA hakuruhusu ushiriki maudhui haya ukitumia programu zilizo kwenye wasifu wako wa kazini"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Huwezi kufungua maudhui haya ukitumia programu za kazini"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Msimamizi wako wa TEHAMA hakuruhusu ufungue maudhui haya ukitumia programu zilizo kwenye wasifu wako wa kazini"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Huwezi kushiriki maudhui haya na programu za binafsi"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Msimamizi wako wa TEHAMA hakuruhusu ushiriki maudhui haya ukitumia programu zilizo kwenye wasifu wako wa binafsi"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Huwezi kufungua maudhui haya ukitumia programu za binafsi"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Msimamizi wako wa TEHAMA hakuruhusu ufungue maudhui haya ukitumia programu zilizo kwenye wasifu wako wa binafsi"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Wasifu wa kazini umesimamishwa"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Washa"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Hakuna programu za kazini zinazoweza kutumia maudhui haya"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Hakuna programu za kazini zinazoweza kufungua maudhui haya"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Hakuna programu za binafsi zinazoweza kutumia maudhui haya"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Hakuna programu za binafsi zinazoweza kufungua maudhui haya"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN ya kufungua mtandao wa SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN ya kufungua SIM iliyofungwa na mtoa huduma za simu"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN ya kufungua SIM ya shirika"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Kuza sehemu ya skrini yako"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Sasa unaweza kukuza skrini yako nzima, sehemu mahususi au ubadilishe kati ya chaguo zote mbili."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Washa katika Mipangilio"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Ondoa"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Ili uendelee, <b><xliff:g id="APP">%s</xliff:g></b> inahitaji ruhusa ya kufikia maikrofoni ya kifaa chako."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 0a5aca5..c27d495 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ஆப்ஸ் இயங்குகிறது"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"பேட்டரியைப் பயன்படுத்தும் ஆப்ஸ்"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"பெரிதாக்கல்"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"அணுகல்தன்மை பாதுகாப்புக் கொள்கை"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகிறது"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகின்றன"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"பேட்டரி மற்றும் டேட்டா உபயோக விவரங்களைக் காண, தட்டவும்"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"உடல் செயல்பாட்டைக் கண்காணிக்கும்"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"கேமரா"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"படங்கள் மற்றும் வீடியோக்கள் எடுக்கலாம்"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"அருகிலுள்ள புளூடூத் சாதனங்கள்"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"அருகிலுள்ள புளூடூத் சாதனங்களைக் கண்டறிந்து அவற்றுடன் இணையும்"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"அழைப்புப் பதிவுகள்"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"மொபைல் அழைப்புப் பதிவைப் படிக்கும், எழுதும்"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ஃபோன்"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"டேப்லெட்டில் புளூடூத் இன் உள்ளமைவைப் பார்க்க மற்றும் இணைந்த சாதனங்களுடன் இணைப்புகளை ஏற்படுத்த மற்றும் ஏற்க ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TVயில் புளூடூத்தின் உள்ளமைவைப் பார்க்கவும் இணைக்கப்பட்ட சாதனங்களுடன் இணைப்புகளை உருவாக்கவும் ஏற்கவும் ஆப்ஸை அனுமதிக்கும்."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"மொபைலில் புளூடூத் இன் உள்ளமைவைப் பார்க்க மற்றும் இணைந்த சாதனங்களுடன் இணைப்புகளை ஏற்படுத்த மற்றும் ஏற்க ஆப்ஸை அனுமதிக்கிறது."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"அருகிலுள்ள புளூடூத் சாதனங்களை கண்டறிந்து இணைத்தல்"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"அருகிலுள்ள புளூடூத் சாதனங்களைக் கண்டறிந்து அவற்றுடன் இணைவதற்கு ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"இணைக்கப்பட்ட புளூடூத் சாதனங்களுடன் இணைத்தல்"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"இணைக்கப்பட்ட புளூடூத் சாதனங்களுடன் இணைவதற்கு ஆப்ஸை அனுமதிக்கும்"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"விருப்பமான NFC பேமெண்ட் சேவை தொடர்பான தகவல்கள்"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"பதிவுசெய்யப்பட்ட கருவிகள், சேருமிடத்திற்கான வழி போன்ற விருப்பமான NFC பேமெண்ட் சேவை தொடர்பான தகவல்களைப் பெற ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"குறுகிய இடைவெளி தகவல்பரிமாற்றத்தைக் கட்டுப்படுத்துதல்"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"அங்கீகரிப்பதில் பிழை"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"திரைப் பூட்டைப் பயன்படுத்து"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"தொடர, சாதன அனுமதிச் சான்றை உள்ளிடுங்கள்"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"கைரேகையை ஓரளவுதான் கண்டறிய முடிந்தது. மீண்டும் முயலவும்."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"கைரேகையைச் செயலாக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"கைரேகை சென்சாரில் தூசி உள்ளது. சுத்தம் செய்து, முயலவும்."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"விரலை வேகமாக எடுத்துவிட்டீர்கள். மீண்டும் முயற்சிக்கவும்."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"விரலை மிகவும் மெதுவாக நகர்த்திவிட்டீர்கள். மீண்டும் முயற்சிக்கவும்."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"கைரேகை அங்கீகரிக்கப்பட்டது"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"முகம் அங்கீகரிக்கப்பட்டது"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"முகம் அங்கீகரிக்கப்பட்டது. ’உறுதிப்படுத்துக’ என்பதை அழுத்துக"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"கைரேகை வன்பொருள் இல்லை."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"கைரேகையைச் சேமிக்க முடியவில்லை. ஏற்கனவே உள்ள கைரேகையை அகற்றவும்."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"கைரேகைக்கான நேரம் முடிந்தது. மீண்டும் முயலவும்."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"கைரேகை செயல்பாடு ரத்துசெய்யப்பட்டது."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"பயனர், கைரேகை உறுதிப்படுத்துதலை ரத்துசெய்தார்."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"முகம் காட்டித் திறத்தல்"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"முகத்தை மீண்டும் பதிவுசெய்யவும்"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"அடையாளத்தை மேம்படுத்த முகத்தை மீண்டும் பதிவுசெய்யவும்"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"முகம் தெளிவாகப் பதிவாகவில்லை. மீண்டும் முயலவும்."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"அதிக ஒளிர்வு. மிதமான ஒளியில் முயலவும்."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"இருட்டாக உள்ளது. பிரகாசமான ஒளியில் முயலவும்."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"நகலெடுக்கப்பட்டது"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> ஆப்ஸிலிருந்து <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ஒட்டப்பட்டது"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"கிளிப்போர்டிலிருந்து <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ஒட்டப்பட்டது"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"மேலும்"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"மெனு+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"மெட்டா மற்றும்"</string>
@@ -2055,7 +2086,7 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"வழக்கமான பேட்டரி சேமிப்பானுக்கான விவர அறிவிப்பு"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"வழக்கமாகச் சார்ஜ் செய்வதற்கு முன்பே பேட்டரி தீர்ந்துபோகக்கூடும்"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"பேட்டரி நிலையை நீட்டிக்க பேட்டரி சேமிப்பான் இயக்கப்பட்டுள்ளது"</string>
- <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"பேட்டரி சேமிப்பான்"</string>
+ <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"பேட்டரி சேமிப்பு"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"பேட்டரி சேமிப்பான் ஆஃப் செய்யப்பட்டுள்ளது"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"மொபைலில் போதுமான சார்ஜ் உள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string>
<string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"டேப்லெட்டில் போதுமான சார்ஜ் உள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"பணிச் சுயவிவரம்"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"தனிப்பட்ட காட்சி"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"பணிக் காட்சி"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"பணி ஆப்ஸுடன் இதைப் பகிர முடியாது"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"உங்கள் பணிக் கணக்கில் உள்ள ஆப்ஸில் இந்த உள்ளடக்கத்தைப் பகிர்வதை உங்கள் IT நிர்வாகி அனுமதிக்கவில்லை"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"பணி ஆப்ஸில் இதைத் திறக்க முடியவில்லை"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"உங்கள் பணிக் கணக்கில் உள்ள ஆப்ஸில் இந்த உள்ளடக்கத்தைத் திறப்பதை உங்கள் IT நிர்வாகி அனுமதிக்கவில்லை"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"தனிப்பட்ட ஆப்ஸுடன் இதைப் பகிர முடியாது"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"உங்கள் தனிப்பட்ட கணக்கில் உள்ள ஆப்ஸில் இந்த உள்ளடக்கத்தைப் பகிர்வதை உங்கள் IT நிர்வாகி அனுமதிக்கவில்லை"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"தனிப்பட்ட ஆப்ஸில் இதைத் திறக்க முடியவில்லை"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"உங்கள் தனிப்பட்ட கணக்கில் உள்ள ஆப்ஸில் இந்த உள்ளடக்கத்தைத் திறப்பதை உங்கள் IT நிர்வாகி அனுமதிக்கவில்லை"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"பணிக் கணக்கு இடைநிறுத்தப்பட்டுள்ளது"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"இயக்கு"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"இந்த உள்ளடக்கத்தை எந்தவொரு பணி ஆப்ஸும் ஆதரிக்காது"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"இந்த உள்ளடக்கத்தை எந்தவொரு பணி ஆப்ஸாலும் திறக்க முடியாது"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"இந்த உள்ளடக்கத்தை எந்தவொரு தனிப்பட்ட ஆப்ஸும் ஆதரிக்காது"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"இந்த உள்ளடக்கத்தை எந்தவொரு தனிப்பட்ட ஆப்ஸாலும் திறக்க முடியாது"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"சிம் நெட்வொர்க் அன்லாக் பின்"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"சிம் நெட்வொர்க் சப்செட் அன்லாக் பின்"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"கார்ப்பரேட் அன்லாக் பின்"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"திரையின் ஒரு பகுதியைப் பெரிதாக்குதல்"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"முழுத்திரையையோ குறிப்பிட்ட பகுதியையோ இப்போது பெரிதாக்கலாம் அல்லது இந்த இரு விருப்பங்களுக்கிடையே மாறலாம்."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"அமைப்புகளில் ஆன் செய்க"</string>
<string name="dismiss_action" msgid="1728820550388704784">"மூடுக"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"தொடர, உங்கள் சாதனத்தின் மைக்ரோஃபோனை அணுகுவதற்கு <b><xliff:g id="APP">%s</xliff:g></b> ஆப்ஸுக்கு அனுமதி வேண்டும்."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index a354380..e1d4cfb 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"యాప్ అమలవుతోంది"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"బ్యాటరీని ఉపయోగిస్తున్న యాప్లు"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"మాగ్నిఫికేషన్"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"యాక్సెసిబిలిటీ సెక్యూరిటీ పాలసీ"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> బ్యాటరీని ఉపయోగిస్తోంది"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> యాప్లు బ్యాటరీని ఉపయోగిస్తున్నాయి"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"బ్యాటరీ మరియు డేటా వినియోగ వివరాల కోసం నొక్కండి"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"భౌతిక కార్యకలాపాన్ని యాక్సెస్ చేయండి"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"కెమెరా"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"చిత్రాలను తీయడానికి మరియు వీడియోను రికార్డ్ చేయడానికి"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"సమీపంలోని బ్లూటూత్ పరికరాలు"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"సమీపంలోని బ్లూటూత్ పరికరాలను కనుగొని, కనెక్ట్ చేయండి"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"కాల్ లాగ్లు"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ఫోన్ కాల్ లాగ్ని చదవండి మరియు రాయండి"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ఫోన్"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"టాబ్లెట్లో బ్లూటూత్ యొక్క కాన్ఫిగరేషన్ను వీక్షించడానికి మరియు జత చేయబడిన పరికరాలతో కనెక్షన్లను ఏర్పాటు చేయడానికి మరియు ఆమోదించడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"మీ Android TV పరికరం బ్లూటూత్ యొక్క కాన్ఫిగరేషన్ను చూడడానికి, జత చేయబడిన పరికరాలతో కనెక్షన్లను ఏర్పాటు చేయడానికి మరియు ఆమోదించడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ఫోన్లో బ్లూటూత్ యొక్క కాన్ఫిగరేషన్ను వీక్షించడానికి మరియు జత చేయబడిన పరికరాలతో కనెక్షన్లను ఏర్పాటు చేయడానికి మరియు ఆమోదించడానికి యాప్ను అనుమతిస్తుంది."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"సమీపంలోని బ్లూటూత్ పరికరాలను కనుగొని పెయిర్ చేయండి"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"సమీపంలోని బ్లూటూత్ పరికరాలను కనుగొనడానికి, పెయిర్ చేయడానికి యాప్ను అనుమతిస్తుంది"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"పెయిర్ చేసిన బ్లూటూత్ పరికరాలకు కనెక్ట్ అవ్వండి"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"పెయిర్ చేసిన బ్లూటూత్ పరికరాలకు కనెక్ట్ అవ్వడానికి యాప్ను అనుమతిస్తుంది"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ప్రాధాన్యత ఇవ్వబడిన NFC చెల్లింపు సేవల సమాచారం"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ప్రాధాన్యత ఇవ్వబడిన NFC చెల్లింపు సేవల సమాచారాన్ని, అంటే రిజిస్టర్ చేయబడిన సహాయక సాధనాలు, మార్గం, గమ్యస్థానం వంటి వాటిని పొందేందుకు యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"సమీప క్షేత్ర కమ్యూనికేషన్ను నియంత్రించడం"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"ప్రామాణీకరిస్తున్నప్పుడు ఎర్రర్ ఏర్పడింది"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"స్క్రీన్ లాక్ను ఉపయోగించండి"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"కొనసాగడానికి, మీ పరికర ఆధారాలను ఎంటర్ చేయండి"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"పాక్షిక వేలిముద్ర గుర్తించబడింది. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"వేలిముద్రను ప్రాసెస్ చేయడం సాధ్యపడలేదు. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"వేలిముద్ర సెన్సార్ మురికిగా ఉంది. దయచేసి శుభ్రపరిచి, మళ్లీ ప్రయత్నించండి."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"వేలిని చాలా వేగంగా తీసేసారు. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"వేలిని చాలా నెమ్మదిగా కదిలించారు. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"వేలిముద్ర ప్రమాణీకరించబడింది"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ముఖం ప్రమాణీకరించబడింది"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ముఖం ప్రమాణీకరించబడింది, దయచేసి ధృవీకరించును నొక్కండి"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"వేలిముద్ర హార్డ్వేర్ అందుబాటులో లేదు."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"వేలిముద్రను నిల్వ చేయడం సాధ్యపడదు. దయచేసి ఇప్పటికే ఉన్న వేలిముద్రను తీసివేయండి."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"వేలిముద్ర గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"వేలిముద్ర కార్యకలాపం రద్దయింది."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"వేలిముద్ర చర్యని వినియోగదారు రద్దు చేసారు."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ఫేస్ అన్లాక్"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"మీ ముఖాన్ని తిరిగి నమోదు చేయండి"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"గుర్తింపును మెరుగుపరచడానికి, దయచేసి మీ ముఖంను తిరిగి నమోదు చేసుకోండి"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"ముఖం డేటా సరిగ్గా రాలేదు. మళ్లీ ప్రయత్నించండి."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"వెలుతురు అధికంగా ఉంది. తక్కువ ఉండేలా చూడండి."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"చాలా చీకటిగా ఉంది. బాగా వెలుతురులో ప్రయత్నించండి."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"కాపీ చేయబడింది"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> నుండి పేస్ట్ చేయబడింది"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> క్లిప్బోర్డ్ నుండి పేస్ట్ చేయబడింది"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"ఎక్కువ"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"మెనూ+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,8 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"సత్వరమార్గాన్ని ఉపయోగించు"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"కలర్ మార్పిడి"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"కలర్ సరిచేయడం"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (3222994553174604132) -->
- <skip />
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"కాంతిని మరింత డిమ్ చేసే"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string>
<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>ని ఉపయోగించడానికి వాల్యూమ్ కీలు రెండింటినీ 3 సెకన్లు నొక్కి ఉంచండి"</string>
@@ -2111,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"ఆఫీస్"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"వ్యక్తిగత వీక్షణ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"పని వీక్షణ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"వర్క్ యాప్లతో దీనిని షేర్ చేయడం సాధ్యపడదు"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"మీ కార్యాలయ ప్రొఫైల్లోని యాప్లతో ఈ కంటెంట్ను మీరు షేర్ చేయడానికి మీ IT అడ్మిన్ అనుమతించరు"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"వర్క్ యాప్లతో తెరవడం సాధ్యపడదు"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"కార్యాలయ ప్రొఫైల్లోని యాప్లతో ఈ కంటెంట్ను మీరు తెరవడానికి మీ IT అడ్మిన్ అనుమతించరు"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"వ్యక్తిగత యాప్లతో దీనిని షేర్ చేయడం సాధ్యపడదు"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"మీ వ్యక్తిగత ప్రొఫైల్లోని యాప్లతో ఈ కంటెంట్ను మీరు షేర్ చేయడానికి మీ IT అడ్మిన్ అనుమతించరు"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"దీనిని, వ్యక్తిగత యాప్లతో తెరవడం సాధ్యపడదు"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"మీ వ్యక్తిగత ప్రొఫైల్లోని యాప్లతో ఈ కంటెంట్ను మీరు తెరవడానికి మీ IT అడ్మిన్ అనుమతించరు"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"కార్యాలయ ప్రొఫైల్ పాజ్ చేయబడింది"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"ఆన్ చేయి"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"కార్యాలయ యాప్లు ఏవీ ఈ కంటెంట్ను సపోర్ట్ చేయలేవు"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"కార్యాలయ యాప్లు ఏవీ ఈ కంటెంట్ను తెరవలేవు"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"వ్యక్తిగత యాప్లు ఏవీ ఈ కంటెంట్ను సపోర్ట్ చేయలేవు"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"వ్యక్తిగత యాప్లు ఏవీ ఈ కంటెంట్ను తెరవలేవు"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM నెట్వర్క్ అన్లాక్ పిన్"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM నెట్వర్క్ సబ్సెట్ అన్లాక్ పిన్"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM కార్పొరేట్ అన్లాక్ పిన్"</string>
@@ -2237,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"మీ స్క్రీన్లో కొంత భాగాన్ని మ్యాగ్నిఫై చేయండి"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"ఇప్పుడు మీరు మీ ఫుల్ స్క్రీన్ను, నిర్దిష్ట ఏరియాను మ్యాగ్నిఫై చేయగలరు లేదా రెండు ఆప్షన్ల మధ్య స్విచ్ చేయగలరు."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"సెట్టింగ్లలో ఆన్ చేయండి"</string>
<string name="dismiss_action" msgid="1728820550388704784">"విస్మరించు"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"కొనసాగించడానికి, <b><xliff:g id="APP">%s</xliff:g></b>కు మీ పరికరం యొక్క మైక్రోఫోన్ యాక్సెస్ అవసరం."</string>
diff --git a/core/res/res/values-television/themes.xml b/core/res/res/values-television/themes.xml
index 176e89e..b023c75 100644
--- a/core/res/res/values-television/themes.xml
+++ b/core/res/res/values-television/themes.xml
@@ -14,14 +14,14 @@
limitations under the License.
-->
<resources>
- <style name="Theme.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+ <style name="Theme.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
<style name="Theme.Dialog.Confirmation" parent="Theme.Leanback.Dialog.Confirmation" />
<style name="Theme.Holo.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
- <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+ <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
<style name="Theme.Material.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
- <style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+ <style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
<style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Leanback.Settings.Dialog.Alert" />
<style name="Theme.Material.Dialog" parent="Theme.Leanback.Dialog" />
- <style name="Theme.Material.Light.Dialog" parent="Theme.Leanback.Light.Dialog" />
+ <style name="Theme.Material.Light.Dialog" parent="Theme.Leanback.Dialog" />
<style name="Theme.Material.Settings.Dialog" parent="Theme.Leanback.Settings.Dialog" />
</resources>
diff --git a/core/res/res/values-television/themes_device_defaults.xml b/core/res/res/values-television/themes_device_defaults.xml
index d6bdeee..9d0e522 100644
--- a/core/res/res/values-television/themes_device_defaults.xml
+++ b/core/res/res/values-television/themes_device_defaults.xml
@@ -16,7 +16,7 @@
<resources>
<style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
<style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
- <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+ <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
<!-- TODO(b/116457731): remove colorBackground from colors_material.xml if not used anymore -->
<style name="Theme.DeviceDefault.Autofill" parent="Theme.Material">
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index a2bdfa7..c46c43b 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"แอปที่ทำงานอยู่"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"แอปหลายแอปกำลังใช้แบตเตอรี่"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"การขยาย"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"นโยบายความปลอดภัยสำหรับการช่วยเหลือพิเศษ"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังใช้แบตเตอรี่"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"แอป <xliff:g id="NUMBER">%1$d</xliff:g> แอปกำลังใช้แบตเตอรี่"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"เข้าถึงกิจกรรมการเคลื่อนไหวร่างกายของคุณ"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"กล้องถ่ายรูป"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ถ่ายภาพและบันทึกวิดีโอ"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"อุปกรณ์บลูทูธที่อยู่ใกล้เคียง"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"ค้นหาและเชื่อมต่อกับอุปกรณ์บลูทูธที่อยู่ใกล้เคียง"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"ประวัติการโทร"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"อ่านและเขียนบันทึกการโทรของโทรศัพท์"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"โทรศัพท์"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"อนุญาตให้แอปพลิเคชันดูการกำหนดค่าบลูทูธของแท็บเล็ต ตลอดจนเชื่อมต่อและยอมรับการเชื่อมต่อกับอุปกรณ์ที่จับคู่ไว้"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"อนุญาตให้แอปดูการกำหนดค่าบลูทูธในอุปกรณ์ Android TV ตลอดจนเชื่อมต่อและยอมรับการเชื่อมต่อกับอุปกรณ์ที่จับคู่ไว้"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"อนุญาตให้แอปพลิเคชันดูการกำหนดค่าบลูทูธของโทรศัพท์ ตลอดจนเชื่อมต่อและยอมรับการเชื่อมต่อกับอุปกรณ์ที่จับคู่ไว้"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"ค้นหาและจับคู่อุปกรณ์บลูทูธที่อยู่ใกล้เคียง"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"อนุญาตให้แอปค้นหาและจับคู่อุปกรณ์บลูทูธที่อยู่ใกล้เคียง"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"เชื่อมต่อกับอุปกรณ์บลูทูธที่จับคู่"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"อนุญาตให้แอปเชื่อมต่อกับอุปกรณ์บลูทูธที่จับคู่"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ข้อมูลบริการชำระเงิน NFC ที่ต้องการ"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"อนุญาตให้แอปรับข้อมูลบริการชำระเงิน NFC ที่ต้องการ เช่น รหัสแอป (AID) ที่ลงทะเบียนและปลายทางของเส้นทาง"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ควบคุม Near Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"การตรวจสอบข้อผิดพลาด"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ใช้การล็อกหน้าจอ"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"ป้อนข้อมูลเข้าสู่ระบบอุปกรณ์เพื่อดำเนินการต่อ"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"ตรวจพบลายนิ้วมือเพียงบางส่วน โปรดลองอีกครั้ง"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ประมวลผลลายนิ้วมือไม่ได้ โปรดลองอีกครั้ง"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"เซ็นเซอร์ลายนิ้วมือไม่สะอาด โปรดทำความสะอาดและลองอีกครั้ง"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"เคลื่อนนิ้วเร็วเกินไป โปรดลองอีกครั้ง"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"นิ้วเคลื่อนที่ช้าเกินไป โปรดลองอีกครั้ง"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"ตรวจสอบสิทธิ์ลายนิ้วมือแล้ว"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ตรวจสอบสิทธิ์ใบหน้าแล้ว"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ตรวจสอบสิทธิ์ใบหน้าแล้ว โปรดกดยืนยัน"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ฮาร์ดแวร์ลายนิ้วมือไม่พร้อมใช้งาน"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"ไม่สามารถเก็บลายนิ้วมือได้ โปรดนำลายนิ้วมือที่มีอยู่ออก"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"หมดเวลาใช้ลายนิ้วมือแล้ว โปรดลองอีกครั้ง"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ยกเลิกการทำงานของลายนิ้วมือ"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ผู้ใช้ยกเลิกการทำงานของลายนิ้วมือ"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ปลดล็อกด้วยใบหน้า"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ลงทะเบียนใบหน้าอีกครั้ง"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"โปรดลงทะเบียนใบหน้าอีกครั้งเพื่อปรับปรุงการจดจำ"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"บันทึกข้อมูลใบหน้าที่ถูกต้องไม่ได้ ลองอีกครั้ง"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"สว่างเกินไป ลองหาตำแหน่งที่แสงน้อยกว่านี้"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"มืดเกินไป ลองหาตำแหน่งที่สว่างขึ้น"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"คัดลอกแล้ว"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"วาง <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> จาก <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> แล้ว"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"วาง <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> จากคลิปบอร์ดแล้ว"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"เพิ่มเติม"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"เมนู+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"งาน"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"มุมมองส่วนตัว"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"ดูงาน"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"แชร์ด้วยแอปงานไม่ได้"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"ผู้ดูแลระบบไอทีไม่อนุญาตให้คุณแชร์เนื้อหานี้ด้วยแอปในโปรไฟล์งาน"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"เปิดด้วยแอปงานไม่ได้"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"ผู้ดูแลระบบไอทีไม่อนุญาตให้คุณเปิดเนื้อหานี้ด้วยแอปในโปรไฟล์งาน"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"แชร์ด้วยแอปส่วนตัวไม่ได้"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"ผู้ดูแลระบบไอทีไม่อนุญาตให้คุณแชร์เนื้อหานี้ด้วยแอปในโปรไฟล์ส่วนตัว"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"เปิดด้วยแอปส่วนตัวไม่ได้"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"ผู้ดูแลระบบไอทีไม่อนุญาตให้คุณเปิดเนื้อหานี้ด้วยแอปในโปรไฟล์ส่วนตัว"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"โปรไฟล์งานหยุดชั่วคราว"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"เปิด"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"ไม่มีแอปงานที่รองรับเนื้อหานี้"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ไม่มีแอปงานที่เปิดเนื้อหานี้ได้"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"ไม่มีแอปส่วนตัวที่รองรับเนื้อหานี้"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"ไม่มีแอปส่วนตัวที่เปิดเนื้อหานี้ได้"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN ปลดล็อกเครือข่ายที่ใช้กับ SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN ปลดล็อกเครือข่ายย่อยที่ใช้กับ SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN ปลดล็อกองค์กรที่ใช้กับ SIM"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"ขยายบางส่วนของหน้าจอ"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"ตอนนี้คุณสามารถขยายเป็นเต็มหน้าจอ ขยายพื้นที่ที่เจาะจง หรือจะสลับไปมาระหว่างตัวเลือกทั้ง 2 อย่างก็ได้"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"เปิดในการตั้งค่า"</string>
<string name="dismiss_action" msgid="1728820550388704784">"ปิด"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"<b><xliff:g id="APP">%s</xliff:g></b> ต้องได้รับสิทธิ์เข้าถึงไมโครโฟนของอุปกรณ์เพื่อดำเนินการต่อ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 030a3e5..790c25e 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Tumatakbo ang app"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Mga app na kumokonsumo ng baterya"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pag-magnify"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Patakaran sa seguridad ng accessibility"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Gumagamit ng baterya ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Gumagamit ng baterya ang <xliff:g id="NUMBER">%1$d</xliff:g> (na) app"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"I-tap para sa mga detalye tungkol sa paggamit ng baterya at data"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"i-access ang iyong pisikal na aktibidad"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Camera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"kumuha ng mga larawan at mag-record ng video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Mga Malapit na Bluetooth Device"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"tumuklas at kumonekta sa mga malapit na Bluetooth device"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Mga log ng tawag"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"binabasa at sinusulat ang log ng tawag sa telepono"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telepono"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Pinapayagan ang app na tingnan ang configuration ng Bluetooth sa tablet, at na gumawa at tumanggap ng mga koneksyong may mga nakapares na device."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Nagbibigay-daan sa app na tingnan ang configuration ng Bluetooth sa iyong Android TV device, and at gumawa at tumanggap ng mga koneksyon sa mga nakapares na device."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Pinapayagan ang app na tingnan ang configuration ng Bluetooth sa telepono, at na gumawa at tumanggap ng mga koneksyong may mga nakapares na device."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"tumuklas at makipagpares sa mga malapit na Bluetooth device"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Nagbibigay-daan sa app na tumuklas at makipagpares sa mga malapit na Bluetooth device"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"kumonekta sa mga nakapares na Bluetooth device"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Nagbibigay-daan sa app na kumonekta sa mga nakapares na Bluetooth device"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Impormasyon sa Gustong NFC na Serbisyo sa Pagbabayad"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Pinapayagan ang app na makakuha ng impormasyon sa gustong nfc na serbisyo sa pagbabayad tulad ng mga nakarehistrong application ID at destinasyon ng ruta."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrolin ang Near Field Communication"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Nagkaroon ng error sa pag-authenticate"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gumamit ng lock ng screen"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Ilagay ang kredensyal ng device para magpatuloy"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Hindi buo ang natukoy na fingerprint. Pakisubukan ulit."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Hindi maproseso ang fingerprint. Pakisubukan ulit."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Marumi ang sensor ng fingerprint. Pakilinis at subukang muli."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Napakabilis ng paggalaw ng daliri. Pakisubukan ulit."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Masyadong mabagal ang paggalaw ng daliri. Pakisubukan ulit."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Na-authenticate ang fingerprint"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Na-authenticate ang mukha"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Na-authenticate ang mukha, pakipindot ang kumpirmahin"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hindi available ang hardware na ginagamitan ng fingerprint."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Hindi maiimbak ang fingerprint. Mangyaring mag-alis ng umiiral nang fingerprint."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Nag-time out ang fingerprint. Subukang muli."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Nakansela ang operasyong ginagamitan ng fingerprint."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Kinansela ng user ang operasyon sa fingerprint."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"I-enroll ulit ang iyong mukha"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Para mapahusay ang pagkilala, paki-enroll ulit ang iyong mukha"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Hindi makakuha ng tamang face data. Subukang muli."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Masyadong maliwanag. Subukang bawasan ang liwanag."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Masyadong madilim. Subukan sa mas maliwanag."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Nakopya"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Na-paste ang <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> mula sa <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Na-paste ang <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> mula sa clipboard"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Higit pa"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Trabaho"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal na view"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"View ng trabaho"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Hindi ito puwedeng ibahagi sa mga app para sa trabaho"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Hindi ka pinapayagan ng iyong IT admin na ibahagi ang content na ito sa pamamagitan ng mga app sa iyong profile sa trabaho"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Hindi ito mabubuksan sa pamamagitan ng mga app para sa trabaho"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Hindi ka pinapayagan ng iyong IT admin na buksan ang content na ito sa pamamagitan ng mga app sa iyong profile sa trabaho"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Hindi ito puwedeng ibahagi sa mga personal na app"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Hindi ka pinapayagan ng iyong IT admin na ibahagi ang content na ito sa pamamagitan ng mga app sa iyong personal na profile"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Hindi ito mabubuksan sa pamamagitan ng mga personal na app"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Hindi ka pinapayagan ng iyong IT admin na buksan ang content na ito sa pamamagitan ng mga app sa iyong personal na profile"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Naka-pause ang profile sa trabaho"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"I-on"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Hindi masusuportahan ng mga app para sa trabaho ang content na ito"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Hindi mabubuksan ng mga app para sa trabaho ang content na ito"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Hindi masusuportahan ng mga personal na app ang content na ito"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Hindi mabubuksan ng mga personal na app ang content na ito"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN para sa pag-unlock ng network ng SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN para sa pag-unlock ng subset ng network ng SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN para sa pangkumpanyang pag-unlock ng SIM"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"I-magnify ang isang bahagi ng iyong screen"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Puwede ka na ngayong mag-magnify ng iyong buong screen o ng partikular na bahagi, o magpalipat-lipat sa dalawang opsyon."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"I-on sa Mga Setting"</string>
<string name="dismiss_action" msgid="1728820550388704784">"I-dismiss"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Para magpatuloy, kailangan ng <b><xliff:g id="APP">%s</xliff:g></b> ng access sa mikropono ng iyong device."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 30bf808..be54f7c 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Uygulama çalışıyor"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Pil kullanan uygulamalar"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Büyütme"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Erişilebilirlik güvenlik politikası"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> pil kullanıyor"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> uygulama pil kullanıyor"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pil ve veri kullanımı ile ilgili ayrıntılar için dokunun"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"fiziksel aktivitenize erişin"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"fotoğraf çekme ve video kaydetme"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Yakındaki Bluetooth Cihazlar"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"yakındaki Bluetooth cihazları keşfedip bağlan"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Arama kayıtları"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"telefon arama kaydını okuma ve yazma"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Uygulamaya, tabletteki Bluetooth yapılandırmasını görüntüleme, eşlenmiş cihazlarla bağlantı yapma ve bu tür bağlantıları kabul etme izni verir."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Uygulamaya, Android TV cihazınızdaki Bluetooth yapılandırmasını görüntüleme, eşleştirilmiş cihazlarla bağlantı yapma ve bu tür bağlantıları kabul etme izni verir."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Uygulamaya, telefondaki Bluetooth yapılandırmasını görüntüleme, eşlenmiş cihazlarla bağlantı yapma ve bu tür bağlantıları kabul etme izni verir."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"yakındaki Bluetooth cihazları keşfedip eşle"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Uygulamaya, yakındaki Bluetooth cihazları keşfedip eşleme izni verir"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"eşlenen Bluetooth cihazlara bağlan"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Uygulamaya, eşlenen Bluetooth cihazlara bağlanma izni verir"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Tercih Edilen NFC Ödeme Hizmeti Bilgileri"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Uygulamaya, kayıtlı yardımlar ve rota hedefi gibi tercih edilen NFC ödeme hizmeti bilgilerini alma izni verir."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Yakın Alan İletişimini denetle"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Kimlik doğrulama sırasında hata oluştu"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekran kilidi kullan"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Devam etmek için cihaz kimlik bilginizi girin"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Parmak izinin tümü algılanamadı. Lütfen tekrar deneyin."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Parmak izi işlenemedi. Lütfen tekrar deneyin."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Parmak izi sensörü kirli. Lütfen temizleyin ve tekrar deneyin."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Parmak hareketi çok hızlıydı. Lütfen tekrar deneyin."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Parmak hareketi çok yavaştı. Lütfen tekrar deneyin."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Parmak izi kimlik doğrulaması yapıldı"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Yüz kimliği doğrulandı"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Yüz kimliği doğrulandı, lütfen onayla\'ya basın"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Parmak izi donanımı kullanılamıyor."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Parmak izi depolanamıyor. Lütfen mevcut parmak izlerinden birini kaldırın."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Parmak izi için zaman aşımı oluştu. Tekrar deneyin."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Parmak izi işlemi iptal edildi."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Parmak izi işlemi kullanıcı tarafından iptal edildi."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Yüz tanıma kilidi"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Yüzünüzü yeniden kaydedin"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Daha iyi tanınmasını sağlamak için lütfen yüzünüzü yeniden kaydedin"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Doğru yüz verileri yakalanamadı. Tekrar deneyin."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Çok parlak. Parlaklığı daha az bir ışıklandırma deneyin."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Çok karanlık. Daha parlak ışıkta deneyin."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Kopyalandı"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> uygulaması <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> kaynağından yapıştırdı"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>, panodan yapıştırıldı."</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Diğer"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menü+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"İş"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Kişisel görünüm"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"İş görünümü"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Bu içerik, iş uygulamalarıyla paylaşılamıyor"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"BT yöneticiniz bu içeriği iş profilinizdeki uygulamalarla paylaşmanıza izin vermiyor"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Bu içerik, iş uygulamalarıyla açılamıyor"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"BT yöneticiniz bu içeriği iş profilinizdeki uygulamalarla açmanıza izin vermiyor"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Kişisel uygulamalarla paylaşılamıyor"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"BT yöneticiniz bu içeriği kişisel profilinizdeki uygulamalarla paylaşmanıza izin vermiyor"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Bu içerik, kişisel uygulamalarla açılamıyor"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"BT yöneticiniz bu içeriği kişisel profilinizdeki uygulamalarla açmanıza izin vermiyor"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"İş profili duraklatıldı"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Aç"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Hiçbir iş uygulaması bu içeriği destekleyemez"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Hiçbir iş uygulaması bu içeriği açamaz"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Hiçbir kişisel uygulama bu içeriği destekleyemez"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Hiçbir kişisel uygulama bu içeriği açamaz"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ağ kilidi açma PIN kodu"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ağ alt kümesi kilidini açma PIN kodu"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM kurumsal kilidi açma PIN kodu"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Ekranınızın bir bölümünü büyütün"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Artık ekranınızın tamamını veya belirli bir bölümünü büyütebilir veya bu iki seçenek arasında geçiş yapabilirsiniz."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ayarlar\'da aç"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Kapat"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Devam etmek için <b><xliff:g id="APP">%s</xliff:g></b> uygulamasının cihazınızın mikrofonuna erişmesi gerekiyor."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 30a829a..2cb286f 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -300,7 +300,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Працює додаток"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Додатки, що використовують заряд акумулятора"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Збільшення"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Правила щодо безпеки спеціальних можливостей"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> використовує заряд акумулятора"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Додатків, що використовують заряд акумулятора: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Торкніться, щоб перевірити використання акумулятора й трафік"</string>
@@ -325,6 +326,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"переглядати дані про фізичну активність"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Камера"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"фотографувати та записувати відео"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Пристрої з Bluetooth поблизу"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"знаходити поблизу пристрої з Bluetooth і підключатися до них"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Журнали викликів"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"перегляд і запис журналу викликів телефона"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Телефон"</string>
@@ -538,6 +541,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Дозволяє програмі переглядати конфігурацію Bluetooth на планшетному ПК, а також створювати та приймати з’єднання зі спареними пристроями."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Дозволяє додатку зчитувати конфігурацію Bluetooth на вашому пристрої Android TV, а також створювати та приймати з\'єднання зі спареними пристроями."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Дозволяє програмі переглядати конфігурацію Bluetooth на телефоні, а також створювати та приймати з’єднання зі спареними пристроями."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"знаходити пристрої з Bluetooth і створювати пару"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Дозволяє додатку знаходити поблизу пристрої Bluetooth і створювати з ними пару"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"підключатися до пристроїв із Bluetooth, з якими є пара"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Дозволяє додатку підключатися до пристроїв із Bluetooth, з якими створено пару"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Використання інформації з платіжного NFC-сервісу"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дозволяє додатку отримувати доступ до інформації потрібного платіжного NFC-сервісу (наприклад, пов\'язаних ідентифікаторів чи даних про маршрутизацію трансакцій)."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"контрол. Near Field Communication"</string>
@@ -573,18 +580,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Помилка автентифікації"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Доступ розблокуванням екрана"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Щоб продовжити, введіть дані для розблокування екрана пристрою"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Відбиток пальця розпізнано частково. Повторіть спробу."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Не вдалось обробити відбиток пальця. Повторіть спробу."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Датчик відбитків пальців забруднився. Очистьте його та повторіть спробу."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Ви забрали палець надто швидко. Повторіть спробу."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Ви провели пальцем надто повільно. Повторіть спробу."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Відбиток пальця автентифіковано"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Обличчя автентифіковано"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Обличчя автентифіковано. Натисніть \"Підтвердити\""</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Сканер відбитків пальців недоступний."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Не вдалося зберегти відбиток пальця. Видаліть наявний відбиток."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Час очікування відбитка пальця минув. Повторіть спробу."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Дію з відбитком пальця скасовано."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Користувач скасував дію з відбитком пальця."</string>
@@ -609,6 +626,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Фейсконтроль"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Повторно проскануйте обличчя"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Повторно проскануйте обличчя для ефективнішого розпізнавання"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Не вдалося чітко зняти обличчя. Повторіть спробу."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Занадто яскраво. Потрібно менше світла."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Занадто темно. Потрібно більше світла."</string>
@@ -1012,6 +1037,12 @@
<string name="copied" msgid="4675902854553014676">"Скопійовано"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Дані з додатка <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> вставлено в <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Дані з буфера обміну вставлено в <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Більше"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Меню+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2178,20 +2209,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Робоче"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Особистий перегляд"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Робочий перегляд"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Цей контент не можна надсилати в робочих додатках"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Ваш ІТ-адміністратор не дозволяє надсилати цей контент у додатках у робочому профілі"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Цей контент не можна відкривати в робочих додатках"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Ваш ІТ-адміністратор не дозволяє відкривати цей контент у додатках у робочому профілі"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Цей контент не можна надсилати в особистих додатках"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Ваш ІТ-адміністратор не дозволяє надсилати цей контент у додатках в особистому профілі"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Цей контент не можна відкривати в особистих додатках"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Ваш ІТ-адміністратор не дозволяє відкривати цей контент у додатках в особистому профілі"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Робочий профіль призупинено"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Увімкнути"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Немає робочих додатків для цього контенту"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Немає робочих додатків, щоб відкрити цей контент"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Особисті додатки не можуть підтримувати цей контент"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Особисті додатки не можуть відкривати цей контент"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-код розблокування мережі SIM-карти"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-код розблокування підгрупи мереж SIM-карти"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-код розблокування корпоративної SIM-карти"</string>
@@ -2304,8 +2346,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Збільшення частини екрана"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Тепер ви можете збільшувати весь екран чи певну область, а також переходити між цими режимами."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Увімкнути в налаштуваннях"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Закрити"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Щоб продовжити, надайте додатку <b><xliff:g id="APP">%s</xliff:g></b> доступ до мікрофона пристрою."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index c17309b..c0f21c4 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ایپ چل رہی ہے"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ایپس بیٹری خرچ کر رہی ہیں"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"میگنیفکیشن"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"ایکسیسبیلٹی سیکیورٹی کی پالیسی"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> بیٹری کا استعمال کر رہی ہے"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ایپس بیٹری کا استعمال کر رہی ہیں"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"بیٹری اور ڈیٹا استعمال کے بارے میں تفصیلات کے لیے تھپتھپائیں"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"اپنی جسمانی سرگرمی تک رسائی حاصل کریں"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"کیمرا"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"تصاویر لیں اور ویڈیو ریکارڈ کریں"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"قریبی بلوٹوتھ آلات"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"قریبی بلوٹوتھ آلات دریافت کریں اور ان سے منسلک کریں"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"کال لاگز"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"فون کال لاگ پڑھ کر لکھیں"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"فون"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ایپ کو ٹیبلیٹ پر بلوٹوتھ کی ترتیب دیکھنے اور جوڑا بنائے ہوئے آلات کے ساتھ کنکشنز بنانے اور قبول کرنے کی اجازت دیتا ہے۔"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ایپ کو آپ کے Android TV آلہ پر بلوٹوتھ کنفیگریشن دیکھنے، اور جوڑا بنائے ہوئے آلات کے ساتھ کنکشنز بنانے اور قبول کرنے کی اجازت دیتا ہے۔"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ایپ کو فون پر بلوٹوتھ کی ترتیب دیکھنے اور جوڑا بنائے ہوئے آلات کے ساتھ کنکشنز بنانے اور قبول کرنے کی اجازت دیتا ہے۔"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"قریبی بلوٹوتھ آلات دریافت کریں اور ان کا جوڑا بنائیں"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"ایپ کو قریبی بلوٹوتھ آلات دریافت کرنے اور ان کا جوڑا بنانے کی اجازت دیں"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"جوڑا بنائے ہوئے بلوٹوتھ آلات سے منسلک کریں"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"ایپ کو جوڑا بنائے ہوئے بلوٹوتھ آلات سے منسلک کرنے کی اجازت دیں"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ترجیح شدہ NFC ادائیگی کی سروس کی معلومات"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ایپ کو رجسٹرشدہ ایڈز اور روٹ ڈسٹنیشن جیسی ترجیح شدہ nfc ادائیگی سروس کی معلومات حاصل کرنے کی اجازت دیتا ہے۔"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Near Field کمیونیکیشن کنٹرول کریں"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"خرابی کی توثیق ہو رہی ہے"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"اسکرین لاک استعمال کریں"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"جاری رکھنے کیلئے اپنے آلے کی سند درج کریں"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"جزوی فنگر پرنٹ کی شناخت ہوئی۔ براہ کرم دوبارہ کوشش کریں۔"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"فنگر پرنٹ پر کارروائی نہیں کی جا سکی۔ براہ کرم دوبارہ کوشش کریں۔"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"فنگر پرنٹ سینسر گندا ہے۔ براہ کرم صاف کریں اور دوبارہ کوشش کریں۔"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"انگلی کو کافی تیزی سے ہٹا لیا گیا۔ براہ کرم دوبارہ کوشش کریں۔"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"انگلی کو بہت آہستہ ہٹایا گیا۔ براہ کرم دوبارہ کوشش کریں۔"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"فنگر پرنٹ کی تصدیق ہو گئی"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"چہرے کی تصدیق ہو گئی"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"چہرے کی تصدیق ہو گئی، براہ کرم \'تصدیق کریں\' کو دبائيں"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"فنگر پرنٹ ہارڈ ویئر دستیاب نہیں ہے۔"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"فنگر پرنٹ اسٹور نہیں کیا جا سکتا ہے۔ براہ کرم ایک موجودہ فنگر پرنٹ ہٹائیں۔"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"فنگر پرنٹ کی کارروائی منسوخ ہوگئی۔"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"صارف نے فنگر پرنٹ کی کارروائی منسوخ کر دی۔"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"چہرے کے ذریعے غیر مقفل کریں"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"اپنے چہرے کو دوبارہ مندرج کریں"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"شناخت کو بہتر بنانے کے لیے براہ کرم اپنے چہرے کو دوبارہ مندرج کریں"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"چہرے کا درست ڈيٹا کیپچر نہیں ہو سکا۔ پھر آزمائيں۔"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"کافی روشنی ہے۔ ہلکی روشنی میں آزمائیں۔"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"کافی اندھیرا ہے۔ تیز روشنی میں آزمائیں۔"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"کاپی ہو گیا"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> سے <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> میں پیسٹ کیا گیا"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"کلپ بورڈ سے <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> میں پیسٹ کیا گیا"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"مزید"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"مینو+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,8 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"شارٹ کٹ استعمال کریں"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"رنگوں کی تقلیب"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"رنگ کی تصحیح"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (3222994553174604132) -->
- <skip />
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"اضافی دھندلا"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آن ہے۔"</string>
<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> کا استعمال کرنے کے لیے 3 سیکنڈ تک والیوم کی دونوں کلیدوں کو چھوئیں اور دبائے رکھیں"</string>
@@ -2111,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"دفتر"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ذاتی ملاحظہ"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"دفتری ملاحظہ"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"ورک ایپس کے ساتھ اس کا اشتراک نہیں کر سکتے"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"آپ کا IT منتظم آپ کو اپنے دفتری پروفائل میں ایپس کے ساتھ اس مواد کا اشتراک کرنے کی اجازت نہیں دیتا ہے"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"اس کو ورک ایپس کے ساتھ نہیں کھول سکتے"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"آپ کا IT منتظم آپ کو اپنے دفتری پروفائل میں ایپس کے ساتھ اس مواد کو کھولنے کی اجازت نہیں دیتا ہے"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"ذاتی ایپس کے ساتھ اس کا اشتراک نہیں کر سکتے"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"آپ کا IT منتظم آپ کو اپنے ذاتی پروفائل میں ایپس کے ساتھ اس مواد کا اشتراک کرنے کی اجازت نہیں دیتا ہے"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"اس کو ذاتی ایپس کے ساتھ نہیں کھول سکتے"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"آپ کا IT منتظم آپ کو اپنے ذاتی پروفائل میں ایپس کے ساتھ اس مواد کو کھولنے کی اجازت نہیں دیتا ہے"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"دفتری پروفائل روک دی گئی ہے"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"آن کریں"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"کوئی ورک ایپس اس مواد کا سپورٹ نہیں کر سکتی ہیں"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"کوئی ورک ایپس اس مواد کو نہیں کھول سکتی ہیں"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"کوئی ذاتی ایپس اس مواد کا سپورٹ نہیں کر سکتی ہیں"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"کوئی ذاتی ایپس اس مواد کو نہیں کھول سکتی ہیں"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM نیٹ ورک غیر مقفل کرنے کا PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM نیٹ ورک سب سیٹ کو غیر مقفل کرنے کا PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM کارپوریٹ کو غیر مقفل کرنے کا PIN"</string>
@@ -2237,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"اپنی اسکرین کے کسی حصے کو بڑا کریں"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"آپ اپنی فُل اسکرین، کسی مخصوص حصے کو بڑا کر سکتے ہیں یا دونوں اختیارات کے درمیان سوئچ کر سکتے ہیں۔"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ترتیبات میں آن کریں"</string>
<string name="dismiss_action" msgid="1728820550388704784">"برخاست کریں"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"جاری رکھنے کیلئے <xliff:g id="APP">%s</xliff:g><b><b> کو آپ کے آلے کے مائیکروفون تک رسائی درکار ہے۔"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index f302d33..f7ed329 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Ilova faol"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareya quvvatini sarflayotgan ilovalar"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Kattalashtirish"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Maxsus imkoniyatlar xavfsizlik siyosati"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi batareya quvvatini sarflamoqda"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ta ilova batareya quvvatini sarflamoqda"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya va trafik sarfi tafsilotlari uchun ustiga bosing"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"jismoniy harakatlar axborotiga ruxsat"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"suratga olish va video yozib olish"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Yaqin-atrofdagi Bluetooth qurilmalari"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"yaqin-atrofdagi Bluetooth qurilmalarini topish va ularga ulanish"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Chaqiruvlar jurnali"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"telefon chaqiruvlari jurnalini o‘qish va unga yozish"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Ilovaga planshetdagi Bluetooth‘ning sozlamasini ko‘rishga va bog‘langan qurilmalarga ulanish va ulardan ulanish so‘rovlarini qabul qulishga imkon beradi."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Ilovaga Android TV qurilmangizdagi Bluetooth sozlamasini koʻrishga va bogʻlangan qurilmalarga ulanish va ulardan ulanish talablarni qabul qilishga imkon beradi."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Ilovaga telefondagi Bluetooth‘ning sozlamasini ko‘rishga va bog‘langan qurilmalarga ulanish va ulardan ulanish so‘rovlarini qabul qulishga imkon beradi."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"Bluetooth qurilmalarini topish va juftlashish"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Ilovaga yaqin-atrofdagi Bluetooth qurilmalarini topish va juftlashish uchun ruxsat beradi"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"juftlangan Bluetooth qurilmalariga ulanish"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Ilovaga juftlangan Bluetooth qurilmalariga ulanish uchun ruxsat beradi"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Asosiy NFC toʻlov xizmati haqidagi axborot"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Bu ilovaga asosiy NFC toʻlov xizmati haqidagi axborotni olish imkonini beradi (masalan, qayd qilingan AID identifikatorlari va marshrutning yakuniy manzili)."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFC modulini boshqarish"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Autentifikatsiya amalga oshmadi"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekran qulfi"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Davom etish uchun qurilma kalitini kiritish"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Barmoq izi qisman aniqlandi. Qayta urinib ko‘ring."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Barmoq izi aniqlanmadi. Qaytadan urining."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Barmoq izi skanerini tozalab, keyin qaytadan urining."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Barmoq juda tez harakatlandi. Qaytadan urining."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Barmoq juda sekin harakatlandi. Qayta urinib ko‘ring."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Barmoq izi tekshirildi"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Yuzingiz aniqlandi"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Yuzingiz aniqlandi, tasdiqlash uchun bosing"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Barmoq izi skaneri ish holatida emas."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Barmoq izini saqlab bo‘lmadi. Mavjud barmoq izlaridan birini o‘chirib tashlang."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Barmoq izini aniqlash vaqti tugab qoldi. Qayta urinib ko‘ring."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Barmoq izi tekshiruvi bekor qilindi."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Barmoq izi amali foydalanuvchi tomonidan bekor qilindi"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Yuz bilan ochish"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Yuzingizni yana qayd qiling"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Yuzingiz yanada yaxshiroq aniqlanishi uchun uni yana bir marta qayd qiling"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Yuz ravshan suratga olinmadi. Qaytadan urining."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Juda yorqin. Biroz soyaroq joy tanlang."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Juda qorongʻi. Atrofingizni yoriting."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Nusxalandi"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> ilovasidan <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> joylandi"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"Vaqtincha xotiradan <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> joylandi"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Yana"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Menyu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Ish"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Shaxsiy rejim"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Ishchi rejim"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Ishga oid ilovalarga ulashilmaydi"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"AT administratoringiz bu turdagi kontentni ishchi profildagi ilovada ulashishni taqiqlagan"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Ishga oid ilovalarda ochilmaydi"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"AT administratoringiz bu turdagi kontentni ishchi profildagi ilovada ochilishini taqiqlagan"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Shaxsiy ilovalarga ulashilmaydi"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"AT administratoringiz bu turdagi kontentni shaxsiy profildagi ilovada ulashishni taqiqlagan"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Shaxsiy ilovalarda ochilmaydi"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"AT administratoringiz bu turdagi kontentni shaxsiy profildagi ilovada ochilishini taqiqlagan"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Ish profili pauzada"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Yoqish"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Bu kontent bilan ishlay oladigan ishga oid ilovalar topilmadi"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Bu kontentni ocha oladigan ishga oid ilovalar topilmadi"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Bu kontent bilan ishlay oladigan shaxsiy ilovalar topilmadi"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Bu kontentni ocha oladigan shaxsiy ilovalar topilmadi"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM kartaning tarmoqdagi qulfini ochish uchun PIN kod"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM karta tarmoq qismini qulfdan chiqarish uchun PIN kod"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Korporativ SIM kartalar qulfini ochish uchun PIN kod"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Ekranning bir qismini kattalashtirish"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Endi siz ekranni toʻliq yoki bir qismini kattalashtirishingiz yoki bu parametrlar orasida almashtirishingiz mumkin."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Sozlamalar orqali yoqish"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Yopish"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Davom etish uchun <b><xliff:g id="APP">%s</xliff:g></b> mikrofoningizdan foydalanishi kerak."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 421e1e7..cabfdfa 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Ứng dụng đang chạy"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Các ứng dụng tiêu thụ pin"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Phóng to"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Chính sách bảo mật của tính năng Hỗ trợ tiếp cận"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang sử dụng pin"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ứng dụng đang sử dụng pin"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"truy cập vào hoạt động thể chất"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Máy ảnh"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"chụp ảnh và quay video"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Các thiết bị Bluetooth ở gần"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"khám phá và kết nối với các thiết bị Bluetooth ở gần"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Nhật ký cuộc gọi"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"đọc và ghi nhật ký cuộc gọi điện thoại"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Điện thoại"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Cho phép ứng dụng xem cấu hình của Bluetooth trên máy tính bảng và tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Cho phép ứng dụng xem cấu hình của Bluetooth trên thiết bị Android TV, đồng thời tạo và chấp nhận các kết nối với thiết bị được ghép nối."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Cho phép ứng dụng xem cấu hình của Bluetooth trên điện thoại, tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"khám phá và ghép nối với thiết bị Bluetooth ở gần"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Cho phép ứng dụng khám phá và ghép nối với các thiết bị Bluetooth ở gần"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"kết nối với các thiết bị Bluetooth đã ghép nối"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Cho phép ứng dụng kết nối với thiết bị Bluetooth đã ghép nối"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Thông tin về dịch vụ thanh toán qua công nghệ giao tiếp tầm gần (NFC) được ưu tiên"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Cho phép ứng dụng nhận thông tin về dịch vụ thanh toán qua công nghệ giao tiếp tầm gần mà bạn ưu tiên, chẳng hạn như các hình thức hỗ trợ đã đăng ký và điểm đến trong hành trình."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kiểm soát Liên lạc trường gần"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Lỗi khi xác thực"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Dùng phương thức khóa màn hình"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Nhập thông tin xác thực thiết bị của bạn để tiếp tục"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Đã phát hiện được một phần vân tay. Vui lòng thử lại."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Không thể xử lý vân tay. Vui lòng thử lại."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Cảm biến vân tay bị bẩn. Hãy làm sạch và thử lại."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Di chuyển ngón tay quá nhanh. Vui lòng thử lại."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Di chuyển ngón tay quá chậm. Vui lòng thử lại."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Đã xác thực vân tay"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Đã xác thực khuôn mặt"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Đã xác thực khuôn mặt, vui lòng nhấn để xác nhận"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Phần cứng vân tay không khả dụng."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Không thể lưu vân tay. Vui lòng xóa vân tay hiện có."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Đã hết thời gian chờ vân tay. Hãy thử lại."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Thao tác dùng dấu vân tay bị hủy."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Người dùng đã hủy thao tác dùng dấu vân tay."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Mở khóa bằng khuôn mặt"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Đăng ký lại khuôn mặt của bạn"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Để cải thiện khả năng nhận dạng, hãy đăng ký lại khuôn mặt của bạn"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Không thể ghi lại đúng dữ liệu mặt. Hãy thử lại."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Quá sáng. Hãy thử giảm độ sáng."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Quá tối. Hãy thử tăng độ sáng."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Đã sao chép"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> đã dán dữ liệu từ <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> đã dán dữ liệu từ bảng nhớ tạm"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Thêm"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Trình đơn+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Công việc"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Chế độ xem cá nhân"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Chế độ xem công việc"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Không thể chia sẻ nội dung này với các ứng dụng công việc"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Quản trị viên CNTT không cho phép chia sẻ nội dung này với các ứng dụng trong hồ sơ công việc của bạn"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Không thể mở nội dung này bằng các ứng dụng công việc"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Quản trị viên CNTT không cho phép mở nội dung này bằng các ứng dụng trong hồ sơ công việc của bạn"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Không thể chia sẻ nội dung này với các ứng dụng cá nhân"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Quản trị viên CNTT không cho phép chia sẻ nội dung này với các ứng dụng trong hồ sơ cá nhân của bạn"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Không thể mở nội dung này bằng các ứng dụng cá nhân"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Quản trị viên CNTT không cho phép mở nội dung này bằng các ứng dụng trong hồ sơ cá nhân của bạn"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Hồ sơ công việc đã bị tạm dừng"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Bật"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Các ứng dụng công việc không hỗ trợ nội dung này"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Các ứng dụng công việc không thể mở nội dung này"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Các ứng dụng cá nhân không hỗ trợ nội dung này"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Các ứng dụng cá nhân không thể mở nội dung này"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Mã PIN mở khóa mạng SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Mã PIN mở khóa tập con của mạng SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Mã PIN mở khóa SIM corporate"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Phóng to một phần màn hình"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Giờ đây, bạn có thể phóng to toàn màn hình, một vùng cụ thể hoặc chuyển đổi giữa hai tùy chọn."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Bật trong phần Cài đặt"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Đóng"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Để tiếp tục, <b><xliff:g id="APP">%s</xliff:g></b> cần quyền truy cập vào micrô trên thiết bị của bạn."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index d7c64e2..c8f035a 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"应用正在运行中"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"消耗电量的应用"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大功能"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"无障碍服务安全政策"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>正在消耗电量"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 个应用正在消耗电量"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"点按即可详细了解电量和流量消耗情况"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"获取您的身体活动数据"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"相机"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"拍摄照片和录制视频"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"附近的蓝牙设备"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"发现并连接到附近的蓝牙设备"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"通话记录"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"读取和写入手机通话记录"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"电话"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"允许该应用查看平板电脑上的蓝牙配置,以及与配对设备建立连接或接受其连接请求。"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"允许应用查看 Android TV 设备上的蓝牙配置,以及与配对设备建立连接或接受其连接请求。"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"允许该应用查看手机上的蓝牙配置,以及与配对设备建立连接或接受其连接请求。"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"发现附近的蓝牙设备并与其配对"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"允许该应用发现附近的蓝牙设备并与其配对"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"连接到已配对的蓝牙设备"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"允许该应用连接到已配对的蓝牙设备"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"首选 NFC 付款服务信息"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允许应用获取首选 NFC 付款服务信息,例如注册的应用标识符和路线目的地。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"控制近距离通信"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"进行身份验证时出错"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"使用屏幕锁定凭据"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"输入您的设备凭据才能继续"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"仅检测到部分指纹,请重试。"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"无法处理指纹,请重试。"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"指纹传感器有脏污。请擦拭干净,然后重试。"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"手指移动太快,请重试。"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"手指移动太慢,请重试。"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"已验证指纹"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"面孔已验证"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"面孔已验证,请按确认按钮"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"指纹硬件无法使用。"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"无法存储指纹。请移除一个现有的指纹。"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"指纹录入操作超时,请重试。"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"指纹操作已取消。"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"用户取消了指纹操作。"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"人脸解锁"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"重新注册您的面孔"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"要提升识别精确度,请重新注册您的面孔"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"无法捕获准确的人脸数据,请重试。"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"亮度过高,请尝试使用较柔和的亮度。"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"亮度不足,请尝试将光线调亮。"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"已复制"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>已粘贴从<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>复制的内容"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>已粘贴剪贴板中的内容"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"更多"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"MENU+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -1689,7 +1720,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用快捷方式"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"颜色反转"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"色彩校正"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"超暗"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"极暗"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已开启。"</string>
<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">"同时按住两个音量键 3 秒钟即可使用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"工作"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"个人视图"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"工作视图"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"无法通过工作应用分享此内容"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"您的 IT 管理员不允许您通过工作资料中的应用分享此内容"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"无法通过工作应用打开此内容"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"您的 IT 管理员不允许您通过工作资料中的应用打开此内容"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"无法通过个人应用分享此内容"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"您的 IT 管理员不允许您通过个人资料中的应用分享此内容"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"无法通过个人应用打开此内容"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"您的 IT 管理员不允许您通过个人资料中的应用打开此内容"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"工作资料已被暂停"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"开启"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"任何工作应用都不支持此内容"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"任何工作应用都无法打开此内容"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"任何个人应用都不支持此内容"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"任何个人应用都无法打开此内容"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM 网络解锁 PIN 码"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM 网络子集解锁 PIN 码"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM 企业解锁 PIN 码"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"放大局部屏幕"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"现在,您可以放大整个屏幕或特定区域,也可以在这两个选项之间切换。"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在“设置”中开启"</string>
<string name="dismiss_action" msgid="1728820550388704784">"关闭"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"如要继续操作,请向<b><xliff:g id="APP">%s</xliff:g></b>授予设备的麦克风使用权。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index bc89bed..68fef91 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"應用程式正在執行"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"耗用電量的應用程式"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"無障礙工具安全性政策"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用電量"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在使用電量"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕按即可查看電池和數據用量詳情"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"存取體能活動"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"相機"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"拍照和錄製影片"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"附近的藍牙裝置"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"探索並連接附近的藍牙裝置"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"通話記錄"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"讀取及寫入手機通話記錄"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"電話"</string>
@@ -437,8 +440,8 @@
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"允許應用程式存取額外的位置提供者指令。這項設定可能會使應用程式干擾 GPS 或其他位置來源的運作。"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"只在前景存取精確位置"</string>
<string name="permdesc_accessFineLocation" msgid="6732174080240016335">"使用此應用程式時,應用程式可透過定位服務獲取您的精確位置。您的裝置必須開啟定位服務,才能讓應用程式獲取位置。這可能會增加電池用量。"</string>
- <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"只在前景存取大概位置"</string>
- <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"使用此應用程式時,應用程式可透過定位服務獲取您的大概位置。您的裝置必須開啟定位服務,才能讓應用程式獲取位置。"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"只在前景存取概略位置"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"使用此應用程式時,應用程式可透過定位服務獲取您的概略位置。您的裝置必須開啟定位服務,才能讓應用程式獲取位置。"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"在背景存取位置資訊"</string>
<string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"即使您不使用此應用程式,它仍可隨時存取位置。"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"更改音效設定"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"允許應用程式查看平板電腦的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"允許應用程式查看 Android TV 裝置的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"允許應用程式查看手機的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"探索並配對附近的藍牙裝置"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"允許應用程式探索並配對附近的藍牙裝置"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"連接附近的藍牙裝置"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"允許應用程式連接已配對的藍牙裝置"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"由用戶允許授權的 NFC 付款服務資訊"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允許應用程式取得由用戶允許授權的 NFC 付款服務資訊 (如已註冊的付款輔助功能和最終付款對象)。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"控制近距離無線通訊"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"驗證時發生錯誤"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"使用螢幕鎖定"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"如要繼續操作,請輸入裝置憑證"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"只偵測到部分指紋。請再試一次。"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"無法處理指紋。請再試一次。"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"指紋感應器不乾淨。請清潔後再試一次。"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"手指移動太快。請再試一次。"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"手指移動太慢,請重試。"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"驗證咗指紋"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"面孔已經驗證"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"面孔已經驗證,請㩒一下 [確認]"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"無法使用指紋軟件。"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"指紋無法儲存。請移除現有指紋。"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"指紋已逾時。請再試一次。"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋操作已取消。"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"使用者已取消指紋操作。"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"臉孔解鎖"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"重新註冊臉孔"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"如要提高識別能力,請重新註冊您的臉孔"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"無法擷取準確的臉容資料。請再試一次。"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"影像太亮。請嘗試在更暗的環境下使用。"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"影像太暗。請嘗試在更明亮的環境下使用。"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"已複製"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> 已貼上從 <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> 複製的資料"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> 已貼上剪貼簿中的資料"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"更多"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"選單鍵 +"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -1950,7 +1981,7 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"已連線至 <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"輕按即可查看檔案"</string>
<string name="pin_target" msgid="8036028973110156895">"固定"</string>
- <string name="pin_specific_target" msgid="7824671240625957415">"將<xliff:g id="LABEL">%1$s</xliff:g>置頂"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"固定「<xliff:g id="LABEL">%1$s</xliff:g>」"</string>
<string name="unpin_target" msgid="3963318576590204447">"取消固定"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"取消將<xliff:g id="LABEL">%1$s</xliff:g>置頂"</string>
<string name="app_info" msgid="6113278084877079851">"應用程式資料"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"公司"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"個人檢視模式"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"工作檢視模式"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"無法透過工作應用程式分享此內容"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT 管理員不允許您透過工作設定檔中的應用程式分享此內容"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"無法透過工作應用程式開啟此內容"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT 管理員不允許您透過工作設定檔中的應用程式開啟此內容"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"無法透過個人應用程式分享此內容"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT 管理員不允許您透過個人設定檔中的應用程式分享此內容"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"無法透過個人應用程式開啟此內容"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT 管理員不允許您透過個人設定檔中的應用程式開啟此內容"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"工作設定檔已暫停使用"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"開啟"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"沒有可支援此內容的工作應用程式"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"沒有可開啟此內容的工作應用程式"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"沒有可支援此內容的個人應用程式"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"沒有可開啟此內容的個人應用程式"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM 網絡解鎖 PIN"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM 網絡子集解鎖 PIN"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM 公司解鎖 PIN"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"放大部分畫面"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"您現在可放大整個或局部畫面,亦可切換這兩種模式。"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在「設定」中開啟"</string>
<string name="dismiss_action" msgid="1728820550388704784">"關閉"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"如要繼續,<b><xliff:g id="APP">%s</xliff:g></b> 需要裝置的麥克風存取權。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index f728be8..1ab5024 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"應用程式執行中"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"正在耗用電量的應用程式"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"無障礙工具安全性政策"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在耗用電量"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在耗用電量"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕觸即可查看電池和數據用量詳情"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"存取你的體能活動記錄"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"相機"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"拍照及錄製影片"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"鄰近藍牙裝置"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"探索鄰近藍牙裝置並進行連線"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"通話記錄"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"讀取及寫入通話記錄"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"電話"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"允許應用程式查看平板電腦的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"允許應用程式查看 Android TV 裝置的藍牙設定,以及建立及接受與其他配對裝置的連線。"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"允許應用程式查看手機的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"探索鄰近藍牙裝置並進行配對"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"允許應用程式探索鄰近藍牙裝置並進行配對"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"與已配對的藍牙裝置連線"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"允許應用程式與已配對的藍牙裝置連線"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"首選 NFC 付費服務資訊"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允許應用程式取得首選 NFC 付費服務資訊,例如已註冊的輔助工具和路線目的地。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"控制近距離無線通訊"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"驗證時發生錯誤"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"使用螢幕鎖定功能"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"如要繼續操作,請輸入裝置憑證"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"僅偵測到部分指紋,請再試一次。"</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"無法處理指紋,請再試一次。"</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"指紋感應器有髒汙。請清潔感應器,然後再試一次。"</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"手指移動速度過快,請再試一次。"</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"手指移動速度過慢,請再試一次。"</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"指紋驗證成功"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"臉孔驗證成功"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"臉孔驗證成功,請按下 [確認] 按鈕"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"指紋硬體無法使用。"</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"無法儲存指紋,請先移除現有指紋。"</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"指紋處理作業逾時,請再試一次。"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋作業已取消。"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"使用者已取消指紋驗證作業。"</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"人臉解鎖"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"請重新註冊你的臉孔"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"為提升辨識精準度,請重新註冊你的臉孔"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"無法擷取精準臉孔資料,請再試一次。"</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"亮度過高,請嘗試使用較柔和的照明方式。"</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"亮度不足,請嘗試使用較明亮的照明方式。"</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"已複製"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」已貼上從「<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>」複製的資料"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」已貼上剪貼簿中的資料"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"更多"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"[Menu] +"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta +"</string>
@@ -2055,7 +2086,7 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"日常安排模式資訊通知"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"電池電力可能會在你平常的充電時間前耗盡"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"已啟用省電模式以延長電池續航力"</string>
- <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"省電模式"</string>
+ <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"節約耗電量"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"省電模式已關閉"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"手機電力充足,各項功能不再受到限制。"</string>
<string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"平板電腦電力充足,各項功能不再受到限制。"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"工作"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"個人檢視模式"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"工作檢視模式"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"無法透過工作應用程式分享這項內容"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"IT 管理員不允許你透過工作資料夾中的應用程式分享這項內容"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"無法透過工作應用程式開啟這項內容"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"IT 管理員不允許你透過工作資料夾中的應用程式開啟這項內容"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"無法透過個人應用程式分享這項內容"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"IT 管理員不允許你透過個人資料夾中的應用程式分享這項內容"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"無法透過個人應用程式開啟這項內容"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"IT 管理員不允許你透過個人資料夾中的應用程式開啟這項內容"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"工作資料夾已暫停使用"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"開啟"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"沒有可支援這項內容的工作應用程式"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"沒有可開啟這項內容的工作應用程式"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"沒有可支援這項內容的個人應用程式"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"沒有可開啟這項內容的個人應用程式"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM 卡網路解鎖 PIN 碼"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM 卡網路子集解鎖 PIN 碼"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM 卡企業解鎖 PIN 碼"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"放大局部螢幕畫面"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"你現在可以放大整個或局部螢幕畫面,也可以隨時切換這兩種模式。"</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在「設定」中開啟"</string>
<string name="dismiss_action" msgid="1728820550388704784">"關閉"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"如要繼續操作,請將裝置的麥克風存取權授予「<xliff:g id="APP">%s</xliff:g>」<b></b>。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index dc15edc..d6fcb0d 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -294,7 +294,8 @@
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Uhlelo loksuebenza olusebenzayo"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Izinhlelo zokusebenza ezidla ibhethri"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ukukhuliswa"</string>
- <string name="notification_channel_accessibility_security_policy" msgid="3350443906017624270">"Inqubomgomo yokuvikeleka kokufinyeleleka"</string>
+ <!-- no translation found for notification_channel_accessibility_security_policy (1727787021725251912) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> isebenzisa ibhethri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> izinhlelo zokusebenza zisebenzisa ibhethri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Thepha ngemininingwane ekusetshenzisweni kwebhethri nedatha"</string>
@@ -319,6 +320,8 @@
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"finyelela kumsebenzi wakho womzimba"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Ikhamela"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"thatha izithombe uphinde urekhode ividiyo"</string>
+ <string name="permgrouplab_nearby_devices" msgid="14428105203684587">"Amadivayisi we-Bluetooth Aseduze"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="1146639974734121820">"thola futhi uxhume kumadivayisi we-Bluetooth aseduze"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Amarekhodi wamakholi"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"funda futhi ubhale irekhodi lamakholi efoni"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Ifoni"</string>
@@ -532,6 +535,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Ivumela uhlelo lokusebenza ukubuka ukucushwa kwe-Bluetooth kuthebhulethi, nokwenza futhi nokwamukela uxhumo namadivayisi amatanisiwe."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Ivumela uhlelo lokusebenza ukubuka ukucushwa kwe-Bluetooth kudivayisi ye-Android TV, nokwenza futhi nokwamukela uxhumo namadivayisi abhangqiwe."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Ivumela uhlelo lokusebenza ukubuka ukucushwa kwe-Bluetooth efonini, ukwenza futhi nokwamukela uxhumo namadivayisi amatanisiwe."</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"thola futhi ubhangqe amadivayisi we-Bluetooth aseduze"</string>
+ <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Kuvumela i-app ithole futhi ibhangqe amadivayisi we-Bluetooth aseduze"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"xhuma kumadivayisi we-Bluetooth abhangqiwe"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Kuvumela i-app ixhume kumadivayisi we-Bluetooth abhangqiwe"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Ulwazi Lwesevisi Yenkokhelo Ye-NFC Okhethwayo"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Ivuemela uhlelo lokusebenza ukuthola ulwazi lesevisi yenkokhelo ye-nfc njengezinsiza zokubhalisa nezindawo zomzila."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"lawula Uxhumano Lwenkambu Eseduze"</string>
@@ -567,18 +574,28 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Iphutha lokufakazela ubuqiniso"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Sebenzisa isikhiya sesikrini"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="8638638125397857315">"Faka izifakazelo zedivayisi yakho ukuze uqhubeke"</string>
- <string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Izigxivizo zeminwe ezincane zitholiwe. Sicela uzame futhi."</string>
+ <!-- no translation found for fingerprint_acquired_partial (694598777291084823) -->
+ <skip />
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Ayikwazanga ukucubungula izigxivizo zeminwe. Sicela uzame futhi."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Inzwa yezigxivizo zeminwe ingcolile. Sicela uyihlanze uphinde uzame futhi."</string>
- <string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Umunwe uhanjiswe ngokushesha kakhulu. Sicela uzame futhi."</string>
+ <!-- no translation found for fingerprint_acquired_imager_dirty (5236744087471419479) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (1254724478300787385) -->
+ <skip />
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Umnwe uhanjiswe kancane kakhulu. Sicela uzame futhi."</string>
+ <!-- no translation found for fingerprint_acquired_already_enrolled (2285166003936206785) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_bright (3863560181670915607) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_try_adjusting (3667006071003809364) -->
+ <skip />
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"Izigxivizo zeminwe zigunyaziwe"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ubuso bufakazelwe ubuqiniso"</string>
<string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ukuqinisekiswa kobuso, sicela ucindezele okuthi qinisekisa"</string>
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Izingxenyekazi zekhompuyutha zezigxivizo zeminwe azitholakali."</string>
- <string name="fingerprint_error_no_space" msgid="6126456006769817485">"Izigxivizo zeminwe azikwazi ukugcinwa. Sicela ususe izigxivizo zeminwe ezikhona."</string>
+ <!-- no translation found for fingerprint_error_no_space (7285481581905967580) -->
+ <skip />
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Ukusebenza kwezigxivizo zeminwe kukhanseliwe."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Umsebenzi wezigxivizo zomunwe ukhanselwe umsebenzisi."</string>
@@ -603,6 +620,14 @@
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"I-Face unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Phinda ubhalise ubuso bakho"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Ukuze uthuthukise ukubonwa, sicela uphinde ubhalise ubuso bakho"</string>
+ <!-- no translation found for face_setup_notification_title (550617822603450009) -->
+ <skip />
+ <!-- no translation found for face_setup_notification_content (5463999831057751676) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_title (2002630611398849495) -->
+ <skip />
+ <!-- no translation found for fingerprint_setup_notification_content (205578121848324852) -->
+ <skip />
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Ayikwazanga ukuthwebula idatha enembile yobuso. Zama futhi."</string>
<string name="face_acquired_too_bright" msgid="8070756048978079164">"Kukhanya kakhulu. Zama ukukhanya okuthambile."</string>
<string name="face_acquired_too_dark" msgid="252573548464426546">"Kumnyama kakhulu Zama ukukhanyisa okukhanyayo."</string>
@@ -1006,6 +1031,12 @@
<string name="copied" msgid="4675902854553014676">"Kukopishiwe"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"I-<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> inamathiselwe kusuka ku-<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
<string name="pasted_from_clipboard" msgid="6295556725844421812">"I-<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> inamathiselwe kusuka ebhodini yokunamathisela"</string>
+ <!-- no translation found for pasted_text (4298871641549173733) -->
+ <skip />
+ <!-- no translation found for pasted_image (4729097394781491022) -->
+ <skip />
+ <!-- no translation found for pasted_content (646276353060777131) -->
+ <skip />
<string name="more_item_label" msgid="7419249600215749115">"Okuningi"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Imenyu+"</string>
<string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
@@ -2110,20 +2141,31 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"Umsebenzi"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Ukubuka komuntu siqu"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Ukubuka komsebenzi"</string>
- <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Ayikwazi ukwabelana ngalokhu ngezinhlelo zokusebenza"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="3332302070341130545">"Umphathi wakho we-IT akakuvumeli ukuthi wabelane ngalokhu okuqukethwe nezinhlelo zokusebenza kuphrofayela yakho yomsebenzi"</string>
- <string name="resolver_cant_access_work_apps" msgid="2455757966397563223">"Ayikwazi ukuvula lokhu ngezinhlelo zokusebenza zomsebenzi"</string>
- <string name="resolver_cant_access_work_apps_explanation" msgid="3626983885525445790">"Umphathi wakho we-IT akakuvumeli ukuthi uvule lokhu okuqukethwe ngezinhlelo zokusebenza kuphrofayela yakho yomsebenzi"</string>
- <string name="resolver_cant_share_with_personal_apps" msgid="3079139799233316203">"Ayikwazi ukwabelana ngalokhu ngezinhlelo zokusebenza zomuntu siqu"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="2959282422751315171">"Umphathi wakho we-IT akakuvumeli ukuthi wabelane ngalokhu okuqukethwe ngezinhlelo zokusebenza kuphrofayela yakho yomuntu siqu"</string>
- <string name="resolver_cant_access_personal_apps" msgid="648291604475669395">"Ayikwazi ukuvula lokhu ngezinhlelo zokusebenza zomuntu siqu"</string>
- <string name="resolver_cant_access_personal_apps_explanation" msgid="2298773629302296519">"Umphathi wakho we-IT akakuvumeli ukuthi uvule lokhu okuqukethwe ngezinhlelo zokusebenza kuphrofayela yakho yomuntu siqu"</string>
+ <!-- no translation found for resolver_cross_profile_blocked (3014597376026044840) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_work_apps_explanation (9071442683080586643) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_work_apps_explanation (1129960195389373279) -->
+ <skip />
+ <!-- no translation found for resolver_cant_share_with_personal_apps_explanation (6349766201904601544) -->
+ <skip />
+ <!-- no translation found for resolver_cant_access_personal_apps_explanation (1679399548862724359) -->
+ <skip />
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Iphrofayela yomsebenzi iphunyuziwe"</string>
- <string name="resolver_switch_on_work" msgid="2873009160846966379">"Vula"</string>
- <string name="resolver_no_work_apps_available_share" msgid="7933949011797699505">"Azikho izinhlelo zokusebenza zomsebenzi ezingasekela lokhu okuqukethwe"</string>
- <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Azikho izinhlelo zokusebenza ezingavula lokhu okuqukethwe"</string>
- <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Azikho izinhlelo zokusebenza ezingasekela lokhu okuqukethwe"</string>
- <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Azikho izinhlelo zokusebenza zomuntu siqu ezingavula lokhu okuqukethwe"</string>
+ <!-- no translation found for resolver_switch_on_work (463709043650610420) -->
+ <skip />
+ <!-- no translation found for resolver_no_work_apps_available (3298291360133337270) -->
+ <skip />
+ <!-- no translation found for resolver_no_personal_apps_available (6284837227019594881) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_personal (2937599899213467617) -->
+ <skip />
+ <!-- no translation found for miniresolver_open_in_work (152208044699347924) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_personal_browser (776072682871133308) -->
+ <skip />
+ <!-- no translation found for miniresolver_use_work_browser (543575306251952994) -->
+ <skip />
<string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Iphinikhodi yokuvula inethiwekhi ye-SIM"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Iphinikhodi yokuvula yesethi engaphansi yenethiwekhi ye-SIM"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Iphinikhodi yokuvula yenkampani ye-SIM"</string>
@@ -2236,8 +2278,10 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
- <string name="window_magnification_prompt_title" msgid="4657040468055863672">"Khulisa ingxenye yesikrini sakho"</string>
- <string name="window_magnification_prompt_content" msgid="3549230303326142349">"Manje usungakwazi ukukhulisa isikrini sakho esigcwele, indawo ethile, noma ushintshe phakathi kwazo zombili izinketho."</string>
+ <!-- no translation found for window_magnification_prompt_title (2876703640772778215) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (8159173903032344891) -->
+ <skip />
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Vula Kumasethingi"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Cashisa"</string>
<string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Ukuze uqhubeke, <b>i-<xliff:g id="APP">%s</xliff:g></b> idinga ukufinyelela imakrofoni yedivayisi yakho."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4b15e01..f508b3e 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3579,6 +3579,22 @@
<!-- Specifies whether the IME supports showing inline suggestions. -->
<attr name="supportsInlineSuggestions" format="boolean" />
<attr name="suppressesSpellChecker" format="boolean" />
+ <!-- Specifies whether the IME wants to be shown in the Input Method picker. Defaults to
+ true. Set this to false if the IME is intended to be accessed programmatically.
+ <p>
+ Note: This functions as a hint to the system, which may choose to ignore this
+ preference in certain situations or in future releases.-->
+ <attr name="showInInputMethodPicker" format="boolean" />
+ <!-- Specify one or more configuration changes that the IME will handle itself. If not
+ specified, the IME will be restarted if any of these configuration changes happen in
+ the system. Otherwise, the IME will remain running and its
+ {@link android.inputmethodservice.InputMethodService#onConfigurationChanged}
+ method is called with the new configuration.
+ <p>Note that all of these configuration changes can impact the
+ resource values seen by the application, so you will generally need
+ to re-retrieve all resources (including view layouts, drawables, etc)
+ to correctly handle any configuration change.-->
+ <attr name="configChanges" />
</declare-styleable>
<!-- This is the subtype of InputMethod. Subtype can describe locales (for example, en_US and
@@ -6070,6 +6086,8 @@
<attr name="color" />
<!-- Alpha multiplier applied to the base color. -->
<attr name="alpha" />
+ <!-- Perceptual luminance applied to the base color. From 0 to 100. -->
+ <attr name="lStar" format="float" />
</declare-styleable>
<!-- Drawable used to render according to the animation scale. Esp. when it is 0 due to battery
@@ -9535,4 +9553,12 @@
<attr name="iconfactoryIconSize" format="dimension"/>
<attr name="iconfactoryBadgeSize" format="dimension"/>
+ <!-- Perceptual luminance of a color, in accessibility friendly color space. From 0 to 100. -->
+ <attr name="lStar" format="float"/>
+
+ <declare-styleable name="DisplayHasherService">
+ <!-- The throttle duration for display hash requests
+ @hide @SystemApi -->
+ <attr name="throttleDurationMillis" format="integer" />
+ </declare-styleable>
</resources>
diff --git a/core/res/res/values/colors_leanback.xml b/core/res/res/values/colors_leanback.xml
index df0be03..1b0fad8 100644
--- a/core/res/res/values/colors_leanback.xml
+++ b/core/res/res/values/colors_leanback.xml
@@ -16,15 +16,11 @@
<!-- Colors specific to Leanback themes. -->
<resources>
- <color name="background_leanback_dark">#ff324248</color>
- <color name="background_leanback_light">#ffeeeeee</color>
+ <color name="background_leanback_dark">#FF1F232B</color>
<color name="primary_text_leanback_dark">#cceeeeee</color>
<color name="secondary_text_leanback_dark">#99eeeeee</color>
- <color name="primary_text_leanback_light">#cc222222</color>
- <color name="secondary_text_leanback_light">#99222222</color>
-
<color name="primary_text_leanback_formwizard_default_dark">#ffeeeeee</color>
<color name="btn_leanback_focused">#E8EAED</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b6c22bb..bf790fa 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -830,13 +830,13 @@
</string-array>
<!-- Default strength, in percentage, of bright color reduction when activated. -->
- <integer name="config_reduceBrightColorsStrengthDefault">0</integer>
+ <integer name="config_reduceBrightColorsStrengthDefault">50</integer>
<!-- Minimum strength, in percentage, supported by bright color reduction. -->
- <integer name="config_reduceBrightColorsStrengthMin">0</integer>
+ <integer name="config_reduceBrightColorsStrengthMin">25</integer>
<!-- Maximum strength, in percentage, supported by bright color reduction. -->
- <integer name="config_reduceBrightColorsStrengthMax">100</integer>
+ <integer name="config_reduceBrightColorsStrengthMax">90</integer>
<!-- Boolean indicating whether display white balance is supported. -->
<bool name="config_displayWhiteBalanceAvailable">false</bool>
@@ -3561,10 +3561,6 @@
<!-- True if assistant app should be pinned via Pinner Service -->
<bool name="config_pinnerAssistantApp">false</bool>
- <!-- List of files pinned by the Pinner Service with the JIT Zygote boot image b/119800099 -->
- <string-array translatable="false" name="config_jitzygoteBootImagePinnerServiceFiles">
- </string-array>
-
<!-- Number of days preloaded file cache should be preserved on a device before it can be
deleted -->
<integer name="config_keepPreloadsMinDays">7</integer>
@@ -4838,4 +4834,7 @@
<bool name="config_cecRcProfileSourceMediaContextSensitiveMenuHandled_default">false</bool>
<bool name="config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_allowed">true</bool>
<bool name="config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_default">true</bool>
+
+ <!-- Whether app hibernation deletes OAT artifact files as part of global hibernation. -->
+ <bool name="config_hibernationDeletesOatArtifactsEnabled">true</bool>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index afbbe46..cf5b4e1 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -47,10 +47,6 @@
<dimen name="status_bar_height_landscape">@dimen/status_bar_height_portrait</dimen>
<!-- Height of area above QQS where battery/time go -->
<dimen name="quick_qs_offset_height">48dp</dimen>
- <!-- Total height of QQS (quick_qs_offset_height + 128) -->
- <dimen name="quick_qs_total_height">176dp</dimen>
- <!-- Total height of QQS with two rows to fit media player (quick_qs_offset_height + 176) -->
- <dimen name="quick_qs_total_height_with_media">224dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_height">48dp</dimen>
<!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
diff --git a/core/res/res/values/dimens_leanback.xml b/core/res/res/values/dimens_leanback.xml
index 3ab2196..ecda735 100644
--- a/core/res/res/values/dimens_leanback.xml
+++ b/core/res/res/values/dimens_leanback.xml
@@ -89,4 +89,6 @@
<dimen name="leanback_button_radius">55dp</dimen>
<dimen name="leanback_button_padding_horizontal">22dp</dimen>
<dimen name="leanback_button_padding_vertical">11dp</dimen>
+
+ <dimen name="leanback_dialog_corner_radius">8dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bc49818..9e159f9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3095,6 +3095,10 @@
<public name="requestOptimizedExternalStorageAccess" />
<!-- @hide @SystemApi -->
<public name="playHomeTransitionSound" />
+ <public name="lStar" />
+ <!-- @hide @SystemApi -->
+ <public name="throttleDurationMillis" />
+ <public name="showInInputMethodPicker" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index dd64750..77ef15b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -745,7 +745,7 @@
<!-- Text shown when viewing channel settings for notifications related to accessibility
security policy. [CHAR_LIMIT=NONE]-->
- <string name="notification_channel_accessibility_security_policy">Accessibility security policy</string>
+ <string name="notification_channel_accessibility_security_policy">Accessibility usage</string>
<!-- Label for foreground service notification when one app is running.
[CHAR LIMIT=NONE BACKUP_MESSAGE_ID=6826789589341671842] -->
@@ -1579,15 +1579,21 @@
<string name="screen_lock_dialog_default_subtitle">Enter your device credential to continue</string>
<!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
- <string name="fingerprint_acquired_partial">Partial fingerprint detected. Please try again.</string>
+ <string name="fingerprint_acquired_partial">Partial fingerprint detected</string>
<!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
<string name="fingerprint_acquired_insufficient">Couldn\'t process fingerprint. Please try again.</string>
<!-- Message shown during fingerprint acquisision when the fingerprint sensor needs cleaning -->
- <string name="fingerprint_acquired_imager_dirty">Fingerprint sensor is dirty. Please clean and try again.</string>
+ <string name="fingerprint_acquired_imager_dirty">Clean the sensor</string>
<!-- Message shown during fingerprint acquisision when the user removes their finger from the sensor too quickly -->
- <string name="fingerprint_acquired_too_fast">Finger moved too fast. Please try again.</string>
+ <string name="fingerprint_acquired_too_fast">Finger moved too fast</string>
<!-- Message shown during fingerprint acquisision when the user moves their finger too slowly -->
<string name="fingerprint_acquired_too_slow">Finger moved too slow. Please try again.</string>
+ <!-- Message shown during fingerprint acquisition when the fingerprint was already enrolled.[CHAR LIMIT=50] -->
+ <string name="fingerprint_acquired_already_enrolled">Try another fingerprint</string>
+ <!-- Message shown during fingerprint acquisition when fingerprint sensor detected too much light.[CHAR LIMIT=50] -->
+ <string name="fingerprint_acquired_too_bright">Too bright</string>
+ <!-- Message shown during fingerprint acquisition when a fingerprint must be adjusted.[CHAR LIMIT=50] -->
+ <string name="fingerprint_acquired_try_adjusting">Try adjusting</string>
<!-- Array containing custom messages shown during fingerprint acquisision from vendor. Vendor is expected to add and translate these strings -->
<string-array name="fingerprint_acquired_vendor">
</string-array>
@@ -1602,7 +1608,7 @@
<!-- Error message shown when the fingerprint hardware can't be accessed -->
<string name="fingerprint_error_hw_not_available">Fingerprint hardware not available.</string>
<!-- Error message shown when the fingerprint hardware has run out of room for storing fingerprints -->
- <string name="fingerprint_error_no_space">Fingerprint can\'t be stored. Please remove an existing fingerprint.</string>
+ <string name="fingerprint_error_no_space">Can\u2019t set up fingerprint</string>
<!-- Error message shown when the fingerprint hardware timer has expired and the user needs to restart the operation. -->
<string name="fingerprint_error_timeout">Fingerprint time out reached. Try again.</string>
<!-- Generic error message shown when the fingerprint operation (e.g. enrollment or authentication) is canceled. Generally not shown to the user-->
@@ -5924,7 +5930,7 @@
<!-- Notification title to prompt the user that new magnification feature is available. [CHAR LIMIT=50] -->
<string name="window_magnification_prompt_title">New magnification settings</string>
<!-- Notification content to prompt the user that new magnification feature is available. [CHAR LIMIT=NONE] -->
- <string name="window_magnification_prompt_content">You can now magnify part of your screen.</string>
+ <string name="window_magnification_prompt_content">You can now magnify part of your screen</string>
<!-- Notification action to bring the user to magnification settings page. [CHAR LIMIT=50] -->
<string name="turn_on_magnification_settings_action">Turn on in Settings</string>
<!-- Notification action to dismiss. [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b924ecd..1ab3c84 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -480,6 +480,7 @@
<java-symbol type="string" name="config_bandwidthEstimateSource" />
<java-symbol type="integer" name="config_smartSelectionInitializedTimeoutMillis" />
<java-symbol type="integer" name="config_smartSelectionInitializingTimeoutMillis" />
+ <java-symbol type="bool" name="config_hibernationDeletesOatArtifactsEnabled"/>
<java-symbol type="color" name="tab_indicator_text_v4" />
@@ -1716,8 +1717,6 @@
<java-symbol type="dimen" name="status_bar_height" />
<java-symbol type="dimen" name="display_cutout_touchable_region_size" />
<java-symbol type="dimen" name="quick_qs_offset_height" />
- <java-symbol type="dimen" name="quick_qs_total_height" />
- <java-symbol type="dimen" name="quick_qs_total_height_with_media" />
<java-symbol type="drawable" name="ic_jog_dial_sound_off" />
<java-symbol type="drawable" name="ic_jog_dial_sound_on" />
<java-symbol type="drawable" name="ic_jog_dial_unlock" />
@@ -3148,7 +3147,6 @@
<java-symbol type="bool" name="config_pinnerCameraApp" />
<java-symbol type="bool" name="config_pinnerHomeApp" />
<java-symbol type="bool" name="config_pinnerAssistantApp" />
- <java-symbol type="array" name="config_jitzygoteBootImagePinnerServiceFiles" />
<java-symbol type="string" name="config_doubleTouchGestureEnableFile" />
diff --git a/core/res/res/values/themes_leanback.xml b/core/res/res/values/themes_leanback.xml
index efe5826..0be9e9800 100644
--- a/core/res/res/values/themes_leanback.xml
+++ b/core/res/res/values/themes_leanback.xml
@@ -15,31 +15,21 @@
-->
<resources>
<style name="Theme.Leanback.Dialog" parent="Theme.Material.BaseDialog">
- <item name="colorBackground">@color/background_leanback_dark</item>
- <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
- <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
- <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
- <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
- <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
- <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
- <item name="buttonBarButtonStyle">@style/Widget.Leanback.Button.ButtonBarGravityStart</item>
- <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
- </style>
-
- <style name="Theme.Leanback.Light.Dialog" parent="Theme.Material.Light.BaseDialog">
- <item name="colorBackground">@color/background_leanback_dark</item>
- <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
- <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
- <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
- <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
- <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
- <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
+ <item name="colorBackground">@color/background_leanback_dark</item>
+ <item name="dialogCornerRadius">@dimen/leanback_dialog_corner_radius</item>
+ <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
+ <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
+ <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
+ <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
+ <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
+ <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
<item name="buttonBarButtonStyle">@style/Widget.Leanback.Button.ButtonBarGravityStart</item>
- <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
+ <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
</style>
<style name="Theme.Leanback.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog">
<item name="colorBackground">@color/background_leanback_dark</item>
+ <item name="dialogCornerRadius">@dimen/leanback_dialog_corner_radius</item>
<item name="textColorPrimary">@color/primary_text_leanback_dark</item>
<item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
<item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
@@ -51,34 +41,25 @@
</style>
<style name="Theme.Leanback.Dialog.Alert" parent="Theme.Material.Dialog.BaseAlert">
- <item name="colorBackground">@color/background_leanback_dark</item>
- <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
- <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
- <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
- <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
- <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
- <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
- <item name="buttonBarButtonStyle">@style/Widget.Leanback.Button.ButtonBarGravityStart</item>
- <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
- </style>
-
- <style name="Theme.Leanback.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.BaseAlert">
- <item name="colorBackground">@color/background_leanback_light</item>
- <item name="textColorPrimary">@color/primary_text_leanback_light</item>
- <item name="textColorSecondary">@color/secondary_text_leanback_light</item>
- <item name="alertDialogStyle">@style/AlertDialog.Leanback.Light</item>
- <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
- <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
- <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
+ <item name="colorBackground">@color/background_leanback_dark</item>
+ <item name="dialogCornerRadius">@dimen/leanback_dialog_corner_radius</item>
+ <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
+ <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
+ <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
+ <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
+ <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
+ <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
<item name="buttonBarButtonStyle">@style/Widget.Leanback.Button.ButtonBarGravityStart</item>
- <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
+ <item name="buttonBarStyle">@style/Widget.Leanback.ButtonBar</item>
</style>
- <style name="Theme.Leanback.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert">
- <item name="colorBackground">@color/background_leanback_light</item>
- <item name="textColorPrimary">@color/primary_text_leanback_light</item>
- <item name="textColorSecondary">@color/secondary_text_leanback_light</item>
- <item name="alertDialogStyle">@style/AlertDialog.Leanback.Light</item>
+ <style name="Theme.Leanback.Settings.Dialog.Alert"
+ parent="Theme.Material.Settings.Dialog.BaseAlert">
+ <item name="colorBackground">@color/background_leanback_dark</item>
+ <item name="dialogCornerRadius">@dimen/leanback_dialog_corner_radius</item>
+ <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
+ <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
+ <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
<item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
<item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
<item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
@@ -144,9 +125,9 @@
<!-- Icon sizes -->
<item name="iconfactoryIconSize">@dimen/resolver_icon_size</item>
<item name="iconfactoryBadgeSize">@dimen/resolver_badge_size</item>
- </style>
+ </style>
<!-- @hide Special theme for the default system Activity-based Alert dialogs. -->
- <style name="Theme.Leanback.Dialog.Confirmation" parent="Theme.DeviceDefault.Dialog.Alert" />
+ <style name="Theme.Leanback.Dialog.Confirmation" parent="Theme.DeviceDefault.Dialog.Alert"/>
</resources>
diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java
index b517428..01e240a 100644
--- a/core/tests/coretests/src/android/content/ContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/ContentResolverTest.java
@@ -86,7 +86,7 @@
final AssetFileDescriptor afd = new AssetFileDescriptor(
new ParcelFileDescriptor(mImage.getFileDescriptor()), 0, mSize, null);
- when(mProvider.openTypedAssetFile(any(), any(), any(), any(), any(), any())).thenReturn(
+ when(mProvider.openTypedAssetFile(any(), any(), any(), any(), any())).thenReturn(
afd);
}
diff --git a/core/tests/coretests/src/android/graphics/FontListParserTest.java b/core/tests/coretests/src/android/graphics/FontListParserTest.java
index 7bc81cd..bef1a4e 100644
--- a/core/tests/coretests/src/android/graphics/FontListParserTest.java
+++ b/core/tests/coretests/src/android/graphics/FontListParserTest.java
@@ -24,14 +24,12 @@
import static android.text.FontConfig.FontFamily.VARIANT_ELEGANT;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
import static junit.framework.Assert.fail;
import android.graphics.fonts.FontStyle;
import android.os.LocaleList;
import android.text.FontConfig;
-import android.util.TypedXmlSerializer;
import android.util.Xml;
import androidx.test.filters.SmallTest;
@@ -43,7 +41,6 @@
import org.xmlpull.v1.XmlPullParserException;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -69,10 +66,6 @@
FontConfig.FontFamily family = readFamily(xml);
assertThat(family).isEqualTo(expected);
-
- String serialized = writeFamily(family);
- assertWithMessage("serialized = " + serialized)
- .that(readFamily(serialized)).isEqualTo(expected);
}
@Test
@@ -94,10 +87,6 @@
FontConfig.FontFamily family = readFamily(xml);
assertThat(family).isEqualTo(expected);
-
- String serialized = writeFamily(family);
- assertWithMessage("serialized = " + serialized)
- .that(readFamily(serialized)).isEqualTo(expected);
}
@Test
@@ -115,10 +104,6 @@
FontConfig.FontFamily family = readFamily(xml);
assertThat(family).isEqualTo(expected);
-
- String serialized = writeFamily(family);
- assertWithMessage("serialized = " + serialized)
- .that(readFamily(serialized)).isEqualTo(expected);
}
@Test
@@ -136,10 +121,6 @@
FontConfig.FontFamily family = readFamily(xml);
assertThat(family).isEqualTo(expected);
-
- String serialized = writeFamily(family);
- assertWithMessage("serialized = " + serialized)
- .that(readFamily(serialized)).isEqualTo(expected);
}
@Test
@@ -164,10 +145,6 @@
"sans-serif", LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT);
FontConfig.FontFamily family = readFamily(xml);
assertThat(family).isEqualTo(expected);
-
- String serialized = writeFamily(family);
- assertWithMessage("serialized = " + serialized)
- .that(readFamily(serialized)).isEqualTo(expected);
}
@Test
@@ -194,10 +171,6 @@
"sans-serif", LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT);
FontConfig.FontFamily family = readFamily(xml);
assertThat(family).isEqualTo(expected);
-
- String serialized = writeFamily(family);
- assertWithMessage("serialized = " + serialized)
- .that(readFamily(serialized)).isEqualTo(expected);
}
@Test
@@ -218,10 +191,6 @@
"sans-serif", LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT);
FontConfig.FontFamily family = readFamily(xml);
assertThat(family).isEqualTo(expected);
-
- String serialized = writeFamily(family);
- assertWithMessage("serialized = " + serialized)
- .that(readFamily(serialized)).isEqualTo(expected);
}
@Test
@@ -338,15 +307,4 @@
parser.nextTag();
return FontListParser.readFamily(parser, "", null);
}
-
- private String writeFamily(FontConfig.FontFamily family) throws IOException {
- TypedXmlSerializer out = Xml.newFastSerializer();
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- out.setOutput(buffer, "UTF-8");
- out.startTag(null, "family");
- FontListParser.writeFamily(out, family);
- out.endTag(null, "family");
- out.endDocument();
- return buffer.toString("UTF-8");
- }
}
diff --git a/core/tests/coretests/src/android/inputmethodservice/ImsConfigurationTrackerTest.java b/core/tests/coretests/src/android/inputmethodservice/ImsConfigurationTrackerTest.java
new file mode 100644
index 0000000..064439e
--- /dev/null
+++ b/core/tests/coretests/src/android/inputmethodservice/ImsConfigurationTrackerTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.inputmethodservice;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ImsConfigurationTrackerTest {
+ private ImsConfigurationTracker mImsConfigTracker;
+ private Context mContext;
+
+ @Before
+ public void setUp() throws TimeoutException {
+ mContext = getInstrumentation().getContext();
+ mImsConfigTracker = new ImsConfigurationTracker();
+ }
+
+ @Test
+ public void testShouldImeRestart() throws Exception {
+ Configuration config = mContext.getResources().getConfiguration();
+ mImsConfigTracker.onInitialize(0 /* handledConfigChanges */);
+ mImsConfigTracker.onBindInput(mContext.getResources());
+ Configuration newConfig = new Configuration(config);
+
+ final AtomicBoolean didReset = new AtomicBoolean();
+ Runnable resetStateRunner = () -> didReset.set(true);
+
+ mImsConfigTracker.onConfigurationChanged(newConfig, resetStateRunner);
+ assertFalse("IME shouldn't restart if config hasn't changed",
+ didReset.get());
+
+ // Screen density changed but IME doesn't handle configChanges
+ newConfig.densityDpi = 99;
+ mImsConfigTracker.onConfigurationChanged(newConfig, resetStateRunner);
+ assertTrue("IME should restart for unhandled configChanges",
+ didReset.get());
+
+ didReset.set(false);
+ // opt-in IME to handle density config changes.
+ mImsConfigTracker.setHandledConfigChanges(ActivityInfo.CONFIG_DENSITY);
+ mImsConfigTracker.onConfigurationChanged(newConfig, resetStateRunner);
+ assertFalse("IME shouldn't restart since it handles configChanges",
+ didReset.get());
+ }
+}
diff --git a/core/tests/coretests/src/android/provider/NameValueCacheTest.java b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
index 4212ef2..97e66c4 100644
--- a/core/tests/coretests/src/android/provider/NameValueCacheTest.java
+++ b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
@@ -33,6 +33,7 @@
import android.util.MemoryIntArray;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
@@ -73,7 +74,8 @@
Settings.Config.clearProviderForTest();
MockitoAnnotations.initMocks(this);
when(mMockContentProvider.getIContentProvider()).thenReturn(mMockIContentProvider);
- mMockContentResolver = new MockContentResolver();
+ mMockContentResolver = new MockContentResolver(InstrumentationRegistry
+ .getInstrumentation().getContext());
mMockContentResolver.addProvider(DeviceConfig.CONTENT_URI.getAuthority(),
mMockContentProvider);
mCacheGenerationStore = new MemoryIntArray(1);
@@ -82,10 +84,10 @@
// Stores keyValues for a given prefix and increments the generation. (Note that this
// increments the generation no matter what, it doesn't pay attention to if anything
// actually changed).
- when(mMockIContentProvider.call(any(), any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
+ when(mMockIContentProvider.call(any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
- Bundle incomingBundle = invocationOnMock.getArgument(5);
+ Bundle incomingBundle = invocationOnMock.getArgument(4);
HashMap<String, String> keyValues =
(HashMap<String, String>) incomingBundle.getSerializable(
Settings.CALL_METHOD_FLAGS_KEY);
@@ -101,10 +103,10 @@
// Returns the keyValues corresponding to a namespace, or an empty map if the namespace
// doesn't have anything stored for it. Returns the generation key if the caller asked
// for one.
- when(mMockIContentProvider.call(any(), any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
+ when(mMockIContentProvider.call(any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
eq(Settings.CALL_METHOD_LIST_CONFIG),
any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
- Bundle incomingBundle = invocationOnMock.getArgument(5);
+ Bundle incomingBundle = invocationOnMock.getArgument(4);
String prefix = incomingBundle.getString(Settings.CALL_METHOD_PREFIX_KEY);
@@ -132,14 +134,14 @@
HashMap<String, String> keyValues = new HashMap<>();
keyValues.put("a", "b");
Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
- verify(mMockIContentProvider).call(any(), any(), any(),
+ verify(mMockIContentProvider).call(any(), any(),
eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
any(), any(Bundle.class));
Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
NAMESPACE,
Collections.emptyList());
- verify(mMockIContentProvider).call(any(), any(), any(),
+ verify(mMockIContentProvider).call(any(), any(),
eq(Settings.CALL_METHOD_LIST_CONFIG),
any(), any(Bundle.class));
assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
@@ -152,13 +154,13 @@
// Modify the value to invalidate the cache.
keyValues.put("a", "c");
Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
- verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+ verify(mMockIContentProvider, times(2)).call(any(), any(),
eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
any(), any(Bundle.class));
Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
NAMESPACE, Collections.emptyList());
- verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+ verify(mMockIContentProvider, times(2)).call(any(), any(),
eq(Settings.CALL_METHOD_LIST_CONFIG),
any(), any(Bundle.class));
assertThat(returnedValues2).containsExactlyEntriesIn(keyValues);
@@ -174,7 +176,7 @@
HashMap<String, String> keyValues = new HashMap<>();
keyValues.put("a", "b");
Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
- verify(mMockIContentProvider).call(any(), any(), any(),
+ verify(mMockIContentProvider).call(any(), any(),
eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
any(), any(Bundle.class));
@@ -182,14 +184,14 @@
keyValues2.put("c", "d");
keyValues2.put("e", "f");
Settings.Config.setStrings(mMockContentResolver, NAMESPACE2, keyValues2);
- verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+ verify(mMockIContentProvider, times(2)).call(any(), any(),
eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
any(), any(Bundle.class));
Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
NAMESPACE,
Collections.emptyList());
- verify(mMockIContentProvider).call(any(), any(), any(),
+ verify(mMockIContentProvider).call(any(), any(),
eq(Settings.CALL_METHOD_LIST_CONFIG),
any(), any(Bundle.class));
assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
@@ -197,7 +199,7 @@
Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
NAMESPACE2,
Collections.emptyList());
- verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+ verify(mMockIContentProvider, times(2)).call(any(), any(),
eq(Settings.CALL_METHOD_LIST_CONFIG),
any(), any(Bundle.class));
assertThat(returnedValues2).containsExactlyEntriesIn(keyValues2);
@@ -218,7 +220,7 @@
Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
NAMESPACE,
Collections.emptyList());
- verify(mMockIContentProvider).call(any(), any(), any(),
+ verify(mMockIContentProvider).call(any(), any(),
eq(Settings.CALL_METHOD_LIST_CONFIG),
any(), any(Bundle.class));
assertThat(returnedValues).isEmpty();
diff --git a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
index 5f640be..4496983 100644
--- a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
+++ b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
@@ -18,13 +18,13 @@
import android.annotation.Nullable;
import android.app.AppOpsManager;
+import android.content.AttributionSource;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.CancellationSignal;
-import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract.Path;
@@ -93,14 +93,12 @@
}
@Override
- protected int enforceReadPermissionInner(Uri uri, String callingPkg,
- @Nullable String callingFeatureId, IBinder callerToken) {
+ protected int enforceReadPermissionInner(Uri uri, AttributionSource attributionSource) {
return AppOpsManager.MODE_ALLOWED;
}
@Override
- protected int enforceWritePermissionInner(Uri uri, String callingPkg,
- @Nullable String callingFeatureId, IBinder callerToken) {
+ protected int enforceWritePermissionInner(Uri uri, AttributionSource attributionSource) {
return AppOpsManager.MODE_ALLOWED;
}
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index 47556c3..34a1fd8 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -97,7 +97,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
// test if setVisibility can show IME
- mImeConsumer.onWindowFocusGained();
+ mImeConsumer.onWindowFocusGained(true);
mController.show(WindowInsets.Type.ime(), true /* fromIme */);
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
@@ -116,7 +116,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
// Request IME visible before control is available.
- mImeConsumer.onWindowFocusGained();
+ mImeConsumer.onWindowFocusGained(true);
mController.show(WindowInsets.Type.ime(), true /* fromIme */);
// set control and verify visibility is applied.
@@ -132,24 +132,58 @@
}
@Test
- public void testImeGetAndClearSkipAnimationOnce() {
+ public void testImeGetAndClearSkipAnimationOnce_expectSkip() {
+ // Expect IME animation will skipped when the IME is visible at first place.
+ verifyImeGetAndClearSkipAnimationOnce(true /* hasWindowFocus */, true /* hasViewFocus */,
+ true /* expectSkipAnim */);
+ }
+
+ @Test
+ public void testImeGetAndClearSkipAnimationOnce_expectNoSkip() {
+ // Expect IME animation will not skipped if previously no view focused when gained the
+ // window focus and requesting the IME visible next time.
+ verifyImeGetAndClearSkipAnimationOnce(true /* hasWindowFocus */, false /* hasViewFocus */,
+ false /* expectSkipAnim */);
+ }
+
+ private void verifyImeGetAndClearSkipAnimationOnce(boolean hasWindowFocus, boolean hasViewFocus,
+ boolean expectSkipAnim) {
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
// Request IME visible before control is available.
- mImeConsumer.onWindowFocusGained();
- mController.show(WindowInsets.Type.ime(), true /* fromIme */);
+ mImeConsumer.onWindowFocusGained(hasWindowFocus);
+ final boolean imeVisible = hasWindowFocus && hasViewFocus;
+ if (imeVisible) {
+ mController.show(WindowInsets.Type.ime(), true /* fromIme */);
+ }
// set control and verify visibility is applied.
InsetsSourceControl control = Mockito.spy(
new InsetsSourceControl(ITYPE_IME, mLeash, new Point(), Insets.NONE));
// Simulate IME source control set this flag when the target has starting window.
control.setSkipAnimationOnce(true);
- mController.onControlsChanged(new InsetsSourceControl[] { control });
- // Verify IME show animation should be triggered when control becomes available and
- // the animation will be skipped by getAndClearSkipAnimationOnce invoked.
- verify(control).getAndClearSkipAnimationOnce();
- verify(mController).applyAnimation(
- eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */,
- eq(true) /* skipAnim */);
+
+ if (imeVisible) {
+ // Verify IME applyAnimation should be triggered when control becomes available,
+ // and expect skip animation state after getAndClearSkipAnimationOnce invoked.
+ mController.onControlsChanged(new InsetsSourceControl[]{ control });
+ verify(control).getAndClearSkipAnimationOnce();
+ verify(mController).applyAnimation(eq(WindowInsets.Type.ime()),
+ eq(true) /* show */, eq(false) /* fromIme */,
+ eq(expectSkipAnim) /* skipAnim */);
+ }
+
+ // If previously hasViewFocus is false, verify when requesting the IME visible next
+ // time will not skip animation.
+ if (!hasViewFocus) {
+ mController.show(WindowInsets.Type.ime(), true);
+ mController.onControlsChanged(new InsetsSourceControl[]{ control });
+ // Verify IME show animation should be triggered when control becomes available and
+ // the animation will be skipped by getAndClearSkipAnimationOnce invoked.
+ verify(control).getAndClearSkipAnimationOnce();
+ verify(mController).applyAnimation(eq(WindowInsets.Type.ime()),
+ eq(true) /* show */, eq(true) /* fromIme */,
+ eq(false) /* skipAnim */);
+ }
});
}
}
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 4390546..6301f32 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -234,7 +234,7 @@
InsetsSourceControl ime = controls[2];
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained();
+ mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained(true);
// since there is no focused view, forcefully make IME visible.
mController.show(Type.ime(), true /* fromIme */);
mController.show(Type.all());
@@ -260,7 +260,7 @@
InsetsSourceControl ime = createControl(ITYPE_IME);
mController.onControlsChanged(new InsetsSourceControl[] { ime });
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained();
+ mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained(true);
mController.show(Type.ime(), true /* fromIme */);
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
index 0d5db6d..d2b52ba 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
@@ -563,7 +563,7 @@
}
@Test
- public void nodeWithA11yFocusWhenAnotherNodeGetsFocus_getsRefreshed() {
+ public void nodeWithA11yFocusWhenAnotherNodeGetsFocus_getsRemoved() {
AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
nodeInfo.setAccessibilityFocused(true);
mAccessibilityCache.add(nodeInfo);
@@ -573,7 +573,7 @@
mAccessibilityCache.onAccessibilityEvent(event);
event.recycle();
try {
- verify(mAccessibilityNodeRefresher).refreshNode(nodeInfo, true);
+ assertNull(mAccessibilityCache.getNode(WINDOW_ID_1, SINGLE_VIEW_ID));
} finally {
nodeInfo.recycle();
}
@@ -614,7 +614,7 @@
}
@Test
- public void nodeWithInputFocusWhenAnotherNodeGetsFocus_getsRefreshed() {
+ public void nodeWithInputFocusWhenAnotherNodeGetsFocus_getsRemoved() {
AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
nodeInfo.setFocused(true);
mAccessibilityCache.add(nodeInfo);
@@ -624,7 +624,7 @@
mAccessibilityCache.onAccessibilityEvent(event);
event.recycle();
try {
- verify(mAccessibilityNodeRefresher).refreshNode(nodeInfo, true);
+ assertNull(mAccessibilityCache.getNode(WINDOW_ID_1, SINGLE_VIEW_ID));
} finally {
nodeInfo.recycle();
}
@@ -733,20 +733,15 @@
}
@Test
- public void addA11yFocusNodeBeforeFocusClearedEvent_previousA11yFocusNodeGetsRefreshed() {
+ public void addA11yFocusNodeBeforeFocusClearedEvent_previousA11yFocusNodeGetsRemoved() {
AccessibilityNodeInfo nodeInfo1 = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
nodeInfo1.setAccessibilityFocused(true);
mAccessibilityCache.add(nodeInfo1);
AccessibilityNodeInfo nodeInfo2 = getNodeWithA11yAndWindowId(OTHER_VIEW_ID, WINDOW_ID_1);
nodeInfo2.setAccessibilityFocused(true);
mAccessibilityCache.add(nodeInfo2);
- AccessibilityEvent event = AccessibilityEvent.obtain(
- AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
- event.setSource(getMockViewWithA11yAndWindowIds(SINGLE_VIEW_ID, WINDOW_ID_1));
- mAccessibilityCache.onAccessibilityEvent(event);
- event.recycle();
try {
- verify(mAccessibilityNodeRefresher).refreshNode(nodeInfo1, true);
+ assertNull(mAccessibilityCache.getNode(WINDOW_ID_1, SINGLE_VIEW_ID));
} finally {
nodeInfo1.recycle();
nodeInfo2.recycle();
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index 549e074..5aacfdd 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -13,3 +13,4 @@
yamasani@google.com
per-file preinstalled-packages* = file:/MULTIUSER_OWNERS
+per-file services.core.protolog.json = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/data/etc/car/com.android.car.cluster.home.xml b/data/etc/car/com.android.car.cluster.home.xml
index 4c2d614..832e5a7 100644
--- a/data/etc/car/com.android.car.cluster.home.xml
+++ b/data/etc/car/com.android.car.cluster.home.xml
@@ -16,6 +16,8 @@
-->
<permissions>
<privapp-permissions package="com.android.car.cluster.home">
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.car.permission.ACCESS_PRIVATE_DISPLAY_ID"/>
<permission name="android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 1924e5f..15d1737 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -466,6 +466,8 @@
<permission name="android.contacts.permission.MANAGE_SIM_ACCOUNTS" />
<!-- Permissions required for CTS test - CtsHdmiCecHostTestCases -->
<permission name="android.permission.HDMI_CEC"/>
+ <!-- Permission required for CTS test - MediaPlayerTest -->
+ <permission name="android.permission.BIND_IMS_SERVICE" />
<!-- Permission needed for CTS test - WifiManagerTest -->
<permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
<permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index d9c0db9..77fe717 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1177,6 +1177,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
},
+ "-760764543": {
+ "message": "Focus not requested for window=%s because it has no surface or is not focusable.",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_FOCUS_LIGHT",
+ "at": "com\/android\/server\/wm\/InputMonitor.java"
+ },
"-754503024": {
"message": "Relayout %s: oldVis=%d newVis=%d. %s",
"level": "INFO",
@@ -1777,6 +1783,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimation.java"
},
+ "3593205": {
+ "message": "commitVisibility: %s: visible=%b mVisibleRequested=%b",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/WallpaperWindowToken.java"
+ },
"9803449": {
"message": "startFreezingDisplayLocked: exitAnim=%d enterAnim=%d called by %s",
"level": "DEBUG",
@@ -1843,12 +1855,6 @@
"group": "WM_DEBUG_TASKS",
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
},
- "63329306": {
- "message": "commitVisibility: %s: visible=%b mVisibleRequested=%b",
- "level": "VERBOSE",
- "group": "WM_DEBUG_WINDOW_TRANSITIONS",
- "at": "com\/android\/server\/wm\/WallpaperWindowToken.java"
- },
"73987756": {
"message": "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s",
"level": "INFO",
diff --git a/docs/html/reference/images/rounded_corner/rounded-corner-info.png b/docs/html/reference/images/rounded_corner/rounded-corner-info.png
new file mode 100644
index 0000000..312d935
--- /dev/null
+++ b/docs/html/reference/images/rounded_corner/rounded-corner-info.png
Binary files differ
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 95c7715..6fdf552 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -25,8 +25,6 @@
import android.os.Build;
import android.os.LocaleList;
import android.text.FontConfig;
-import android.text.TextUtils;
-import android.util.TypedXmlSerializer;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
@@ -194,32 +192,6 @@
return new FontConfig.FontFamily(fonts, name, LocaleList.forLanguageTags(lang), intVariant);
}
- /**
- * Write a family tag representing {@code fontFamily}. The tag should be started by the caller.
- */
- public static void writeFamily(TypedXmlSerializer out, FontConfig.FontFamily fontFamily)
- throws IOException {
- if (!TextUtils.isEmpty(fontFamily.getName())) {
- out.attribute(null, ATTR_NAME, fontFamily.getName());
- }
- if (!fontFamily.getLocaleList().isEmpty()) {
- out.attribute(null, ATTR_LANG, fontFamily.getLocaleList().toLanguageTags());
- }
- switch (fontFamily.getVariant()) {
- case FontConfig.FontFamily.VARIANT_COMPACT:
- out.attribute(null, ATTR_VARIANT, VARIANT_COMPACT);
- break;
- case FontConfig.FontFamily.VARIANT_ELEGANT:
- out.attribute(null, ATTR_VARIANT, VARIANT_ELEGANT);
- break;
- }
- for (FontConfig.Font font : fontFamily.getFontList()) {
- out.startTag(null, TAG_FONT);
- writeFont(out, font);
- out.endTag(null, TAG_FONT);
- }
- }
-
/** Matches leading and trailing XML whitespace. */
private static final Pattern FILENAME_WHITESPACE_PATTERN =
Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");
@@ -292,34 +264,6 @@
return null;
}
- private static void writeFont(TypedXmlSerializer out, FontConfig.Font font)
- throws IOException {
- if (font.getTtcIndex() != 0) {
- out.attributeInt(null, ATTR_INDEX, font.getTtcIndex());
- }
- if (font.getStyle().getWeight() != FontStyle.FONT_WEIGHT_NORMAL) {
- out.attributeInt(null, ATTR_WEIGHT, font.getStyle().getWeight());
- }
- if (font.getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC) {
- out.attribute(null, ATTR_STYLE, STYLE_ITALIC);
- } else {
- out.attribute(null, ATTR_STYLE, STYLE_NORMAL);
- }
- if (!TextUtils.isEmpty(font.getFontFamilyName())) {
- out.attribute(null, ATTR_FALLBACK_FOR, font.getFontFamilyName());
- }
- out.text(font.getFile().getName());
- FontVariationAxis[] axes =
- FontVariationAxis.fromFontVariationSettings(font.getFontVariationSettings());
- if (axes != null) {
- for (FontVariationAxis axis : axes) {
- out.startTag(null, TAG_AXIS);
- writeAxis(out, axis);
- out.endTag(null, TAG_AXIS);
- }
- }
- }
-
private static FontVariationAxis readAxis(XmlPullParser parser)
throws XmlPullParserException, IOException {
String tagStr = parser.getAttributeValue(null, ATTR_TAG);
@@ -328,12 +272,6 @@
return new FontVariationAxis(tagStr, Float.parseFloat(styleValueStr));
}
- private static void writeAxis(TypedXmlSerializer out, FontVariationAxis axis)
- throws IOException {
- out.attribute(null, ATTR_TAG, axis.getTag());
- out.attributeFloat(null, ATTR_STYLEVALUE, axis.getStyleValue());
- }
-
/**
* Reads alias elements
*/
diff --git a/graphics/java/android/graphics/drawable/RippleShader.java b/graphics/java/android/graphics/drawable/RippleShader.java
index 98b9584..01280a2 100644
--- a/graphics/java/android/graphics/drawable/RippleShader.java
+++ b/graphics/java/android/graphics/drawable/RippleShader.java
@@ -65,7 +65,7 @@
+ " float currentRadius = radius * progress;\n"
+ " float circle_outer = softCircle(uv, xy, currentRadius + thickness, blur);\n"
+ " float circle_inner = softCircle(uv, xy, currentRadius - thickness, blur);\n"
- + " return clamp(circle_outer - circle_inner, 0., 1.);\n"
+ + " return saturate(circle_outer - circle_inner);\n"
+ "}\n"
+ "float subProgress(float start, float end, float progress) {\n"
+ " float sub = clamp(progress, start, end);\n"
@@ -133,7 +133,7 @@
}
public void setResolution(float w, float h, int density) {
- float densityScale = density * DisplayMetrics.DENSITY_DEFAULT_SCALE * 0.5f;
+ float densityScale = density * DisplayMetrics.DENSITY_DEFAULT_SCALE;
setUniform("in_resolutionScale", new float[] {1f / w, 1f / h});
setUniform("in_noiseScale", new float[] {densityScale / w, densityScale / h});
}
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index 75e248e..df579bb 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -125,6 +125,8 @@
}
}
+ private static final String KEYSTORE2_SERVICE_NAME =
+ "android.system.keystore2.IKeystoreService/default";
private KeyStore2() {
mBinder = null;
@@ -137,7 +139,7 @@
private synchronized IKeystoreService getService(boolean retryLookup) {
if (mBinder == null || retryLookup) {
mBinder = IKeystoreService.Stub.asInterface(ServiceManager
- .getService("android.system.keystore2"));
+ .getService(KEYSTORE2_SERVICE_NAME));
}
return mBinder;
}
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 3f03302..18f019d 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -118,14 +118,14 @@
"androidx.appcompat_appcompat",
"androidx.arch.core_core-runtime",
"androidx.dynamicanimation_dynamicanimation",
+ "androidx.recyclerview_recyclerview",
"kotlinx-coroutines-android",
"kotlinx-coroutines-core",
"iconloader_base",
"jsr330",
"protolog-lib",
- "SettingsLib",
"WindowManager-Shell-proto",
- "jsr330"
+ "jsr330",
],
kotlincflags: ["-Xjvm-default=enable"],
manifest: "AndroidManifest.xml",
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index cd63de8..6edaf6f 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -41,13 +41,13 @@
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"מסך עליון מלא"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"עליון 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"עליון 50%"</string>
- <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"עליון 30%"</string>
+ <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"למעלה 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"מסך תחתון מלא"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"איך להשתמש במצב שימוש ביד אחת"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"כדי לצאת, יש להחליק למעלה מתחתית המסך או להקיש במקום כלשהו במסך מעל האפליקציה"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"הפעלה של מצב שימוש ביד אחת"</string>
<string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"יציאה ממצב שימוש ביד אחת"</string>
- <string name="bubbles_settings_button_description" msgid="1301286017420516912">"הגדרות בשביל בועות של <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1301286017420516912">"הגדרות לבועות של <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"גלישה"</string>
<string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"הוספה בחזרה לערימה"</string>
<string name="bubble_content_description_single" msgid="8495748092720065813">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> מהאפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 8d29123..0e78377 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -15,7 +15,13 @@
limitations under the License.
-->
<resources>
- <!-- Animation duration for resizing of PIP when entering/exiting. -->
+ <!-- Animation duration for PIP when entering. -->
+ <integer name="config_pipEnterAnimationDuration">425</integer>
+
+ <!-- Animation duration for PIP when exiting. -->
+ <integer name="config_pipExitAnimationDuration">250</integer>
+
+ <!-- Animation duration for resizing of PIP. -->
<integer name="config_pipResizeAnimationDuration">425</integer>
<!-- Allow dragging the PIP to a location to close it -->
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index 6f4550c..d1fbf31 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -19,6 +19,7 @@
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
import com.android.wm.shell.apppairs.AppPairsController;
+import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ExternalThread;
@@ -40,6 +41,7 @@
private final DisplayImeController mDisplayImeController;
private final DragAndDropController mDragAndDropController;
private final ShellTaskOrganizer mShellTaskOrganizer;
+ private final Optional<BubbleController> mBubblesOptional;
private final Optional<LegacySplitScreenController> mLegacySplitScreenOptional;
private final Optional<SplitScreenController> mSplitScreenOptional;
private final Optional<AppPairsController> mAppPairsOptional;
@@ -54,6 +56,7 @@
public ShellInitImpl(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
+ Optional<BubbleController> bubblesOptional,
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
@@ -65,6 +68,7 @@
mDisplayImeController = displayImeController;
mDragAndDropController = dragAndDropController;
mShellTaskOrganizer = shellTaskOrganizer;
+ mBubblesOptional = bubblesOptional;
mLegacySplitScreenOptional = legacySplitScreenOptional;
mSplitScreenOptional = splitScreenOptional;
mAppPairsOptional = appPairsOptional;
@@ -91,6 +95,7 @@
mAppPairsOptional.ifPresent(AppPairsController::onOrganizerRegistered);
mSplitScreenOptional.ifPresent(SplitScreenController::onOrganizerRegistered);
+ mBubblesOptional.ifPresent(BubbleController::initialize);
// Bind the splitscreen impl to the drag drop controller
mDragAndDropController.initialize(mSplitScreenOptional);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 620c382..4ff1ce9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -120,6 +120,16 @@
@Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer;
private final FloatingContentCoordinator mFloatingContentCoordinator;
private final BubbleDataRepository mDataRepository;
+ private final WindowManagerShellWrapper mWindowManagerShellWrapper;
+ private final LauncherApps mLauncherApps;
+ private final IStatusBarService mBarService;
+ private final WindowManager mWindowManager;
+ private final ShellTaskOrganizer mTaskOrganizer;
+
+ // Used to post to main UI thread
+ private final ShellExecutor mMainExecutor;
+ private final Handler mMainHandler;
+
private BubbleLogger mLogger;
private BubbleData mBubbleData;
private View mBubbleScrim;
@@ -148,12 +158,6 @@
*/
@Nullable private BubbleEntry mNotifEntryToExpandOnShadeUnlock;
- private IStatusBarService mBarService;
- private WindowManager mWindowManager;
-
- // Used to post to main UI thread
- private final ShellExecutor mMainExecutor;
-
/** LayoutParams used to add the BubbleStackView to the window manager. */
private WindowManager.LayoutParams mWmLayoutParams;
/** Whether or not the BubbleStackView has been added to the WindowManager. */
@@ -177,15 +181,6 @@
private boolean mInflateSynchronously;
- private ShellTaskOrganizer mTaskOrganizer;
-
- /**
- * Whether the IME is visible, as reported by the BubbleStackView. If it is, we'll make the
- * Bubbles window NOT_FOCUSABLE so that touches on the Bubbles UI doesn't steal focus from the
- * ActivityView and hide the IME.
- */
- private boolean mImeVisible = false;
-
/** true when user is in status bar unlock shade. */
private boolean mIsStatusBarShade = true;
@@ -231,13 +226,28 @@
ShellExecutor mainExecutor,
Handler mainHandler) {
mContext = context;
+ mLauncherApps = launcherApps;
+ mBarService = statusBarService == null
+ ? IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE))
+ : statusBarService;
+ mWindowManager = windowManager;
+ mWindowManagerShellWrapper = windowManagerShellWrapper;
mFloatingContentCoordinator = floatingContentCoordinator;
mDataRepository = dataRepository;
mLogger = bubbleLogger;
mMainExecutor = mainExecutor;
-
+ mMainHandler = mainHandler;
+ mTaskOrganizer = organizer;
+ mSurfaceSynchronizer = synchronizer;
+ mCurrentUserId = ActivityManager.getCurrentUser();
mBubblePositioner = positioner;
mBubbleData = data;
+ mSavedBubbleKeysPerUser = new SparseSetArray<>();
+ mBubbleIconFactory = new BubbleIconFactory(context);
+ }
+
+ public void initialize() {
mBubbleData.setListener(mBubbleDataListener);
mBubbleData.setSuppressionChangedListener(bubble -> {
// Make sure NoMan knows suppression state so that anyone querying it can tell.
@@ -261,28 +271,18 @@
});
try {
- windowManagerShellWrapper.addPinnedStackListener(new BubblesImeListener());
+ mWindowManagerShellWrapper.addPinnedStackListener(new BubblesImeListener());
} catch (RemoteException e) {
e.printStackTrace();
}
- mSurfaceSynchronizer = synchronizer;
- mWindowManager = windowManager;
- mBarService = statusBarService == null
- ? IStatusBarService.Stub.asInterface(
- ServiceManager.getService(Context.STATUS_BAR_SERVICE))
- : statusBarService;
- mSavedBubbleKeysPerUser = new SparseSetArray<>();
- mCurrentUserId = ActivityManager.getCurrentUser();
mBubbleData.setCurrentUserId(mCurrentUserId);
- mBubbleIconFactory = new BubbleIconFactory(context);
- mTaskOrganizer = organizer;
mTaskOrganizer.addLocusIdListener((taskId, locus, visible) ->
mBubbleData.onLocusVisibilityChanged(taskId, locus, visible));
- launcherApps.registerCallback(new LauncherApps.Callback() {
+ mLauncherApps.registerCallback(new LauncherApps.Callback() {
@Override
public void onPackageAdded(String s, UserHandle userHandle) {}
@@ -318,7 +318,7 @@
mBubbleData.removeBubblesWithInvalidShortcuts(
packageName, validShortcuts, DISMISS_SHORTCUT_REMOVED);
}
- }, mainHandler);
+ }, mMainHandler);
}
@VisibleForTesting
@@ -527,10 +527,6 @@
}
}
- void onImeVisibilityChanged(boolean imeVisible) {
- mImeVisible = imeVisible;
- }
-
/** Removes the BubbleStackView from the WindowManager if it's there. */
private void removeFromWindowManagerMaybe() {
if (!mAddedToWindowManager) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
index 2d9da21..fe3f9ef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
@@ -93,7 +93,7 @@
final float ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.importance_ring_stroke_width);
final int importantConversationColor = mContext.getResources().getColor(
- com.android.settingslib.R.color.important_conversation, null);
+ R.color.important_conversation, null);
Bitmap badgeAndRing = Bitmap.createBitmap(userBadgedBitmap.getWidth(),
userBadgedBitmap.getHeight(), userBadgedBitmap.getConfig());
Canvas c = new Canvas(badgeAndRing);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index e5c9e25..9eec48c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -876,8 +876,6 @@
mTaskbarScrim.setVisibility(GONE);
setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
- mBubbleController.onImeVisibilityChanged(
- insets.getInsets(WindowInsets.Type.ime()).bottom > 0);
if (!mIsExpanded || mIsExpansionAnimating) {
return view.onApplyWindowInsets(insets);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index bacff78..b64c796 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -27,9 +27,10 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Rect;
import android.view.SurfaceControl;
+import android.view.WindowInsets;
+import android.view.WindowManager;
import androidx.annotation.Nullable;
@@ -75,7 +76,7 @@
mDividerSize = mDividerWindowWidth - mDividerInsets * 2;
mRootBounds.set(configuration.windowConfiguration.getBounds());
- mDividerSnapAlgorithm = getSnapAlgorithm(context.getResources(), mRootBounds);
+ mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
resetDividerPosition();
}
@@ -114,7 +115,7 @@
mContext = mContext.createConfigurationContext(configuration);
mSplitWindowManager.setConfiguration(configuration);
mRootBounds.set(rootBounds);
- mDividerSnapAlgorithm = getSnapAlgorithm(mContext.getResources(), mRootBounds);
+ mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
resetDividerPosition();
// Don't inflate divider bar if it is not initialized.
@@ -217,15 +218,15 @@
return mDividerSnapAlgorithm.calculateSnapTarget(position, velocity, hardDismiss);
}
- private DividerSnapAlgorithm getSnapAlgorithm(Resources resources, Rect rootBounds) {
+ private DividerSnapAlgorithm getSnapAlgorithm(Context context, Rect rootBounds) {
final boolean isLandscape = isLandscape(rootBounds);
return new DividerSnapAlgorithm(
- resources,
+ context.getResources(),
rootBounds.width(),
rootBounds.height(),
mDividerSize,
!isLandscape,
- new Rect() /* insets */,
+ getDisplayInsets(context),
isLandscape ? DOCKED_LEFT : DOCKED_TOP /* dockSide */);
}
@@ -250,6 +251,15 @@
animator.start();
}
+ private static Rect getDisplayInsets(Context context) {
+ return context.getSystemService(WindowManager.class)
+ .getMaximumWindowMetrics()
+ .getWindowInsets()
+ .getInsets(WindowInsets.Type.navigationBars()
+ | WindowInsets.Type.statusBars()
+ | WindowInsets.Type.displayCutout()).toRect();
+ }
+
private static boolean isLandscape(Rect bounds) {
return bounds.width() > bounds.height();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
index f4c0f93..cf35656 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
@@ -67,7 +67,7 @@
final SurfaceSession mSurfaceSession = new SurfaceSession();
- private final SplitScreenTransitions mSplitTransitions;
+ private final LegacySplitScreenTransitions mSplitTransitions;
LegacySplitScreenTaskListener(LegacySplitScreenController splitScreenController,
ShellTaskOrganizer shellTaskOrganizer,
@@ -75,7 +75,7 @@
SyncTransactionQueue syncQueue) {
mSplitScreenController = splitScreenController;
mTaskOrganizer = shellTaskOrganizer;
- mSplitTransitions = new SplitScreenTransitions(splitScreenController.mTransactionPool,
+ mSplitTransitions = new LegacySplitScreenTransitions(splitScreenController.mTransactionPool,
transitions, mSplitScreenController, this);
transitions.addHandler(mSplitTransitions);
mSyncQueue = syncQueue;
@@ -112,7 +112,7 @@
return mTaskOrganizer;
}
- SplitScreenTransitions getSplitTransitions() {
+ LegacySplitScreenTransitions getSplitTransitions() {
return mSplitTransitions;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTransitions.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTransitions.java
index d06064a..27c56fd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTransitions.java
@@ -47,7 +47,7 @@
import java.util.ArrayList;
/** Plays transition animations for split-screen */
-public class SplitScreenTransitions implements Transitions.TransitionHandler {
+public class LegacySplitScreenTransitions implements Transitions.TransitionHandler {
private static final String TAG = "SplitScreenTransitions";
public static final int TRANSIT_SPLIT_DISMISS_SNAP = TRANSIT_FIRST_CUSTOM + 10;
@@ -68,7 +68,7 @@
private Transitions.TransitionFinishCallback mFinishCallback = null;
private SurfaceControl.Transaction mFinishTransaction;
- SplitScreenTransitions(@NonNull TransactionPool pool, @NonNull Transitions transitions,
+ LegacySplitScreenTransitions(@NonNull TransactionPool pool, @NonNull Transitions transitions,
@NonNull LegacySplitScreenController splitScreen,
@NonNull LegacySplitScreenTaskListener listener) {
mTransactionPool = pool;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 7965a80..8bbc35f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -403,9 +403,9 @@
}
private void updateDisplayLayout(int displayId) {
- mDisplayAreaOrganizer.setDisplayLayout(
- mDisplayController.getDisplayLayout(displayId));
- mGestureHandler.onDisplayChanged(mDisplayAreaOrganizer.getDisplayLayout());
+ final DisplayLayout newDisplayLayout = mDisplayController.getDisplayLayout(displayId);
+ mDisplayAreaOrganizer.setDisplayLayout(newDisplayLayout);
+ mGestureHandler.onDisplayChanged(newDisplayLayout);
}
private ContentObserver getObserver(Runnable onChangeRunnable) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
index 495362a..9e83a61 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
@@ -63,7 +63,7 @@
private boolean mIsEnabled;
private int mNavGestureHeight;
private boolean mIsThreeButtonModeEnabled;
- private int mRotation;
+ private int mRotation = Surface.ROTATION_0;
@VisibleForTesting
InputMonitor mInputMonitor;
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 fa31a0a..ffa821d 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
@@ -63,6 +63,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -131,7 +132,8 @@
private final PipAnimationController mPipAnimationController;
private final PipTransitionController mPipTransitionController;
private final PipUiEventLogger mPipUiEventLoggerLogger;
- private final int mEnterExitAnimationDuration;
+ private final int mEnterAnimationDuration;
+ private final int mExitAnimationDuration;
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private final Optional<LegacySplitScreenController> mSplitScreenOptional;
protected final ShellTaskOrganizer mTaskOrganizer;
@@ -225,8 +227,10 @@
mPipBoundsAlgorithm = boundsHandler;
mPipMenuController = pipMenuController;
mPipTransitionController = pipTransitionController;
- mEnterExitAnimationDuration = context.getResources()
- .getInteger(R.integer.config_pipResizeAnimationDuration);
+ mEnterAnimationDuration = context.getResources()
+ .getInteger(R.integer.config_pipEnterAnimationDuration);
+ mExitAnimationDuration = context.getResources()
+ .getInteger(R.integer.config_pipExitAnimationDuration);
mSurfaceTransactionHelper = surfaceTransactionHelper;
mPipAnimationController = pipAnimationController;
mPipUiEventLoggerLogger = pipUiEventLogger;
@@ -378,12 +382,13 @@
}
// removePipImmediately is expected when the following animation finishes.
- mPipAnimationController
+ ValueAnimator animator = mPipAnimationController
.getAnimator(mTaskInfo, mLeash, mPipBoundsState.getBounds(), 1f, 0f)
.setTransitionDirection(TRANSITION_DIRECTION_REMOVE_STACK)
- .setPipAnimationCallback(mPipAnimationCallback)
- .setDuration(mEnterExitAnimationDuration)
- .start();
+ .setPipAnimationCallback(mPipAnimationCallback);
+ animator.setDuration(mExitAnimationDuration);
+ animator.setInterpolator(Interpolators.ALPHA_OUT);
+ animator.start();
mState = State.EXITING_PIP;
}
@@ -465,11 +470,11 @@
final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
info.pictureInPictureParams, currentBounds);
scheduleAnimateResizePip(currentBounds, destinationBounds, 0 /* startingAngle */,
- sourceHintRect, TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
+ sourceHintRect, TRANSITION_DIRECTION_TO_PIP, mEnterAnimationDuration,
null /* updateBoundsCallback */);
mState = State.ENTERING_PIP;
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
- enterPipWithAlphaAnimation(destinationBounds, mEnterExitAnimationDuration);
+ enterPipWithAlphaAnimation(destinationBounds, mEnterAnimationDuration);
mOneShotAnimationType = ANIM_TYPE_BOUNDS;
} else {
throw new RuntimeException("Unrecognized animation type: " + mOneShotAnimationType);
@@ -553,7 +558,7 @@
*/
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
- if (!mState.isInPip()) {
+ if (mState == State.UNDEFINED) {
return;
}
final WindowContainerToken token = info.token;
@@ -596,7 +601,7 @@
final Rect destinationBounds = mPipBoundsAlgorithm.getAdjustedDestinationBounds(
mPipBoundsState.getBounds(), mPipBoundsState.getAspectRatio());
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
- scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration,
+ scheduleAnimateResizePip(destinationBounds, mEnterAnimationDuration,
null /* updateBoundsCallback */);
}
@@ -946,6 +951,7 @@
|| direction == TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND;
// Animate with a cross-fade if enabled and seamless resize is disables by the app.
final boolean animateCrossFadeResize = mayAnimateFinishResize
+ && mPictureInPictureParams != null
&& !mPictureInPictureParams.isSeamlessResizeEnabled();
if (animateCrossFadeResize) {
// Take a snapshot of the PIP task and hide it. We'll show it and fade it out after
@@ -965,7 +971,7 @@
mMainExecutor.execute(() -> {
// Start animation to fade out the snapshot.
final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f);
- animator.setDuration(mEnterExitAnimationDuration);
+ animator.setDuration(mEnterAnimationDuration);
animator.addUpdateListener(animation -> {
final float alpha = (float) animation.getAnimatedValue();
final SurfaceControl.Transaction transaction =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
index 580861c..65f3d3a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
@@ -244,9 +244,11 @@
*/
public void showMenuWithPossibleDelay(int menuState, Rect stackBounds, boolean allowMenuTimeout,
boolean willResizeMenu, boolean showResizeHandle) {
- // hide all visible controls including close button and etc. first, this is to ensure
- // menu is totally invisible during the transition to eliminate unpleasant artifacts
- fadeOutMenu();
+ if (willResizeMenu) {
+ // hide all visible controls including close button and etc. first, this is to ensure
+ // menu is totally invisible during the transition to eliminate unpleasant artifacts
+ fadeOutMenu();
+ }
showMenuInternal(menuState, stackBounds, allowMenuTimeout, willResizeMenu,
willResizeMenu /* withDelay=willResizeMenu here */, showResizeHandle);
}
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 debdceb..d75c1d6 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
@@ -24,7 +24,6 @@
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;
-import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.PictureInPictureParams;
@@ -55,11 +54,12 @@
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.common.ExecutorUtils;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.onehanded.OneHandedController;
+import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.pip.IPip;
import com.android.wm.shell.pip.IPipAnimationListener;
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
@@ -74,6 +74,7 @@
import java.io.PrintWriter;
import java.util.Objects;
+import java.util.Optional;
import java.util.function.Consumer;
/**
@@ -94,6 +95,7 @@
private PipBoundsState mPipBoundsState;
private PipTouchHandler mTouchHandler;
private PipTransitionController mPipTransitionController;
+ private Optional<OneHandedController> mOneHandedController;
protected final PipImpl mImpl;
private final Rect mTmpInsetBounds = new Rect();
@@ -239,7 +241,9 @@
PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer,
PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController,
WindowManagerShellWrapper windowManagerShellWrapper,
- TaskStackListenerImpl taskStackListener, ShellExecutor mainExecutor) {
+ TaskStackListenerImpl taskStackListener,
+ Optional<OneHandedController> oneHandedController,
+ ShellExecutor mainExecutor) {
if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
Slog.w(TAG, "Device doesn't support Pip feature");
return null;
@@ -248,7 +252,7 @@
return new PipController(context, displayController, pipAppOpsListener, pipBoundsAlgorithm,
pipBoundsState, pipMediaController, phonePipMenuController, pipTaskOrganizer,
pipTouchHandler, pipTransitionController, windowManagerShellWrapper,
- taskStackListener, mainExecutor)
+ taskStackListener, oneHandedController, mainExecutor)
.mImpl;
}
@@ -264,6 +268,7 @@
PipTransitionController pipTransitionController,
WindowManagerShellWrapper windowManagerShellWrapper,
TaskStackListenerImpl taskStackListener,
+ Optional<OneHandedController> oneHandedController,
ShellExecutor mainExecutor
) {
// Ensure that we are the primary user's SystemUI.
@@ -284,6 +289,7 @@
mMenuController = phonePipMenuController;
mTouchHandler = pipTouchHandler;
mAppOpsListener = pipAppOpsListener;
+ mOneHandedController = oneHandedController;
mPipTransitionController = pipTransitionController;
mPipInputConsumer = new PipInputConsumer(WindowManagerGlobal.getWindowManagerService(),
INPUT_CONSUMER_PIP, mainExecutor);
@@ -374,6 +380,21 @@
clearedTask /* skipAnimation */);
}
});
+
+ mOneHandedController.ifPresent(controller -> {
+ controller.asOneHanded().registerTransitionCallback(
+ new OneHandedTransitionCallback() {
+ @Override
+ public void onStartFinished(Rect bounds) {
+ mTouchHandler.setOhmOffset(bounds.top);
+ }
+
+ @Override
+ public void onStopFinished(Rect bounds) {
+ mTouchHandler.setOhmOffset(bounds.top);
+ }
+ });
+ });
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
index 8ab405b..1bfae53 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
@@ -76,7 +76,6 @@
private static final int INITIAL_DISMISS_DELAY = 3500;
private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
private static final long MENU_FADE_DURATION = 125;
- private static final long MENU_SLOW_FADE_DURATION = 175;
private static final long MENU_SHOW_ON_EXPAND_START_DELAY = 30;
private static final float MENU_BACKGROUND_ALPHA = 0.3f;
@@ -253,9 +252,7 @@
mMenuContainerAnimator.playTogether(dismissAnim, resizeAnim);
}
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
- mMenuContainerAnimator.setDuration(menuState == MENU_STATE_CLOSE
- ? MENU_FADE_DURATION
- : MENU_SLOW_FADE_DURATION);
+ mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
if (allowMenuTimeout) {
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index c726c01..adbd3b8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -108,7 +108,7 @@
// For pinch-resize
private boolean mThresholdCrossed0;
private boolean mThresholdCrossed1;
- private boolean mUsingPinchToZoom = true;
+ private boolean mOngoingPinchToResize = false;
private float mAngle = 0;
int mFirstIndex = -1;
int mSecondIndex = -1;
@@ -117,6 +117,7 @@
private InputEventReceiver mInputEventReceiver;
private int mCtrlType;
+ private int mOhmOffset;
public PipResizeGestureHandler(Context context, PipBoundsAlgorithm pipBoundsAlgorithm,
PipBoundsState pipBoundsState, PipMotionHelper motionHelper,
@@ -236,7 +237,7 @@
}
if (ev instanceof MotionEvent) {
- if (mUsingPinchToZoom) {
+ if (mOngoingPinchToResize) {
onPinchResize((MotionEvent) ev);
} else {
onDragCornerResize((MotionEvent) ev);
@@ -248,7 +249,7 @@
* Checks if there is currently an on-going gesture, either drag-resize or pinch-resize.
*/
public boolean hasOngoingGesture() {
- return mCtrlType != CTRL_NONE || mUsingPinchToZoom;
+ return mCtrlType != CTRL_NONE || mOngoingPinchToResize;
}
/**
@@ -305,7 +306,7 @@
case MotionEvent.ACTION_POINTER_DOWN:
if (mEnablePinchResize && ev.getPointerCount() == 2) {
onPinchResize(ev);
- mUsingPinchToZoom = true;
+ mOngoingPinchToResize = true;
return true;
}
break;
@@ -520,7 +521,7 @@
private void onDragCornerResize(MotionEvent ev) {
int action = ev.getActionMasked();
float x = ev.getX();
- float y = ev.getY();
+ float y = ev.getY() - mOhmOffset;
if (action == MotionEvent.ACTION_DOWN) {
final Rect currentPipBounds = mPipBoundsState.getBounds();
mLastResizeBounds.setEmpty();
@@ -587,7 +588,7 @@
// Pinch-to-resize needs to re-calculate snap fraction and animate to the snapped
// position correctly. Drag-resize does not need to move, so just finalize resize.
- if (mUsingPinchToZoom) {
+ if (mOngoingPinchToResize) {
final Rect startBounds = new Rect(mLastResizeBounds);
// If user resize is pretty close to max size, just auto resize to max.
if (mLastResizeBounds.width() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.x
@@ -612,7 +613,7 @@
private void resetState() {
mCtrlType = CTRL_NONE;
mAngle = 0;
- mUsingPinchToZoom = false;
+ mOngoingPinchToResize = false;
mAllowGesture = false;
mThresholdCrossed = false;
}
@@ -637,6 +638,10 @@
mMinSize.set(minX, minY);
}
+ void setOhmOffset(int offset) {
+ mOhmOffset = offset;
+ }
+
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
@@ -645,6 +650,7 @@
pw.println(innerPrefix + "mIsEnabled=" + mIsEnabled);
pw.println(innerPrefix + "mEnablePinchResize=" + mEnablePinchResize);
pw.println(innerPrefix + "mThresholdCrossed=" + mThresholdCrossed);
+ pw.println(innerPrefix + "mOhmOffset=" + mOhmOffset);
}
class PipResizeInputEventReceiver extends BatchedInputEventReceiver {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index b0a7319..75166b6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -1013,6 +1013,10 @@
: mPipBoundsState.getBounds();
}
+ void setOhmOffset(int offset) {
+ mPipResizeGestureHandler.setOhmOffset(offset);
+ }
+
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
index e7cd38f..01a81d2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
@@ -40,15 +40,17 @@
void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds,
WindowContainerTransaction wct) {
final WindowContainerToken rootToken = mRootTaskInfo.token;
- wct.setHidden(rootToken, false)
- .setBounds(rootToken, rootBounds)
+ wct.setBounds(rootToken, rootBounds)
.reparent(task.token, rootToken, true /* onTop*/)
// Moving the root task to top after the child tasks were repareted , or the root
// task cannot be visible and focused.
- .reorder(rootToken, true);
+ .reorder(rootToken, true /* onTop */);
}
boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
+ // No matter if the root task is empty or not, moving the root to bottom because it no
+ // longer preserves visible child task.
+ wct.reorder(mRootTaskInfo.token, false /* onTop */);
if (mChildrenTaskInfo.size() == 0) return false;
wct.reparentTasks(
mRootTaskInfo.token,
@@ -62,10 +64,7 @@
boolean removeTask(int taskId, WindowContainerToken newParent, WindowContainerTransaction wct) {
final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.get(taskId);
if (task == null) return false;
-
- wct.setHidden(mRootTaskInfo.token, true)
- .reorder(mRootTaskInfo.token, false)
- .reparent(task.token, newParent, false /* onTop */);
+ wct.reparent(task.token, newParent, false /* onTop */);
return true;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 55d0b7d..1302314 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -126,6 +126,7 @@
labelRes = app.labelRes;
}
+ final int taskId = taskInfo.taskId;
Context context = mContext;
// replace with the default theme if the application didn't set
final int theme = windowInfo.splashScreenThemeResId != 0
@@ -153,6 +154,7 @@
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Failed creating package context with package name "
+ activityInfo.packageName + " for user " + taskInfo.userId, e);
+ return;
}
}
@@ -167,15 +169,21 @@
final TypedArray typedArray = overrideContext.obtainStyledAttributes(
com.android.internal.R.styleable.Window);
final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
- if (resId != 0 && overrideContext.getDrawable(resId) != null) {
- // We want to use the windowBackground for the override context if it is
- // available, otherwise we use the default one to make sure a themed starting
- // window is displayed for the app.
- if (DEBUG_SPLASH_SCREEN) {
- Slog.d(TAG, "addSplashScreen: apply overrideConfig"
- + taskConfig + " to starting window resId=" + resId);
+ try {
+ if (resId != 0 && overrideContext.getDrawable(resId) != null) {
+ // We want to use the windowBackground for the override context if it is
+ // available, otherwise we use the default one to make sure a themed starting
+ // window is displayed for the app.
+ if (DEBUG_SPLASH_SCREEN) {
+ Slog.d(TAG, "addSplashScreen: apply overrideConfig"
+ + taskConfig + " to starting window resId=" + resId);
+ }
+ context = overrideContext;
}
- context = overrideContext;
+ } catch (Resources.NotFoundException e) {
+ Slog.w(TAG, "failed creating starting window for overrideConfig at taskId: "
+ + taskId, e);
+ return;
}
typedArray.recycle();
}
@@ -258,7 +266,6 @@
params.setTitle("Splash Screen " + activityInfo.packageName);
// TODO(b/173975965) tracking performance
- final int taskId = taskInfo.taskId;
SplashScreenView sView = null;
try {
final View view = win.getDecorView();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
new file mode 100644
index 0000000..71fd917
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.SurfaceControl;
+import android.window.IRemoteTransition;
+import android.window.IRemoteTransitionFinishedCallback;
+import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
+
+/**
+ * Handler that forwards to a RemoteTransition. It is designed for one-shot use to attach a
+ * specific remote animation to a specific transition.
+ */
+public class OneShotRemoteHandler implements Transitions.TransitionHandler {
+ private final ShellExecutor mMainExecutor;
+
+ /** The specific transition that this handler is associated with. Just for validation. */
+ private IBinder mTransition = null;
+
+ /** The remote to delegate animation to */
+ private final IRemoteTransition mRemote;
+
+ public OneShotRemoteHandler(@NonNull ShellExecutor mainExecutor,
+ @NonNull IRemoteTransition remote) {
+ mMainExecutor = mainExecutor;
+ mRemote = remote;
+ }
+
+ public void setTransition(@NonNull IBinder transition) {
+ mTransition = transition;
+ }
+
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction t,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ if (mTransition != transition) return false;
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Using registered One-shot remote"
+ + " transition %s for %s.", mRemote, transition);
+
+ final IBinder.DeathRecipient remoteDied = () -> {
+ Log.e(Transitions.TAG, "Remote transition died, finishing");
+ mMainExecutor.execute(
+ () -> finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */));
+ };
+ IRemoteTransitionFinishedCallback cb = new IRemoteTransitionFinishedCallback.Stub() {
+ @Override
+ public void onTransitionFinished(WindowContainerTransaction wct) {
+ if (mRemote.asBinder() != null) {
+ mRemote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */);
+ }
+ mMainExecutor.execute(
+ () -> finishCallback.onTransitionFinished(wct, null /* wctCB */));
+ }
+ };
+ try {
+ if (mRemote.asBinder() != null) {
+ mRemote.asBinder().linkToDeath(remoteDied, 0 /* flags */);
+ }
+ mRemote.startAnimation(info, t, cb);
+ } catch (RemoteException e) {
+ if (mRemote.asBinder() != null) {
+ mRemote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */);
+ }
+ Log.e(Transitions.TAG, "Error running remote transition.", e);
+ finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
+ }
+ return true;
+ }
+
+ @Override
+ @Nullable
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @Nullable TransitionRequestInfo request) {
+ IRemoteTransition remote = request.getRemoteTransition();
+ if (remote != mRemote) return null;
+ mTransition = transition;
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "RemoteTransition directly requested"
+ + " for %s: %s", transition, remote);
+ return new WindowContainerTransaction();
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
index 9667f4b..8876e5f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -84,12 +84,16 @@
}
void removeFiltered(IRemoteTransition remote) {
- remote.asBinder().unlinkToDeath(mTransitionDeathRecipient, 0 /* flags */);
+ boolean removed = false;
for (int i = mFilters.size() - 1; i >= 0; --i) {
if (mFilters.get(i).second == remote) {
mFilters.remove(i);
+ removed = true;
}
}
+ if (removed) {
+ remote.asBinder().unlinkToDeath(mTransitionDeathRecipient, 0 /* flags */);
+ }
}
@Override
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index 35bab7a..fcd333f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -73,7 +73,8 @@
fun FlickerTestParameter.appPairsPrimaryBoundsIsVisible(rotation: Int, primaryLayerName: String) {
assertLayersEnd {
val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
- this.coversExactly(getPrimaryRegion(dividerRegion, rotation), primaryLayerName)
+ visibleRegion(primaryLayerName)
+ .coversExactly(getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -83,7 +84,8 @@
) {
assertLayersEnd {
val dividerRegion = entry.getVisibleBounds(DOCKED_STACK_DIVIDER)
- this.coversExactly(getPrimaryRegion(dividerRegion, rotation), primaryLayerName)
+ visibleRegion(primaryLayerName)
+ .coversExactly(getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -93,7 +95,8 @@
) {
assertLayersEnd {
val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
- this.coversExactly(getSecondaryRegion(dividerRegion, rotation), secondaryLayerName)
+ visibleRegion(secondaryLayerName)
+ .coversExactly(getSecondaryRegion(dividerRegion, rotation))
}
}
@@ -103,7 +106,8 @@
) {
assertLayersEnd {
val dividerRegion = entry.getVisibleBounds(DOCKED_STACK_DIVIDER)
- this.coversExactly(getSecondaryRegion(dividerRegion, rotation), secondaryLayerName)
+ visibleRegion(secondaryLayerName)
+ .coversExactly(getSecondaryRegion(dividerRegion, rotation))
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
index 63e9a78..614530b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
@@ -82,10 +82,10 @@
fun appsEndingBounds() {
testSpec.assertLayersEnd {
val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
- this.coversExactly(appPairsHelper.getPrimaryBounds(dividerRegion),
- primaryApp.defaultWindowName)
- .coversExactly(appPairsHelper.getSecondaryBounds(dividerRegion),
- secondaryApp.defaultWindowName)
+ visibleRegion(primaryApp.defaultWindowName)
+ .coversExactly(appPairsHelper.getPrimaryBounds(dividerRegion))
+ visibleRegion(secondaryApp.defaultWindowName)
+ .coversExactly(appPairsHelper.getSecondaryBounds(dividerRegion))
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
index 234dda4..ef68ed6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
@@ -87,10 +87,10 @@
fun appsStartingBounds() {
testSpec.assertLayersStart {
val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
- coversExactly(appPairsHelper.getPrimaryBounds(dividerRegion),
- primaryApp.defaultWindowName)
- coversExactly(appPairsHelper.getSecondaryBounds(dividerRegion),
- secondaryApp.defaultWindowName)
+ visibleRegion(primaryApp.defaultWindowName)
+ .coversExactly(appPairsHelper.getPrimaryBounds(dividerRegion))
+ visibleRegion(secondaryApp.defaultWindowName)
+ .coversExactly(appPairsHelper.getSecondaryBounds(dividerRegion))
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
index 5a96a7c..f4dd7de 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
@@ -26,8 +26,6 @@
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.pip.tv.closeTvPipWindow
import com.android.wm.shell.flicker.pip.tv.isFocusedOrHasFocusedChild
-import com.android.wm.shell.flicker.pip.waitPipWindowGone
-import com.android.wm.shell.flicker.pip.waitPipWindowShown
import com.android.wm.shell.flicker.testapp.Components
class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
@@ -64,7 +62,7 @@
stringExtras: Map<String, String>
) {
super.launchViaIntent(wmHelper, expectedWindowName, action, stringExtras)
- wmHelper.waitPipWindowShown()
+ wmHelper.waitFor { it.wmState.hasPipWindow() }
}
private fun focusOnObject(selector: BySelector): Boolean {
@@ -86,7 +84,7 @@
clickObject(ENTER_PIP_BUTTON_ID)
// Wait on WMHelper or simply wait for 3 seconds
- wmHelper?.waitPipWindowShown() ?: SystemClock.sleep(3_000)
+ wmHelper?.waitFor { it.wmState.hasPipWindow() } ?: SystemClock.sleep(3_000)
}
fun clickStartMediaSessionButton() {
@@ -139,7 +137,7 @@
}
// Wait for animation to complete.
- wmHelper.waitPipWindowGone()
+ wmHelper.waitFor { !it.wmState.hasPipWindow() }
wmHelper.waitForHomeActivityVisible()
}
@@ -169,7 +167,7 @@
val windowRect = windowRegion.bounds
uiDevice.click(windowRect.centerX(), windowRect.centerY())
uiDevice.click(windowRect.centerX(), windowRect.centerY())
- wmHelper.waitPipWindowGone()
+ wmHelper.waitFor { !it.wmState.hasPipWindow() }
wmHelper.waitForAppTransitionIdle()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
index f40a08c..33ade38 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
@@ -183,8 +183,8 @@
dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
displayBounds.right,
displayBounds.bottom - WindowUtils.navigationBarHeight)
- this.coversExactly(topAppBounds, "SimpleActivity")
- .coversExactly(bottomAppBounds, "ImeActivity")
+ visibleRegion("SimpleActivity").coversExactly(topAppBounds)
+ visibleRegion("ImeActivity").coversExactly(bottomAppBounds)
}
}
@@ -203,8 +203,8 @@
displayBounds.right,
displayBounds.bottom - WindowUtils.navigationBarHeight)
- this.coversExactly(topAppBounds, sSimpleActivity)
- .coversExactly(bottomAppBounds, sImeActivity)
+ visibleRegion(sSimpleActivity).coversExactly(topAppBounds)
+ visibleRegion(sImeActivity).coversExactly(bottomAppBounds)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
index 0333227..1ba1f3b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
@@ -90,8 +90,8 @@
@Test
fun testAppCoversFullScreenWithPipOnDisplay() {
testSpec.assertLayersStart {
- coversExactly(displayBounds, testApp.defaultWindowName)
- coversAtMost(displayBounds, pipApp.defaultWindowName)
+ visibleRegion(testApp.defaultWindowName).coversExactly(displayBounds)
+ visibleRegion(pipApp.defaultWindowName).coversAtMost(displayBounds)
}
}
@@ -99,7 +99,7 @@
@Test
fun pipAppCoversFullScreen() {
testSpec.assertLayersEnd {
- coversExactly(displayBounds, pipApp.defaultWindowName)
+ visibleRegion(pipApp.defaultWindowName).coversExactly(displayBounds)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index ba88ee5..2beec2e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -75,7 +75,7 @@
// Enter PiP, and assert that the PiP is within bounds now that the device is back
// in portrait
broadcastActionTrigger.doAction(ACTION_ENTER_PIP)
- wmHelper.waitPipWindowShown()
+ wmHelper.waitFor { it.wmState.hasPipWindow() }
wmHelper.waitForAppTransitionIdle()
}
}
@@ -116,7 +116,7 @@
@Test
fun pipAppLayerHidesTestApp() {
testSpec.assertLayersStart {
- coversExactly(startingBounds, pipApp.defaultWindowName)
+ visibleRegion(pipApp.defaultWindowName).coversExactly(startingBounds)
isInvisible(testApp.defaultWindowName)
}
}
@@ -125,7 +125,7 @@
@Test
fun testAppLayerCoversFullScreen() {
testSpec.assertLayersEnd {
- coversExactly(endingBounds, testApp.defaultWindowName)
+ visibleRegion(testApp.defaultWindowName).coversExactly(endingBounds)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
index 96eb66c..0037059 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
@@ -16,62 +16,14 @@
package com.android.wm.shell.flicker.pip
-import android.app.WindowConfiguration
import android.content.ComponentName
-import com.android.server.wm.flicker.traces.windowmanager.WindowManagerStateSubject
import com.android.server.wm.traces.common.windowmanager.WindowManagerState
import com.android.server.wm.traces.parser.toWindowName
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
-import com.google.common.truth.Truth
-
-inline val WindowManagerState.pinnedWindows
- get() = visibleWindows
- .filter { it.windowingMode == WindowConfiguration.WINDOWING_MODE_PINNED }
-
-/**
- * Checks if the state has any window in PIP mode
- */
-fun WindowManagerState.hasPipWindow(): Boolean = pinnedWindows.isNotEmpty()
/**
* Checks that an activity [activity] is in PIP mode
*/
fun WindowManagerState.isInPipMode(activity: ComponentName): Boolean {
val windowName = activity.toWindowName()
- return pinnedWindows.any { it.title == windowName }
+ return isInPipMode(windowName)
}
-
-/**
- * Asserts that an activity [activity] exists and is in PIP mode
- */
-fun WindowManagerStateSubject.isInPipMode(
- activity: ComponentName
-): WindowManagerStateSubject = apply {
- val windowName = activity.toWindowName()
- contains(windowName)
- val pinnedWindows = wmState.pinnedWindows
- .map { it.title }
- Truth.assertWithMessage("Window not in PIP mode")
- .that(pinnedWindows)
- .contains(windowName)
-}
-
-/**
- * Waits until the state has a window in PIP mode, i.e., with
- * windowingMode = WindowConfiguration.WINDOWING_MODE_PINNED
- */
-fun WindowManagerStateHelper.waitPipWindowShown(): Boolean =
- waitFor("PIP window shown") {
- val result = it.wmState.hasPipWindow()
- result
- }
-
-/**
- * Waits until the state doesn't have a window in PIP mode, i.e., with
- * windowingMode = WindowConfiguration.WINDOWING_MODE_PINNED
- */
-fun WindowManagerStateHelper.waitPipWindowGone(): Boolean =
- waitFor("PIP window gone") {
- val result = !it.wmState.hasPipWindow()
- result
- }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index bf148bc..6166721 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -116,8 +116,8 @@
@Test
fun bothAppLayersVisible() {
testSpec.assertLayersEnd {
- coversAtMost(displayBounds, testApp.defaultWindowName)
- coversAtMost(displayBounds, imeApp.defaultWindowName)
+ visibleRegion(testApp.defaultWindowName).coversAtMost(displayBounds)
+ visibleRegion(imeApp.defaultWindowName).coversAtMost(displayBounds)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt
index f554ca3..5713822b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt
@@ -18,6 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.view.Surface
+import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -63,11 +64,11 @@
@Test
fun pipLayerInsideDisplay() {
testSpec.assertLayersStart {
- coversAtMost(displayBounds, pipApp.defaultWindowName)
+ visibleRegion(pipApp.defaultWindowName).coversAtMost(displayBounds)
}
}
- @Presubmit
+ @FlakyTest(bugId = 184050344)
@Test
fun pipWindowMovesUp() = testSpec.assertWmEnd {
val initialState = this.trace?.first()?.wmState
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index 8ceef8a..852ee47 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -26,11 +26,11 @@
import com.android.server.wm.flicker.endRotation
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.startRotation
-import com.android.wm.shell.flicker.helpers.FixedAppHelper
-import com.android.server.wm.flicker.noUncoveredRegions
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.startRotation
import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.wm.shell.flicker.helpers.FixedAppHelper
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -91,8 +91,8 @@
@Test
fun appLayerRotates_StartingBounds() {
testSpec.assertLayersStart {
- coversExactly(startingBounds, fixedApp.defaultWindowName)
- coversAtMost(startingBounds, pipApp.defaultWindowName)
+ visibleRegion(fixedApp.defaultWindowName).coversExactly(startingBounds)
+ visibleRegion(pipApp.defaultWindowName).coversAtMost(startingBounds)
}
}
@@ -100,8 +100,8 @@
@Test
fun appLayerRotates_EndingBounds() {
testSpec.assertLayersEnd {
- coversExactly(endingBounds, fixedApp.defaultWindowName)
- coversAtMost(endingBounds, pipApp.defaultWindowName)
+ visibleRegion(fixedApp.defaultWindowName).coversExactly(endingBounds)
+ visibleRegion(pipApp.defaultWindowName).coversAtMost(endingBounds)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
index 945a20b..6f17a2c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
@@ -83,7 +83,7 @@
@Test
fun testAppCoversFullScreen() {
testSpec.assertLayersStart {
- coversExactly(displayBounds, pipApp.defaultWindowName)
+ visibleRegion(pipApp.defaultWindowName).coversExactly(displayBounds)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
index 7dc7e7d..f885682 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
@@ -131,13 +131,13 @@
removeAllTasksButHome()
if (!eachRun) {
pipApp.launchViaIntent(wmHelper, stringExtras = stringExtras)
- wmHelper.waitPipWindowShown()
+ wmHelper.waitFor { it.wmState.hasPipWindow() }
}
}
eachRun {
if (eachRun) {
pipApp.launchViaIntent(wmHelper, stringExtras = stringExtras)
- wmHelper.waitPipWindowShown()
+ wmHelper.waitFor { it.wmState.hasPipWindow() }
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
index 102af92..9aab7f3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
@@ -91,7 +91,7 @@
@Test
fun pipWindowInsideDisplay() {
testSpec.assertWmStart {
- coversAtMost(startingBounds, pipApp.defaultWindowName)
+ frameRegion(pipApp.defaultWindowName).coversAtMost(startingBounds)
}
}
@@ -107,7 +107,7 @@
@Test
fun pipLayerInsideDisplay() {
testSpec.assertLayersStart {
- coversAtMost(startingBounds, pipApp.defaultWindowName)
+ visibleRegion(pipApp.defaultWindowName).coversAtMost(startingBounds)
}
}
@@ -121,7 +121,7 @@
@Test
fun pipAppLayerCoversFullScreen() {
testSpec.assertLayersEnd {
- coversExactly(endingBounds, pipApp.defaultWindowName)
+ visibleRegion(pipApp.defaultWindowName).coversExactly(endingBounds)
}
}
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 f2b4e97..700bf78 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
@@ -42,6 +42,7 @@
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipMediaController;
@@ -54,6 +55,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Optional;
+
/**
* Unit tests for {@link PipController}
*/
@@ -75,6 +78,7 @@
@Mock private PipBoundsState mMockPipBoundsState;
@Mock private TaskStackListenerImpl mMockTaskStackListener;
@Mock private ShellExecutor mMockExecutor;
+ @Mock private Optional<OneHandedController> mMockOneHandedController;
@Before
public void setUp() throws RemoteException {
@@ -83,7 +87,7 @@
mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipBoundsState,
mMockPipMediaController, mMockPhonePipMenuController, mMockPipTaskOrganizer,
mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper,
- mMockTaskStackListener, mMockExecutor);
+ mMockTaskStackListener, mMockOneHandedController, mMockExecutor);
doAnswer(invocation -> {
((Runnable) invocation.getArgument(0)).run();
return null;
@@ -116,7 +120,7 @@
mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipBoundsState,
mMockPipMediaController, mMockPhonePipMenuController, mMockPipTaskOrganizer,
mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper,
- mMockTaskStackListener, mMockExecutor));
+ mMockTaskStackListener, mMockOneHandedController, mMockExecutor));
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 8ae0a73..78b3d4e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -112,7 +112,8 @@
spyOn(context);
spyOn(realWindowManager);
try {
- doReturn(context).when(context).createPackageContext(anyString(), anyInt());
+ doReturn(context).when(context)
+ .createPackageContextAsUser(anyString(), anyInt(), any());
} catch (PackageManager.NameNotFoundException e) {
//
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index 926108c..c1733de 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -22,6 +22,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_FIRST_CUSTOM;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -30,6 +31,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -295,6 +298,44 @@
verify(mOrganizer, times(1)).finishTransition(eq(transitToken), any(), any());
}
+ @Test
+ public void testOneShotRemoteHandler() {
+ Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
+ mMainExecutor, mAnimExecutor);
+ transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+ final boolean[] remoteCalled = new boolean[]{false};
+ final WindowContainerTransaction remoteFinishWCT = new WindowContainerTransaction();
+ IRemoteTransition testRemote = new IRemoteTransition.Stub() {
+ @Override
+ public void startAnimation(TransitionInfo info, SurfaceControl.Transaction t,
+ IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
+ remoteCalled[0] = true;
+ finishCallback.onTransitionFinished(remoteFinishWCT);
+ }
+ };
+
+ final int transitType = TRANSIT_FIRST_CUSTOM + 1;
+
+ OneShotRemoteHandler oneShot = new OneShotRemoteHandler(mMainExecutor, testRemote);
+ // Verify that it responds to the remote but not other things.
+ IBinder transitToken = new Binder();
+ assertNotNull(oneShot.handleRequest(transitToken,
+ new TransitionRequestInfo(transitType, null, testRemote)));
+ assertNull(oneShot.handleRequest(transitToken,
+ new TransitionRequestInfo(transitType, null, null)));
+
+ Transitions.TransitionFinishCallback testFinish =
+ mock(Transitions.TransitionFinishCallback.class);
+ // Verify that it responds to animation properly
+ oneShot.setTransition(transitToken);
+ IBinder anotherToken = new Binder();
+ assertFalse(oneShot.startAnimation(anotherToken, new TransitionInfo(transitType, 0),
+ mock(SurfaceControl.Transaction.class), testFinish));
+ assertTrue(oneShot.startAnimation(transitToken, new TransitionInfo(transitType, 0),
+ mock(SurfaceControl.Transaction.class), testFinish));
+ }
+
class TransitionInfoBuilder {
final TransitionInfo mInfo;
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 168a863..1e90b7c 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1379,6 +1379,11 @@
enum : uint32_t {
// Additional flag indicating an entry is public.
SPEC_PUBLIC = 0x40000000u,
+
+ // Additional flag indicating the resource id for this resource may change in a future
+ // build. If this flag is set, the SPEC_PUBLIC flag is also set since the resource must be
+ // public to be exposed as an API to other applications.
+ SPEC_STAGED_API = 0x20000000u,
};
};
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index b51777c..822d22b 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -4499,14 +4499,25 @@
int i = 0;
for (final String key: params.keySet()) {
- keys[i] = key;
- Object value = params.get(key);
-
- // Bundle's byte array is a byte[], JNI layer only takes ByteBuffer
- if (value instanceof byte[]) {
- values[i] = ByteBuffer.wrap((byte[])value);
+ if (key.equals(MediaFormat.KEY_AUDIO_SESSION_ID)) {
+ int sessionId = 0;
+ try {
+ sessionId = (Integer)params.get(key);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Wrong Session ID Parameter!");
+ }
+ keys[i] = "audio-hw-sync";
+ values[i] = AudioSystem.getAudioHwSyncForSession(sessionId);
} else {
- values[i] = value;
+ keys[i] = key;
+ Object value = params.get(key);
+
+ // Bundle's byte array is a byte[], JNI layer only takes ByteBuffer
+ if (value instanceof byte[]) {
+ values[i] = ByteBuffer.wrap((byte[])value);
+ } else {
+ values[i] = value;
+ }
}
++i;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
index de353bf..a0d4492 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
@@ -24,8 +24,10 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.AttributionSource;
import android.content.ContentProviderClient;
import android.content.ContentValues;
+import android.content.Context;
import android.content.IContentProvider;
import android.media.MediaInserter;
import android.net.Uri;
@@ -46,7 +48,7 @@
private MediaInserter mMediaInserter;
private static final int TEST_BUFFER_SIZE = 10;
private @Mock IContentProvider mMockProvider;
- private String mPackageName;
+ private AttributionSource mAttributionSource;
private int mFilesCounter;
private int mAudioCounter;
@@ -86,11 +88,14 @@
super.setUp();
MockitoAnnotations.initMocks(this);
- final ContentProviderClient client = new ContentProviderClient(
- getInstrumentation().getContext().createFeatureContext(TEST_FEATURE_ID)
+ final Context attributionContext = getInstrumentation().getContext()
+ .createFeatureContext(TEST_FEATURE_ID);
+
+ final ContentProviderClient client = new ContentProviderClient(attributionContext
.getContentResolver(), mMockProvider, true);
+
mMediaInserter = new MediaInserter(client, TEST_BUFFER_SIZE);
- mPackageName = getInstrumentation().getContext().getPackageName();
+ mAttributionSource = attributionContext.getAttributionSource();
mFilesCounter = 0;
mAudioCounter = 0;
mVideoCounter = 0;
@@ -144,13 +149,13 @@
fillBuffer(sVideoUri, TEST_BUFFER_SIZE - 2);
fillBuffer(sImagesUri, TEST_BUFFER_SIZE - 1);
- verify(mMockProvider, never()).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ verify(mMockProvider, never()).bulkInsert(eq(mAttributionSource), any(),
any());
}
@SmallTest
public void testInsertContentsEqualToBufferSize() throws Exception {
- when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ when(mMockProvider.bulkInsert(eq(mAttributionSource), any(),
any())).thenReturn(1);
fillBuffer(sFilesUri, TEST_BUFFER_SIZE);
@@ -158,13 +163,13 @@
fillBuffer(sVideoUri, TEST_BUFFER_SIZE);
fillBuffer(sImagesUri, TEST_BUFFER_SIZE);
- verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ verify(mMockProvider, times(4)).bulkInsert(eq(mAttributionSource), any(),
any());
}
@SmallTest
public void testInsertContentsMoreThanBufferSize() throws Exception {
- when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ when(mMockProvider.bulkInsert(eq(mAttributionSource), any(),
any())).thenReturn(1);
fillBuffer(sFilesUri, TEST_BUFFER_SIZE + 1);
@@ -172,7 +177,7 @@
fillBuffer(sVideoUri, TEST_BUFFER_SIZE + 3);
fillBuffer(sImagesUri, TEST_BUFFER_SIZE + 4);
- verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ verify(mMockProvider, times(4)).bulkInsert(eq(mAttributionSource), any(),
any());
}
@@ -183,7 +188,7 @@
@SmallTest
public void testFlushAllWithSomeContents() throws Exception {
- when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ when(mMockProvider.bulkInsert(eq(mAttributionSource), any(),
any())).thenReturn(1);
fillBuffer(sFilesUri, TEST_BUFFER_SIZE - 4);
@@ -192,13 +197,13 @@
fillBuffer(sImagesUri, TEST_BUFFER_SIZE - 1);
mMediaInserter.flushAll();
- verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ verify(mMockProvider, times(4)).bulkInsert(eq(mAttributionSource), any(),
any());
}
@SmallTest
public void testInsertContentsAfterFlushAll() throws Exception {
- when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ when(mMockProvider.bulkInsert(eq(mAttributionSource), any(),
any())).thenReturn(1);
fillBuffer(sFilesUri, TEST_BUFFER_SIZE - 4);
@@ -212,19 +217,19 @@
fillBuffer(sVideoUri, TEST_BUFFER_SIZE + 3);
fillBuffer(sImagesUri, TEST_BUFFER_SIZE + 4);
- verify(mMockProvider, times(8)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ verify(mMockProvider, times(8)).bulkInsert(eq(mAttributionSource), any(),
any());
}
@SmallTest
public void testInsertContentsWithDifferentSizePerContentType() throws Exception {
- when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sFilesUri),
+ when(mMockProvider.bulkInsert(eq(mAttributionSource), eqUri(sFilesUri),
any())).thenReturn(1);
- when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sAudioUri),
+ when(mMockProvider.bulkInsert(eq(mAttributionSource), eqUri(sAudioUri),
any())).thenReturn(1);
- when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sVideoUri),
+ when(mMockProvider.bulkInsert(eq(mAttributionSource), eqUri(sVideoUri),
any())).thenReturn(1);
- when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sImagesUri),
+ when(mMockProvider.bulkInsert(eq(mAttributionSource), eqUri(sImagesUri),
any())).thenReturn(1);
for (int i = 0; i < TEST_BUFFER_SIZE; ++i) {
@@ -234,13 +239,13 @@
fillBuffer(sImagesUri, 4);
}
- verify(mMockProvider, times(1)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+ verify(mMockProvider, times(1)).bulkInsert(eq(mAttributionSource),
eqUri(sFilesUri), any());
- verify(mMockProvider, times(2)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+ verify(mMockProvider, times(2)).bulkInsert(eq(mAttributionSource),
eqUri(sAudioUri), any());
- verify(mMockProvider, times(3)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+ verify(mMockProvider, times(3)).bulkInsert(eq(mAttributionSource),
eqUri(sVideoUri), any());
- verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+ verify(mMockProvider, times(4)).bulkInsert(eq(mAttributionSource),
eqUri(sImagesUri), any());
}
}
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index 3af66260..5967e63 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4470785958457506021">"ניהול מכשיר מותאם"</string>
- <string name="chooser_title" msgid="2262294130493605839">"בחירה של <xliff:g id="PROFILE_NAME">%1$s</xliff:g> לניהול באמצעות <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
+ <string name="chooser_title" msgid="2262294130493605839">"בחירת <xliff:g id="PROFILE_NAME">%1$s</xliff:g> לניהול באמצעות <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"מכשיר"</string>
<string name="profile_name_watch" msgid="576290739483672360">"שעון"</string>
<string name="confirmation_title" msgid="8455544820286920304">"אישור לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לנהל את <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt
index 0a9560a..7428c6e 100644
--- a/packages/Connectivity/framework/api/current.txt
+++ b/packages/Connectivity/framework/api/current.txt
@@ -311,6 +311,7 @@
field public static final int NET_CAPABILITY_ENTERPRISE = 29; // 0x1d
field public static final int NET_CAPABILITY_FOREGROUND = 19; // 0x13
field public static final int NET_CAPABILITY_FOTA = 3; // 0x3
+ field public static final int NET_CAPABILITY_HEAD_UNIT = 32; // 0x20
field public static final int NET_CAPABILITY_IA = 7; // 0x7
field public static final int NET_CAPABILITY_IMS = 4; // 0x4
field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc
@@ -334,6 +335,7 @@
field public static final int TRANSPORT_CELLULAR = 0; // 0x0
field public static final int TRANSPORT_ETHERNET = 3; // 0x3
field public static final int TRANSPORT_LOWPAN = 6; // 0x6
+ field public static final int TRANSPORT_USB = 8; // 0x8
field public static final int TRANSPORT_VPN = 4; // 0x4
field public static final int TRANSPORT_WIFI = 1; // 0x1
field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index 970a236..2065559 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -179,10 +179,12 @@
}
public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo {
- ctor public VpnTransportInfo(int);
+ ctor public VpnTransportInfo(int, @Nullable String);
method public int describeContents();
+ method @NonNull public android.net.VpnTransportInfo makeCopy(long);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnTransportInfo> CREATOR;
+ field @Nullable public final String sessionId;
field public final int type;
}
diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt
index 95df8b8..6c3b620 100644
--- a/packages/Connectivity/framework/api/system-current.txt
+++ b/packages/Connectivity/framework/api/system-current.txt
@@ -219,7 +219,7 @@
method public void onAutomaticReconnectDisabled();
method public void onBandwidthUpdateRequested();
method public void onNetworkCreated();
- method public void onNetworkDisconnected();
+ method public void onNetworkDestroyed();
method public void onNetworkUnwanted();
method public void onQosCallbackRegistered(int, @NonNull android.net.QosFilter);
method public void onQosCallbackUnregistered(int);
@@ -238,6 +238,7 @@
method public final void sendQosSessionLost(int, int, int);
method public final void sendSocketKeepaliveEvent(int, int);
method @Deprecated public void setLegacySubtype(int, @NonNull String);
+ method public void setTeardownDelayMs(@IntRange(from=0, to=0x1388) int);
method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
method public void unregister();
field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index 3939c7f..350b47f 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -924,6 +924,7 @@
BLOCKED_REASON_DOZE,
BLOCKED_REASON_APP_STANDBY,
BLOCKED_REASON_RESTRICTED_MODE,
+ BLOCKED_REASON_LOCKDOWN_VPN,
BLOCKED_METERED_REASON_DATA_SAVER,
BLOCKED_METERED_REASON_USER_RESTRICTED,
BLOCKED_METERED_REASON_ADMIN_DISABLED,
@@ -3715,7 +3716,8 @@
public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {}
/**
- * Called when access to the specified network is blocked or unblocked.
+ * Called when access to the specified network is blocked or unblocked, or the reason for
+ * access being blocked changes.
*
* If a NetworkCallback object implements this method,
* {@link #onBlockedStatusChanged(Network, boolean)} will not be called.
diff --git a/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl b/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl
index f9d3994..d941d4b 100644
--- a/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl
+++ b/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl
@@ -47,5 +47,5 @@
void onQosFilterCallbackRegistered(int qosCallbackId, in QosFilterParcelable filterParcel);
void onQosCallbackUnregistered(int qosCallbackId);
void onNetworkCreated();
- void onNetworkDisconnected();
+ void onNetworkDestroyed();
}
diff --git a/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl b/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl
index cbd6193..26cb1ed 100644
--- a/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl
+++ b/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl
@@ -41,4 +41,5 @@
void sendNrQosSessionAvailable(int callbackId, in QosSession session, in NrQosSessionAttributes attributes);
void sendQosSessionLost(int qosCallbackId, in QosSession session);
void sendQosCallbackError(int qosCallbackId, int exceptionType);
+ void sendTeardownDelayMs(int teardownDelayMs);
}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgent.java b/packages/Connectivity/framework/src/android/net/NetworkAgent.java
index 6b55bb7..c57da53 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkAgent.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkAgent.java
@@ -185,6 +185,20 @@
public static final int EVENT_UNDERLYING_NETWORKS_CHANGED = BASE + 5;
/**
+ * Sent by the NetworkAgent to ConnectivityService to pass the current value of the teardown
+ * delay.
+ * arg1 = teardown delay in milliseconds
+ * @hide
+ */
+ public static final int EVENT_TEARDOWN_DELAY_CHANGED = BASE + 6;
+
+ /**
+ * The maximum value for the teardown delay, in milliseconds.
+ * @hide
+ */
+ public static final int MAX_TEARDOWN_DELAY_MS = 5000;
+
+ /**
* Sent by ConnectivityService to the NetworkAgent to inform the agent of the
* networks status - whether we could use the network or could not, due to
* either a bad network configuration (no internet link) or captive portal.
@@ -197,7 +211,6 @@
*/
public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7;
-
/**
* Network validation suceeded.
* Corresponds to {@link NetworkCapabilities.NET_CAPABILITY_VALIDATED}.
@@ -376,7 +389,7 @@
*
* @hide
*/
- public static final int CMD_NETWORK_DISCONNECTED = BASE + 23;
+ public static final int CMD_NETWORK_DESTROYED = BASE + 23;
private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType,
@@ -581,8 +594,8 @@
onNetworkCreated();
break;
}
- case CMD_NETWORK_DISCONNECTED: {
- onNetworkDisconnected();
+ case CMD_NETWORK_DESTROYED: {
+ onNetworkDestroyed();
break;
}
}
@@ -732,8 +745,8 @@
}
@Override
- public void onNetworkDisconnected() {
- mHandler.sendMessage(mHandler.obtainMessage(CMD_NETWORK_DISCONNECTED));
+ public void onNetworkDestroyed() {
+ mHandler.sendMessage(mHandler.obtainMessage(CMD_NETWORK_DESTROYED));
}
}
@@ -851,6 +864,29 @@
}
/**
+ * Sets the value of the teardown delay.
+ *
+ * The teardown delay is the time between when the network disconnects and when the native
+ * network corresponding to this {@code NetworkAgent} is destroyed. By default, the native
+ * network is destroyed immediately. If {@code teardownDelayMs} is non-zero, then when this
+ * network disconnects, the system will instead immediately mark the network as restricted
+ * and unavailable to unprivileged apps, but will defer destroying the native network until the
+ * teardown delay timer expires.
+ *
+ * The interfaces in use by this network will remain in use until the native network is
+ * destroyed and cannot be reused until {@link #onNetworkDestroyed()} is called.
+ *
+ * This method may be called at any time while the network is connected. It has no effect if
+ * the network is already disconnected and the teardown delay timer is running.
+ *
+ * @param teardownDelayMs the teardown delay to set, or 0 to disable teardown delay.
+ */
+ public void setTeardownDelayMs(
+ @IntRange(from = 0, to = MAX_TEARDOWN_DELAY_MS) int teardownDelayMs) {
+ queueOrSendMessage(reg -> reg.sendTeardownDelayMs(teardownDelayMs));
+ }
+
+ /**
* Change the legacy subtype of this network agent.
*
* This is only for backward compatibility and should not be used by non-legacy network agents,
@@ -1053,7 +1089,7 @@
/**
* Called when ConnectivityService has successfully destroy this NetworkAgent's native network.
*/
- public void onNetworkDisconnected() {}
+ public void onNetworkDestroyed() {}
/**
* Requests that the network hardware send the specified packet at the specified interval.
diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
index ca69f16..4f95ccc 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
@@ -275,6 +275,7 @@
NET_CAPABILITY_ENTERPRISE,
NET_CAPABILITY_VSIM,
NET_CAPABILITY_BIP,
+ NET_CAPABILITY_HEAD_UNIT,
})
public @interface NetCapability { }
@@ -508,8 +509,13 @@
@SystemApi
public static final int NET_CAPABILITY_BIP = 31;
+ /**
+ * Indicates that this network is connected to an automotive head unit.
+ */
+ public static final int NET_CAPABILITY_HEAD_UNIT = 32;
+
private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
- private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_BIP;
+ private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_HEAD_UNIT;
/**
* Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -527,7 +533,10 @@
| (1 << NET_CAPABILITY_NOT_SUSPENDED)
| (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY)
| (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED)
- | (1 << NET_CAPABILITY_NOT_VCN_MANAGED);
+ | (1 << NET_CAPABILITY_NOT_VCN_MANAGED)
+ // The value of NET_CAPABILITY_HEAD_UNIT is 32, which cannot use int to do bit shift,
+ // otherwise there will be an overflow. Use long to do bit shift instead.
+ | (1L << NET_CAPABILITY_HEAD_UNIT);
/**
* Network capabilities that are not allowed in NetworkRequests. This exists because the
@@ -867,6 +876,7 @@
TRANSPORT_WIFI_AWARE,
TRANSPORT_LOWPAN,
TRANSPORT_TEST,
+ TRANSPORT_USB,
})
public @interface Transport { }
@@ -913,10 +923,15 @@
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int TRANSPORT_TEST = 7;
+ /**
+ * Indicates this network uses a USB transport.
+ */
+ public static final int TRANSPORT_USB = 8;
+
/** @hide */
public static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
/** @hide */
- public static final int MAX_TRANSPORT = TRANSPORT_TEST;
+ public static final int MAX_TRANSPORT = TRANSPORT_USB;
/** @hide */
public static boolean isValidTransport(@Transport int transportType) {
@@ -931,7 +946,8 @@
"VPN",
"WIFI_AWARE",
"LOWPAN",
- "TEST"
+ "TEST",
+ "USB"
};
/**
@@ -2107,6 +2123,7 @@
case NET_CAPABILITY_ENTERPRISE: return "ENTERPRISE";
case NET_CAPABILITY_VSIM: return "VSIM";
case NET_CAPABILITY_BIP: return "BIP";
+ case NET_CAPABILITY_HEAD_UNIT: return "HEAD_UNIT";
default: return Integer.toString(capability);
}
}
diff --git a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
index cd8f4c0..ba83a44 100644
--- a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
+++ b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
@@ -17,11 +17,14 @@
package android.net;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import java.util.Objects;
@@ -38,8 +41,26 @@
/** Type of this VPN. */
public final int type;
- public VpnTransportInfo(int type) {
+ @Nullable
+ public final String sessionId;
+
+ @Override
+ public long getApplicableRedactions() {
+ return REDACT_FOR_NETWORK_SETTINGS;
+ }
+
+ /**
+ * Create a copy of a {@link VpnTransportInfo} with the sessionId redacted if necessary.
+ */
+ @NonNull
+ public VpnTransportInfo makeCopy(long redactions) {
+ return new VpnTransportInfo(type,
+ ((redactions & REDACT_FOR_NETWORK_SETTINGS) != 0) ? null : sessionId);
+ }
+
+ public VpnTransportInfo(int type, @Nullable String sessionId) {
this.type = type;
+ this.sessionId = sessionId;
}
@Override
@@ -47,17 +68,17 @@
if (!(o instanceof VpnTransportInfo)) return false;
VpnTransportInfo that = (VpnTransportInfo) o;
- return this.type == that.type;
+ return (this.type == that.type) && TextUtils.equals(this.sessionId, that.sessionId);
}
@Override
public int hashCode() {
- return Objects.hash(type);
+ return Objects.hash(type, sessionId);
}
@Override
public String toString() {
- return String.format("VpnTransportInfo{type=%d}", type);
+ return String.format("VpnTransportInfo{type=%d, sessionId=%s}", type, sessionId);
}
@Override
@@ -68,12 +89,13 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(type);
+ dest.writeString(sessionId);
}
public static final @NonNull Creator<VpnTransportInfo> CREATOR =
new Creator<VpnTransportInfo>() {
public VpnTransportInfo createFromParcel(Parcel in) {
- return new VpnTransportInfo(in.readInt());
+ return new VpnTransportInfo(in.readInt(), in.readString());
}
public VpnTransportInfo[] newArray(int size) {
return new VpnTransportInfo[size];
diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp
index b44128b..518f198 100644
--- a/packages/Connectivity/service/Android.bp
+++ b/packages/Connectivity/service/Android.bp
@@ -72,7 +72,7 @@
"ServiceConnectivityResources",
],
static_libs: [
- "dnsresolver_aidl_interface-V7-java",
+ "dnsresolver_aidl_interface-V8-java",
"modules-utils-os",
"net-utils-device-common",
"net-utils-framework-common",
diff --git a/packages/DynamicSystemInstallationService/res/values-nl/strings.xml b/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
index 3bf7247..5babf32 100644
--- a/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
@@ -13,5 +13,5 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Herstarten"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamisch systeem niet opgeslagen"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Kan dynamisch systeem niet opnieuw opstarten of laden"</string>
- <string name="toast_failed_to_disable_dynsystem" msgid="3285742944977744413">"Kan dynamisch systeem niet uitschakelen"</string>
+ <string name="toast_failed_to_disable_dynsystem" msgid="3285742944977744413">"Kan dynamisch systeem niet uitzetten"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 087275e..801b490 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.usage.StorageStatsManager;
+import android.content.AttributionSource;
import android.content.ContentResolver;
import android.content.UriPermission;
import android.database.Cursor;
@@ -28,7 +29,6 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
-import android.os.IBinder;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.DiskInfo;
@@ -141,17 +141,17 @@
}
@Override
- protected int enforceReadPermissionInner(Uri uri, String callingPkg,
- @Nullable String featureId, IBinder callerToken) throws SecurityException {
+ protected int enforceReadPermissionInner(Uri uri,
+ @NonNull AttributionSource attributionSource) throws SecurityException {
enforceShellRestrictions();
- return super.enforceReadPermissionInner(uri, callingPkg, featureId, callerToken);
+ return super.enforceReadPermissionInner(uri, attributionSource);
}
@Override
- protected int enforceWritePermissionInner(Uri uri, String callingPkg,
- @Nullable String featureId, IBinder callerToken) throws SecurityException {
+ protected int enforceWritePermissionInner(Uri uri,
+ @NonNull AttributionSource attributionSource) throws SecurityException {
enforceShellRestrictions();
- return super.enforceWritePermissionInner(uri, callingPkg, featureId, callerToken);
+ return super.enforceWritePermissionInner(uri, attributionSource);
}
public void updateVolumes() {
diff --git a/packages/PackageInstaller/res/values-iw/strings.xml b/packages/PackageInstaller/res/values-iw/strings.xml
index 5b17d74..e5e2195 100644
--- a/packages/PackageInstaller/res/values-iw/strings.xml
+++ b/packages/PackageInstaller/res/values-iw/strings.xml
@@ -24,7 +24,7 @@
<string name="installing_app" msgid="1165095864863849422">"מתבצעת התקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
<string name="install_done" msgid="5987363587661783896">"האפליקציה הותקנה."</string>
<string name="install_confirm_question" msgid="8176284075816604590">"להתקין את האפליקציה הזו?"</string>
- <string name="install_confirm_question_update" msgid="7942235418781274635">"האם ברצונך להתקין עדכון עבור אפליקציה קיימת זו? הנתונים הקיימים שלך לא יאבדו."</string>
+ <string name="install_confirm_question_update" msgid="7942235418781274635">"להתקין עדכון עבור האפליקציה הזו? הנתונים הקיימים שלך לא יאבדו."</string>
<string name="install_confirm_question_update_system" msgid="4713001702777910263">"האם ברצונך להתקין עדכון עבור אפליקציה מובנית זו? הנתונים הקיימים שלך לא יאבדו."</string>
<string name="install_failed" msgid="5777824004474125469">"האפליקציה לא הותקנה."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"החבילה נחסמה להתקנה."</string>
@@ -43,7 +43,7 @@
<string name="ok" msgid="7871959885003339302">"אישור"</string>
<string name="manage_applications" msgid="5400164782453975580">"ניהול אפליקציות"</string>
<string name="out_of_space_dlg_title" msgid="4156690013884649502">"אין מספיק שטח"</string>
- <string name="out_of_space_dlg_text" msgid="8727714096031856231">"לא ניתן להתקין את <xliff:g id="APP_NAME">%1$s</xliff:g>. יש לפנות שטח ולנסות שוב."</string>
+ <string name="out_of_space_dlg_text" msgid="8727714096031856231">"לא ניתן להתקין את <xliff:g id="APP_NAME">%1$s</xliff:g>. יש לפנות מקום אחסון ולנסות שוב."</string>
<string name="app_not_found_dlg_title" msgid="5107924008597470285">"האפליקציה לא נמצאה"</string>
<string name="app_not_found_dlg_text" msgid="5219983779377811611">"האפליקציה לא נמצאת ברשימת האפליקציות המותקנות."</string>
<string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"לא מורשה"</string>
@@ -62,11 +62,11 @@
<string name="uninstalling_notification_channel" msgid="840153394325714653">"התקנות בתהליכי הסרה"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"הסרות התקנה שנכשלו"</string>
<string name="uninstalling" msgid="8709566347688966845">"בתהליך הסרת התקנה..."</string>
- <string name="uninstalling_app" msgid="8866082646836981397">"מסיר את ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+ <string name="uninstalling_app" msgid="8866082646836981397">"המערכת מסירה את ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
<string name="uninstall_done" msgid="439354138387969269">"הסרת ההתקנה הסתיימה."</string>
<string name="uninstall_done_app" msgid="4588850984473605768">"ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> הוסרה"</string>
- <string name="uninstall_failed" msgid="1847750968168364332">"הסרת ההתקנה נכשלה."</string>
- <string name="uninstall_failed_app" msgid="5506028705017601412">"נכשלה הסרת ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+ <string name="uninstall_failed" msgid="1847750968168364332">"לא ניתן היה להסיר את ההתקנה."</string>
+ <string name="uninstall_failed_app" msgid="5506028705017601412">"לא ניתן היה להסיר את ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
<string name="uninstall_failed_device_policy_manager" msgid="785293813665540305">"לא ניתן להסיר את ההתקנה של אפליקציה פעילה של מנהל המכשיר"</string>
<string name="uninstall_failed_device_policy_manager_of_user" msgid="4813104025494168064">"לא ניתן להסיר את ההתקנה של אפליקציה פעילה של מנהל המכשיר של <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="uninstall_all_blocked_profile_owner" msgid="2009393666026751501">"אפליקציה זו נדרשת לחלק מהמשתמשים או מהפרופילים והתקנתה הוסרה למשתמשים אחרים"</string>
@@ -83,7 +83,7 @@
<string name="untrusted_external_source_warning" product="tablet" msgid="6539403649459942547">"לצורכי אבטחה, הטאבלט שלך חסום להתקנת אפליקציות בלתי מוכרות המגיעות ממקור זה."</string>
<string name="untrusted_external_source_warning" product="tv" msgid="1206648674551321364">"לצורכי אבטחה, מכשיר הטלוויזיה שלך חסום להתקנת אפליקציות בלתי מוכרות המגיעות ממקור זה."</string>
<string name="untrusted_external_source_warning" product="default" msgid="7279739265754475165">"לצורכי אבטחה, הטלפון שלך חסום להתקנת אפליקציות בלתי מוכרות המגיעות ממקור זה."</string>
- <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"נתוני הטלפון והנתונים האישיים שלך חשופים יותר בפני התקפות על ידי אפליקציות ממקורות לא ידועים. אם תתקין אפליקציה זו, אתה מסכים לכך שאתה האחראי הבלעדי במקרה של אובדן נתונים או אם ייגרם נזק לטלפון שלך בעקבות השימוש באפליקציה."</string>
+ <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"נתוני הטלפון והנתונים האישיים שלך חשופים יותר בפני התקפות על ידי אפליקציות ממקורות לא ידועים. התקנת האפליקציה הזו מהווה את הסכמתך לכך שהאחריות הבלעדית היא שלך במקרה של אובדן נתונים או גרימת נזק לטלפון שלך בעקבות השימוש באפליקציה."</string>
<string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"נתוני הטאבלט והנתונים האישיים שלך חשופים יותר בפני התקפות על ידי אפליקציות ממקורות לא ידועים. אם תתקין אפליקציה זו, אתה מסכים לכך שאתה האחראי הבלעדי במקרה של אובדן נתונים או אם ייגרם נזק לטאבלט שלך בעקבות השימוש באפליקציה."</string>
<string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"נתוני הטלוויזיה והנתונים האישיים שלך חשופים יותר בפני התקפות על ידי אפליקציות ממקורות לא ידועים. אם תתקין אפליקציה זו, אתה מסכים לכך שאתה האחראי הבלעדי במקרה של אובדן נתונים או אם ייגרם נזק לטלוויזיה שלך בעקבות השימוש באפליקציה."</string>
<string name="anonymous_source_continue" msgid="4375745439457209366">"המשך"</string>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 5dcd7f2..1850233 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -27,7 +27,7 @@
<string name="label_duplex" msgid="5370037254347072243">"דו-צדדי"</string>
<string name="label_orientation" msgid="2853142581990496477">"כיוון"</string>
<string name="label_pages" msgid="7768589729282182230">"עמודים"</string>
- <string name="destination_default_text" msgid="5422708056807065710">"בחר מדפסת"</string>
+ <string name="destination_default_text" msgid="5422708056807065710">"בחירת מדפסת"</string>
<string name="template_all_pages" msgid="3322235982020148762">"הכל <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
<string name="template_page_range" msgid="428638530038286328">"טווח של <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
<string name="pages_range_example" msgid="8558694453556945172">"למשל 1–5,8,11–13"</string>
@@ -41,7 +41,7 @@
<string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="page_description_template" msgid="6831239682256197161">"עמוד <xliff:g id="CURRENT_PAGE">%1$d</xliff:g> מתוך <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="summary_template" msgid="8899734908625669193">"סיכום, עותקים <xliff:g id="COPIES">%1$s</xliff:g>, גודל נייר <xliff:g id="PAPER_SIZE">%2$s</xliff:g>"</string>
- <string name="expand_handle" msgid="7282974448109280522">"ידית הרחבה"</string>
+ <string name="expand_handle" msgid="7282974448109280522">"נקודת אחיזה להרחבה"</string>
<string name="collapse_handle" msgid="6886637989442507451">"ידית כיווץ"</string>
<string name="print_button" msgid="645164566271246268">"הדפס"</string>
<string name="savetopdf_button" msgid="2976186791686924743">"שמירה כ-PDF"</string>
@@ -72,7 +72,7 @@
<string name="print_no_printers" msgid="4869403323900054866">"לא נמצאו מדפסות"</string>
<string name="cannot_add_printer" msgid="7840348733668023106">"לא ניתן להוסיף מדפסות"</string>
<string name="select_to_add_printers" msgid="3800709038689830974">"בחר כדי להוסיף מדפסת"</string>
- <string name="enable_print_service" msgid="3482815747043533842">"בחר כדי להפעיל"</string>
+ <string name="enable_print_service" msgid="3482815747043533842">"צריך לבחור כדי להפעיל"</string>
<string name="enabled_services_title" msgid="7036986099096582296">"שירותים מופעלים"</string>
<string name="recommended_services_title" msgid="3799434882937956924">"שירותים מומלצים"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"שירותים מושבתים"</string>
@@ -84,7 +84,7 @@
<item quantity="one">התקן כדי לגלות מדפסת <xliff:g id="COUNT_0">%1$s</xliff:g></item>
</plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"מדפיס את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <string name="cancelling_notification_title_template" msgid="1821759594704703197">"מבטל את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
+ <string name="cancelling_notification_title_template" msgid="1821759594704703197">"המערכת מבטלת את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"שגיאת מדפסת ב-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"המדפסת חסמה את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancel" msgid="4373674107267141885">"ביטול"</string>
@@ -111,5 +111,5 @@
<string name="print_error_retry" msgid="1426421728784259538">"כדאי לנסות שוב"</string>
<string name="print_error_printer_unavailable" msgid="8985614415253203381">"המדפסת הזו אינה זמינה כעת."</string>
<string name="print_cannot_load_page" msgid="6179560924492912009">"לא ניתן להציג תצוגה מקדימה"</string>
- <string name="print_preparing_preview" msgid="3939930735671364712">"מכין תצוגה מקדימה…"</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"בתהליך יצירת תצוגה מקדימה…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-ml/strings.xml b/packages/PrintSpooler/res/values-ml/strings.xml
deleted file mode 100644
index 73af95d..0000000
--- a/packages/PrintSpooler/res/values-ml/strings.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4469836075319831821">"Print Spooler"</string>
- <string name="more_options_button" msgid="2243228396432556771">"കൂടുതൽ ഓപ്ഷനുകൾ"</string>
- <string name="label_destination" msgid="9132510997381599275">"ലക്ഷ്യസ്ഥാനം"</string>
- <string name="label_copies" msgid="3634531042822968308">"പകർപ്പുകൾ"</string>
- <string name="label_copies_summary" msgid="3861966063536529540">"പകർപ്പുകൾ:"</string>
- <string name="label_paper_size" msgid="908654383827777759">"പേപ്പർ വലുപ്പം"</string>
- <string name="label_paper_size_summary" msgid="5668204981332138168">"പേപ്പർ വലുപ്പം:"</string>
- <string name="label_color" msgid="1108690305218188969">"നിറം"</string>
- <string name="label_duplex" msgid="5370037254347072243">"രണ്ട് വശങ്ങളുള്ളത്"</string>
- <string name="label_orientation" msgid="2853142581990496477">"ഓറിയന്റേഷന്"</string>
- <string name="label_pages" msgid="7768589729282182230">"പേജുകൾ"</string>
- <string name="destination_default_text" msgid="5422708056807065710">"ഒരു പ്രിന്റർ തിരഞ്ഞെടുക്കുക"</string>
- <string name="template_all_pages" msgid="3322235982020148762">"എല്ലാ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
- <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> എന്നതിന്റെ പരിധി"</string>
- <string name="pages_range_example" msgid="8558694453556945172">"ഉദാ. 1—5,8,11—13"</string>
- <string name="print_preview" msgid="8010217796057763343">"പ്രിന്റ് പ്രിവ്യൂ"</string>
- <string name="install_for_print_preview" msgid="6366303997385509332">"പ്രിവ്യൂ കാണിക്കുന്നതിന് PDF വ്യൂവർ ഇൻസ്റ്റാൾ ചെയ്യുക"</string>
- <string name="printing_app_crashed" msgid="854477616686566398">"പ്രിന്റുചെയ്യൽ അപ്ലിക്കേഷൻ ക്രാഷായി"</string>
- <string name="generating_print_job" msgid="3119608742651698916">"പ്രിന്റ് ജോലി സൃഷ്ടിക്കുന്നു"</string>
- <string name="save_as_pdf" msgid="5718454119847596853">"PDF-ആയി സംരക്ഷിക്കൂ"</string>
- <string name="all_printers" msgid="5018829726861876202">"എല്ലാ പ്രിന്ററുകളും..."</string>
- <string name="print_dialog" msgid="32628687461331979">"പ്രിന്റ് സംഭാഷണം"</string>
- <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
- <string name="page_description_template" msgid="6831239682256197161">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> / <xliff:g id="PAGE_COUNT">%2$d</xliff:g> പേജ്"</string>
- <string name="summary_template" msgid="8899734908625669193">"സംഗ്രഹം, പകർപ്പുകൾ <xliff:g id="COPIES">%1$s</xliff:g>, പേപ്പർ വലുപ്പം <xliff:g id="PAPER_SIZE">%2$s</xliff:g> എന്നിവ"</string>
- <string name="expand_handle" msgid="7282974448109280522">"വിപുലീകരണം കൈകാര്യം ചെയ്യുക"</string>
- <string name="collapse_handle" msgid="6886637989442507451">"ചുരുക്കുന്നത് കൈകാര്യം ചെയ്യുക"</string>
- <string name="print_button" msgid="645164566271246268">"പ്രിന്റുചെയ്യുക"</string>
- <string name="savetopdf_button" msgid="2976186791686924743">"PDF-ൽ സംരക്ഷിക്കുക"</string>
- <string name="print_options_expanded" msgid="6944679157471691859">"പ്രിന്റ് ചെയ്യാനുള്ള ഓപ്ഷനുകൾ വിപുലീകരിച്ചു"</string>
- <string name="print_options_collapsed" msgid="7455930445670414332">"പ്രിന്റ് ചെയ്യാനുള്ള ഓപ്ഷനുകൾ ചുരുക്കി"</string>
- <string name="search" msgid="5421724265322228497">"Search"</string>
- <string name="all_printers_label" msgid="3178848870161526399">"എല്ലാ പ്രിന്ററുകളും"</string>
- <string name="add_print_service_label" msgid="5356702546188981940">"സേവനം ചേർക്കുക"</string>
- <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"തിരയൽ ബോക്സ് ദൃശ്യമാക്കിയിരിക്കുന്നു"</string>
- <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"തിരയൽ ബോക്സ് മറച്ചിരിക്കുന്നു"</string>
- <string name="print_add_printer" msgid="1088656468360653455">"പ്രിന്റർ ചേർക്കുക"</string>
- <string name="print_select_printer" msgid="7388760939873368698">"പ്രിന്റർ തിരഞ്ഞെടുക്കുക"</string>
- <string name="print_forget_printer" msgid="5035287497291910766">"പ്രിന്റർ മറന്നു"</string>
- <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
- <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> പ്രിന്ററുകൾ കണ്ടെത്തി</item>
- <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> പ്രിന്റർ കണ്ടെത്തി</item>
- </plurals>
- <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
- <string name="printer_info_desc" msgid="7181988788991581654">"ഈ പ്രിന്ററിനെ കുറിച്ചുള്ള കൂടുതൽ വിവരങ്ങൾ"</string>
- <string name="notification_channel_progress" msgid="872788690775721436">"നടന്നുകൊണ്ടിരിക്കുന്ന പ്രിന്റ് ജോലികൾ"</string>
- <string name="notification_channel_failure" msgid="9042250774797916414">"പരാജയപ്പെട്ട പ്രിന്റ് ജോലികൾ"</string>
- <string name="could_not_create_file" msgid="3425025039427448443">"ഫയൽ സൃഷ്ടിക്കാൻ കഴിഞ്ഞില്ല"</string>
- <string name="print_services_disabled_toast" msgid="9089060734685174685">"ചില പ്രിന്റ് സേവനങ്ങൾ പ്രവർത്തനരഹിതമാക്കി"</string>
- <string name="print_searching_for_printers" msgid="6550424555079932867">"പ്രിന്ററുകൾക്കായി തിരയുന്നു"</string>
- <string name="print_no_print_services" msgid="8561247706423327966">"പ്രിന്റ് സേവനങ്ങളൊന്നും പ്രവർത്തനക്ഷമാക്കിയിട്ടില്ല"</string>
- <string name="print_no_printers" msgid="4869403323900054866">"പ്രിന്ററുകളൊന്നും കണ്ടെത്തിയില്ല"</string>
- <string name="cannot_add_printer" msgid="7840348733668023106">"പ്രിന്ററുകൾ ചേർക്കാൻ കഴിയില്ല"</string>
- <string name="select_to_add_printers" msgid="3800709038689830974">"പ്രിന്റർ ചേർക്കാൻ തിരഞ്ഞെടുക്കുക"</string>
- <string name="enable_print_service" msgid="3482815747043533842">"പ്രവർത്തനക്ഷമമാക്കാൻ തിരഞ്ഞെടുക്കുക"</string>
- <string name="enabled_services_title" msgid="7036986099096582296">"പ്രവർത്തനക്ഷമമാക്കിയ സേവനങ്ങൾ"</string>
- <string name="recommended_services_title" msgid="3799434882937956924">"ശുപാർശ ചെയ്യപ്പെടുന്ന സേവനങ്ങൾ"</string>
- <string name="disabled_services_title" msgid="7313253167968363211">"പ്രവർത്തനരഹിതമാക്കിയ സേവനങ്ങൾ"</string>
- <string name="all_services_title" msgid="5578662754874906455">"എല്ലാ സേവനങ്ങളും"</string>
- <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
- <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> പ്രിന്ററുകൾ കണ്ടെത്തുന്നതിന് ഇൻസ്റ്റാൾ ചെയ്യുക</item>
- <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> പ്രിന്റർ കണ്ടെത്തുന്നതിന് ഇൻസ്റ്റാൾ ചെയ്യുക</item>
- </plurals>
- <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> പ്രിന്റുചെയ്യുന്നു"</string>
- <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> റദ്ദാക്കുന്നു"</string>
- <string name="failed_notification_title_template" msgid="2256217208186530973">"പ്രിന്റർ പിശക് <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <string name="blocked_notification_title_template" msgid="1175435827331588646">"പ്രിന്റർ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> തടഞ്ഞു"</string>
- <string name="cancel" msgid="4373674107267141885">"റദ്ദാക്കുക"</string>
- <string name="restart" msgid="2472034227037808749">"പുനരാരംഭിക്കുക"</string>
- <string name="no_connection_to_printer" msgid="2159246915977282728">"പ്രിന്ററിൽ കണക്ഷനൊന്നുമില്ല"</string>
- <string name="reason_unknown" msgid="5507940196503246139">"അജ്ഞാതം"</string>
- <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> ഉപയോഗിക്കണോ?"</string>
- <string name="print_service_security_warning_summary" msgid="1427434625361692006">"നിങ്ങളുടെ പ്രമാണം പ്രിന്ററിലേക്ക് പോകുന്നതിനിടെ അത് ഒന്നോ അതിലധികമോ സെർവറുകളിലൂടെ കടന്നുപോകാനിടയുണ്ട്."</string>
- <string-array name="color_mode_labels">
- <item msgid="7602948745415174937">"കറുപ്പ് & വെള്ള"</item>
- <item msgid="2762241247228983754">"നിറം"</item>
- </string-array>
- <string-array name="duplex_mode_labels">
- <item msgid="3882302912790928315">"ഒന്നുമില്ല"</item>
- <item msgid="7296563835355641719">"നീളമുള്ള അരിക്"</item>
- <item msgid="79513688117503758">"ഹ്രസ്വ അരിക്"</item>
- </string-array>
- <string-array name="orientation_labels">
- <item msgid="4061931020926489228">"പോർട്രെയ്റ്റ്"</item>
- <item msgid="3199660090246166812">"ലാൻഡ്സ്കേപ്പ്"</item>
- </string-array>
- <string name="print_write_error_message" msgid="5787642615179572543">"ഫയലിൽ റൈറ്റുചെയ്യാനായില്ല"</string>
- <string name="print_error_default_message" msgid="8602678405502922346">"ക്ഷമിക്കണം, അത് പ്രവർത്തിച്ചില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
- <string name="print_error_retry" msgid="1426421728784259538">"വീണ്ടും ശ്രമിക്കുക"</string>
- <string name="print_error_printer_unavailable" msgid="8985614415253203381">"ഈ പ്രിന്ററർ ഇപ്പോൾ ലഭ്യമല്ല."</string>
- <string name="print_cannot_load_page" msgid="6179560924492912009">"പ്രിവ്യൂ കാണിക്കാൻ കഴിയില്ല"</string>
- <string name="print_preparing_preview" msgid="3939930735671364712">"പ്രിവ്യൂ തയ്യാറാക്കുന്നു…"</string>
-</resources>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index 2cd8d9b..79cb1ae 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -64,9 +64,9 @@
<string name="notification_channel_progress" msgid="872788690775721436">"Actieve afdruktaken"</string>
<string name="notification_channel_failure" msgid="9042250774797916414">"Mislukte afdruktaken"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Kan bestand niet maken"</string>
- <string name="print_services_disabled_toast" msgid="9089060734685174685">"Sommige afdrukservices zijn uitgeschakeld"</string>
+ <string name="print_services_disabled_toast" msgid="9089060734685174685">"Sommige afdrukservices zijn uitgezet"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printers zoeken"</string>
- <string name="print_no_print_services" msgid="8561247706423327966">"Geen afdrukservices ingeschakeld"</string>
+ <string name="print_no_print_services" msgid="8561247706423327966">"Geen afdrukservices aangezet"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Geen printers gevonden"</string>
<string name="cannot_add_printer" msgid="7840348733668023106">"Kan geen printers toevoegen"</string>
<string name="select_to_add_printers" msgid="3800709038689830974">"Selecteer om printer toe te voegen"</string>
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index 49f6bd8..a2bec33 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -555,7 +555,7 @@
bundle.putString(META_DATA_PREFERENCE_KEYHINT, key);
}
try {
- return provider.call(context.getPackageName(), context.getAttributionTag(),
+ return provider.call(context.getAttributionSource(),
uri.getAuthority(), method, uri.toString(), bundle);
} catch (RemoteException e) {
return null;
diff --git a/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml b/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml
index f45105d..31b3fe5 100644
--- a/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml
+++ b/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml
@@ -70,4 +70,13 @@
android:scaleY="2"
android:layout_marginTop="4dp"
android:max="100"/>
+
+ <TextView
+ android:id="@+id/bottom_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:ellipsize="marquee"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"
+ android:textSize="14sp"/>
</LinearLayout>
diff --git a/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java b/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java
index 2185950..a2b1de2 100644
--- a/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java
+++ b/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java
@@ -44,6 +44,7 @@
private CharSequence mUsageSummary;
private CharSequence mTotalSummary;
+ private CharSequence mBottomSummary;
private ImageView mCustomImageView;
private int mPercent = -1;
@@ -101,6 +102,15 @@
notifyChanged();
}
+ /** Set bottom summary. */
+ public void setBottomSummary(CharSequence bottomSummary) {
+ if (TextUtils.equals(mBottomSummary, bottomSummary)) {
+ return;
+ }
+ mBottomSummary = bottomSummary;
+ notifyChanged();
+ }
+
/** Set percentage of the progress bar. */
public void setPercent(long usage, long total) {
if (total == 0L || usage > total) {
@@ -147,6 +157,14 @@
totalSummary.setText(mTotalSummary);
}
+ final TextView bottomSummary = (TextView) holder.findViewById(R.id.bottom_summary);
+ if (TextUtils.isEmpty(mBottomSummary)) {
+ bottomSummary.setVisibility(View.GONE);
+ } else {
+ bottomSummary.setVisibility(View.VISIBLE);
+ bottomSummary.setText(mBottomSummary);
+ }
+
final ProgressBar progressBar = (ProgressBar) holder.findViewById(android.R.id.progress);
if (mPercent < 0) {
progressBar.setIndeterminate(true);
diff --git a/packages/SettingsLib/res/values/colors.xml b/packages/SettingsLib/res/values/colors.xml
index 88c6185..5e8779f 100644
--- a/packages/SettingsLib/res/values/colors.xml
+++ b/packages/SettingsLib/res/values/colors.xml
@@ -39,7 +39,4 @@
<color name="dark_mode_icon_color_single_tone">#99000000</color>
<color name="light_mode_icon_color_single_tone">#ffffff</color>
-
- <!-- Yellow 600, used for highlighting "important" conversations in settings & notifications -->
- <color name="important_conversation">#f9ab00</color>
</resources>
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java
index fe76b06..cd78add 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java
@@ -92,6 +92,28 @@
}
@Test
+ public void setBottomSummary_getCorrectSummary() {
+ final String expectedText = "Should last until about 7:45 PM";
+ mUsageProgressBarPreference.setBottomSummary(expectedText);
+
+ mUsageProgressBarPreference.onBindViewHolder(mViewHolder);
+
+ final TextView bottomSummary = (TextView) mViewHolder.findViewById(R.id.bottom_summary);
+ assertThat(bottomSummary.getText()).isEqualTo(expectedText);
+ assertThat(bottomSummary.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void setBottomSummary_emptyText_isGone() {
+ mUsageProgressBarPreference.setBottomSummary(null);
+
+ mUsageProgressBarPreference.onBindViewHolder(mViewHolder);
+
+ final TextView bottomSummary = (TextView) mViewHolder.findViewById(R.id.bottom_summary);
+ assertThat(bottomSummary.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
public void setPercent_getCorrectProgress() {
mUsageProgressBarPreference.setPercent(31, 80);
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index db9b83e..53920f0 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -165,6 +165,8 @@
VALIDATORS.put(Secure.ASSIST_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ASSIST_GESTURE_WAKE_ENABLED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.ASSIST_TOUCH_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.ASSIST_LONG_PRESS_HOME_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.VR_DISPLAY_MODE, new DiscreteValueValidator(new String[] {"0", "1"}));
VALIDATORS.put(Secure.NOTIFICATION_BADGING, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.NOTIFICATION_DISMISS_RTL, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index fdbbc39..df6ff73 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -18,6 +18,7 @@
import android.annotation.SystemApi;
import android.app.ActivityManager;
+import android.content.AttributionSource;
import android.content.IContentProvider;
import android.os.Binder;
import android.os.Bundle;
@@ -250,7 +251,8 @@
Bundle args = new Bundle();
args.putInt(Settings.CALL_METHOD_USER_KEY,
ActivityManager.getService().getCurrentUser().id);
- Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+ Bundle b = provider.call(new AttributionSource(Process.myUid(),
+ resolveCallingPackage(), null), Settings.AUTHORITY,
Settings.CALL_METHOD_DELETE_CONFIG, compositeKey, args);
success = (b != null && b.getInt(SettingsProvider.RESULT_ROWS_DELETED) == 1);
} catch (RemoteException e) {
@@ -266,7 +268,8 @@
Bundle args = new Bundle();
args.putInt(Settings.CALL_METHOD_USER_KEY,
ActivityManager.getService().getCurrentUser().id);
- Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+ Bundle b = provider.call(new AttributionSource(Process.myUid(),
+ resolveCallingPackage(), null), Settings.AUTHORITY,
Settings.CALL_METHOD_LIST_CONFIG, null, args);
if (b != null) {
Map<String, String> flagsToValues =
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 9c67e9c..4119dc9f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1881,6 +1881,12 @@
dumpSetting(s, p,
Settings.Secure.ASSIST_GESTURE_SETUP_COMPLETE,
SecureSettingsProto.Assist.GESTURE_SETUP_COMPLETE);
+ dumpSetting(s, p,
+ Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED,
+ SecureSettingsProto.Assist.TOUCH_GESTURE_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED,
+ SecureSettingsProto.Assist.LONG_PRESS_HOME_ENABLED);
p.end(assistToken);
final long assistHandlesToken = p.start(SecureSettingsProto.ASSIST_HANDLES);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
index 3b3ca5b..17ebf6f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -17,6 +17,7 @@
package com.android.providers.settings;
import android.app.ActivityManager;
+import android.content.AttributionSource;
import android.content.IContentProvider;
import android.content.pm.PackageManager;
import android.os.Binder;
@@ -309,7 +310,9 @@
try {
Bundle arg = new Bundle();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
- Bundle result = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+ final AttributionSource attributionSource = new AttributionSource(
+ Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
+ Bundle result = provider.call(attributionSource, Settings.AUTHORITY,
callListCommand, null, arg);
lines.addAll(result.getStringArrayList(SettingsProvider.RESULT_SETTINGS_LIST));
Collections.sort(lines);
@@ -334,7 +337,9 @@
try {
Bundle arg = new Bundle();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
- Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+ final AttributionSource attributionSource = new AttributionSource(
+ Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
+ Bundle b = provider.call(attributionSource, Settings.AUTHORITY,
callGetCommand, key, arg);
if (b != null) {
result = b.getPairValue();
@@ -372,7 +377,9 @@
if (makeDefault) {
arg.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
}
- provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+ final AttributionSource attributionSource = new AttributionSource(
+ Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
+ provider.call(attributionSource, Settings.AUTHORITY,
callPutCommand, key, arg);
} catch (RemoteException e) {
throw new RuntimeException("Failed in IPC", e);
@@ -396,7 +403,9 @@
try {
Bundle arg = new Bundle();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
- Bundle result = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
+ final AttributionSource attributionSource = new AttributionSource(
+ Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
+ Bundle result = provider.call(attributionSource, Settings.AUTHORITY,
callDeleteCommand, key, arg);
return result.getInt(SettingsProvider.RESULT_ROWS_DELETED);
} catch (RemoteException e) {
@@ -423,7 +432,9 @@
}
String packageName = mPackageName != null ? mPackageName : resolveCallingPackage();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
- provider.call(packageName, null, Settings.AUTHORITY, callResetCommand, null, arg);
+ final AttributionSource attributionSource = new AttributionSource(
+ Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
+ provider.call(attributionSource, Settings.AUTHORITY, callResetCommand, null, arg);
} catch (RemoteException e) {
throw new RuntimeException("Failed in IPC", e);
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index cff8ad1..4c56db4 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -35,6 +35,8 @@
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
+ <uses-permission android:name="android.permission.READ_CALL_LOG" />
+ <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@@ -194,11 +196,14 @@
<uses-permission android:name="android.permission.MANAGE_CAMERA" />
<!-- Permissions needed to test system only camera devices -->
<uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.BACKGROUND_CAMERA" />
<uses-permission android:name="android.permission.SYSTEM_CAMERA" />
<!-- Permissions needed to test onCameraOpened/Closed callbacks -->
<uses-permission android:name="android.permission.CAMERA_OPEN_CLOSE_LISTENER" />
<!-- Permissions needed for CTS camera test: RecordingTest.java when assuming shell id -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
+ <uses-permission android:name="android.permission.RECORD_BACKGROUND_AUDIO" />
+
<!-- Permission needed to enable/disable Bluetooth/Wifi -->
<uses-permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED" />
<uses-permission android:name="android.permission.MANAGE_WIFI_WHEN_WIRELESS_CONSENT_REQUIRED" />
diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml
index c99e69e..ade92db 100644
--- a/packages/Shell/res/values-iw/strings.xml
+++ b/packages/Shell/res/values-iw/strings.xml
@@ -18,18 +18,18 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"מעטפת"</string>
<string name="bugreport_notification_channel" msgid="2574150205913861141">"דוחות על באגים"</string>
- <string name="bugreport_in_progress_title" msgid="4311705936714972757">"יצירת הדוח על הבאג <xliff:g id="ID">#%d</xliff:g> מתבצעת"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"בתהליך יצירה של דוח על באג (<xliff:g id="ID">#%d</xliff:g>)"</string>
<string name="bugreport_finished_title" msgid="4429132808670114081">"הדוח על הבאג <xliff:g id="ID">#%d</xliff:g> צולם"</string>
- <string name="bugreport_updating_title" msgid="4423539949559634214">"מוסיף פרטים לדוח על הבאג"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"בתהליך הוספת פרטים לדוח על הבאג"</string>
<string name="bugreport_updating_wait" msgid="3322151947853929470">"המתן…"</string>
<string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"הדוח על הבאג יופיע בטלפון בקרוב"</string>
- <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"הקש כדי לשתף את הדוח על הבאג"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"יש להקיש כדי לשתף את הדוח על הבאג"</string>
<string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"הקש כדי לשתף את הדוח על הבאג"</string>
<string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"החלק ימינה כדי לשתף את הדוח על הבאג ללא צילום מסך או המתן להשלמת צילום המסך"</string>
- <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"הקש כדי לשתף את הדוח על הבאג ללא צילום מסך, או המתן להשלמת צילום המסך"</string>
- <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"הקש כדי לשתף את הדוח על הבאג ללא צילום מסך, או המתן להשלמת צילום המסך"</string>
- <string name="bugreport_confirm" msgid="5917407234515812495">"דוחות על באגים כוללים נתונים מקובצי היומן השונים במערכת, שעשויים לכלול נתונים הנחשבים רגישים (כגון שימוש באפליקציות ונתוני מיקום). שתף דוחות על באגים רק עם אפליקציות ואנשים שאתה סומך עליהם."</string>
- <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"אל תציג שוב"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"יש להקיש כדי לשתף את הדוח על הבאג ללא צילום מסך, או להמתין להשלמת צילום המסך"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"יש להקיש כדי לשתף את הדוח על הבאג ללא צילום מסך, או להמתין להשלמת צילום המסך"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"דוחות על באגים כוללים נתונים מקובצי היומן השונים במערכת, שעשויים לכלול נתונים הנחשבים רגישים (כגון שימוש באפליקציות ונתוני מיקום). כדאי לשתף דוחות על באגים רק עם אפליקציות ואנשים מהימנים."</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"אל תציגו זאת שוב"</string>
<string name="bugreport_storage_title" msgid="5332488144740527109">"דוחות באגים"</string>
<string name="bugreport_unreadable_text" msgid="586517851044535486">"לא ניתן היה לקרוא את קובץ הדוח על הבאג"</string>
<string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"לא ניתן היה להוסיף את פרטי הדוח על הבאג לקובץ ה-zip"</string>
@@ -38,7 +38,7 @@
<string name="bugreport_screenshot_action" msgid="8677781721940614995">"צילום מסך"</string>
<string name="bugreport_screenshot_taken" msgid="5684211273096253120">"צילום המסך בוצע בהצלחה."</string>
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"לא ניתן היה לצלם מסך."</string>
- <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"פרטי הדוח על הבאג <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"פרטי הדוח על הבאג (<xliff:g id="ID">#%d</xliff:g>)"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"שם קובץ"</string>
<string name="bugreport_info_title" msgid="2306030793918239804">"כותרת הבאג"</string>
<string name="bugreport_info_description" msgid="5072835127481627722">"סיכום הבאג"</string>
diff --git a/packages/Shell/res/values-nl/strings.xml b/packages/Shell/res/values-nl/strings.xml
index 3868f4a..dadf9fa 100644
--- a/packages/Shell/res/values-nl/strings.xml
+++ b/packages/Shell/res/values-nl/strings.xml
@@ -22,14 +22,14 @@
<string name="bugreport_finished_title" msgid="4429132808670114081">"Bugrapport <xliff:g id="ID">#%d</xliff:g> is vastgelegd"</string>
<string name="bugreport_updating_title" msgid="4423539949559634214">"Details toevoegen aan het bugrapport"</string>
<string name="bugreport_updating_wait" msgid="3322151947853929470">"Even geduld…"</string>
- <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Het bugrapport wordt over enkele ogenblikken op de telefoon weergegeven"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Het bugrapport zie je over enkele ogenblikken op de telefoon"</string>
<string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Selecteer dit om je bugrapport te delen"</string>
<string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tik om je bugrapport te delen"</string>
<string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Selecteer dit om je bugrapport te delen zonder screenshot of wacht tot het screenshot is voltooid"</string>
<string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tik om je bugrapport te delen zonder screenshot of wacht tot het screenshot is voltooid"</string>
<string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tik om je bugrapport te delen zonder screenshot of wacht tot het screenshot is voltooid"</string>
<string name="bugreport_confirm" msgid="5917407234515812495">"Bugrapporten bevatten gegevens uit de verschillende logbestanden van het systeem, die gegevens kunnen bevatten die je als gevoelig beschouwt (zoals gegevens met betrekking tot app-gebruik en locatie). Deel bugrapporten alleen met mensen en apps die je vertrouwt."</string>
- <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Niet opnieuw weergeven"</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Niet opnieuw tonen"</string>
<string name="bugreport_storage_title" msgid="5332488144740527109">"Bugrapporten"</string>
<string name="bugreport_unreadable_text" msgid="586517851044535486">"Bestand met bugrapport kan niet worden gelezen"</string>
<string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Kan details van bugrapport niet toevoegen aan zip-bestand"</string>
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index f884270..835471d 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -9,6 +9,7 @@
awickham@google.com
beverlyt@google.com
brockman@google.com
+ccassidy@google.com
cinek@google.com
cwren@google.com
dupin@google.com
@@ -19,10 +20,10 @@
hyunyoungs@google.com
jaggies@google.com
jamesoleary@google.com
+jdemeulenaere@google.com
jeffdq@google.com
jjaggi@google.com
jonmiranda@google.com
-joshmcgrath@google.com
joshtrask@google.com
juliacr@google.com
juliatuttle@google.com
@@ -37,7 +38,6 @@
mpietal@google.com
mrcasey@google.com
mrenouf@google.com
-nbenbernou@google.com
nesciosquid@google.com
ogunwale@google.com
peanutbutter@google.com
@@ -45,6 +45,7 @@
pixel@google.com
roosa@google.com
santie@google.com
+shanh@google.com
snoeberger@google.com
sreyasr@google.com
steell@google.com
@@ -59,6 +60,7 @@
vadimt@google.com
victortulias@google.com
winsonc@google.com
+yurilin@google.com
xuqiu@google.com
zakcohen@google.com
diff --git a/packages/SystemUI/docs/camera.md b/packages/SystemUI/docs/camera.md
index 7a7a5aa..cabc65c 100644
--- a/packages/SystemUI/docs/camera.md
+++ b/packages/SystemUI/docs/camera.md
@@ -13,8 +13,8 @@
4. Inside SystemUI, [onCameraLaunchDetected](/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java#3927) looks at the keyguard state and determines
1. whether the camera is even allowed
2. whether the screen is on; if not, we need to delay until that happens
- 3. whether the device is locked (defined as "keyuguard is showing").
-5. If the device is unlocked (no keyguard), the camera is launched immediately. [Callsite](/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java#3949).
+ 3. whether the device is locked (defined as "keyguard is showing").
+5. If the device is unlocked (no keyguard), the camera is launched immediately. [Callsite in onCameraLaunchGestureDetected](/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java#4047).
6. If the keyguard is up, however, [KeyguardBottomAreaView.launchCamera](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#477) takes over to handle the "secure camera" (a different intent, usually directing to the same app, but giving that app the cue to not allow access to the photo roll, etc).
7. If the intent [would have to launch a resolver](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#480) (the user has multiple cameras installed and hasn’t chosen one to always launch for the `SECURE_CAMERA_INTENT`),
1. In order to show the resolver, the lockscreen "bouncer" (authentication method) [is first presented](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#523).
@@ -26,8 +26,9 @@
* If the keyguard is not showing (device is unlocked)
- * `KeyguardBottomAreaView.INSECURE_CAMERA_INTENT`, defined to be `MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA`.
+ * `CameraIntents.getInsecureCameraIntent()`, defined to be `MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA`.
* [Callsite](/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java#3950) in StatusBar.java.
* If the keyguard is showing (device locked)
- * [KeyguardBottomAreaView.getCameraIntent()](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#366) is consulted, which allows the "keyguard right button" (which we don’t actually show) to control the camera intent. The [default implementation](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#831) returns one of `KeyguardBottomAreaView.INSECURE_CAMERA_INTENT` or `KeyguardBottomAreaView.SECURE_CAMERA_INTENT`, which are `MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA` and `MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE`, respectively.
+ * [KeyguardBottomAreaView.getCameraIntent()](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#366) is consulted, which allows the "keyguard right button" (which we don’t actually show) to control the camera intent. The [default implementation](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#831) returns one of `CameraIntents.getInsecureCameraIntent()` or `CameraIntents.getSecureCameraIntent()`, which are `MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA` and `MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE`, respectively.
* [Callsite](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#523) in KeyguardBottomAreaView.java.
+* Note that starting in Android 12, as required by some OEMs, if the special string resource `config_cameraGesturePackage` is nonempty, this will be treated as a package name to be added to the insecure camera intent, constraining the invocation to that single app and typically preventing implicit intent resolution. This package must be on the device or the camera gesture will no longer work properly.
\ No newline at end of file
diff --git a/packages/SystemUI/docs/falsing.md b/packages/SystemUI/docs/falsing.md
new file mode 100644
index 0000000..e224ca8
--- /dev/null
+++ b/packages/SystemUI/docs/falsing.md
@@ -0,0 +1,240 @@
+# Falsing in SystemUI
+
+Phones are easily and often accidentally-activated in owners' pockets ("falsing" or "pocket
+dialing"). Because a phone's screen can be turned on with a single tap, and because we have further
+actions that be activated with basic tapping and swiping, it is critical that we
+analyze touch events on the screen for intentional vs accidental behavior. With analysis,
+features within SystemUI have an opportunity to ignore or even undo accidental interactions as they
+are occurring.
+
+## Technical Details
+
+The `FalsingManager` tracks all touch interactions happening on a phone's lock screen.
+
+If you support any sort of touch gestures on the lock screen, you **must**, at a
+minimum, inform the `FalsingManager` of what touches are on touch targets vs not (things that may be
+ intentional). If you do not tell the `FalsingManager`, it will assume touches on your feature are
+always accidental and penalize the session accordingly.
+
+Individual touch targets do not _have_ to be separated out; it's acceptable to
+wrap your whole feature in one virtual block that reports touches to the
+`FalsingManager`, however more granular tracking will result in better results
+across the whole lock screen.
+
+You can _act_ on the results of the `FalsingManager`. Instead of only telling
+the `FalsingManager` that touch events were on touch targets, you can further use the
+returned results to decide if you want to respond to an owner's touch, if you
+want to prompt them to confirm their action, or if you simply want to ignore the
+touch.
+
+The flow through the system looks like such:
+
+1. Gesture on the screen.
+2. The `FalsingManager` makes a note of all of the `MotionEvents`.
+ * If no feature/touch target receives the `MotionEvents`, skip to 4.
+3. Your touch target receives the `MotionEvents`.
+ * Once your feature is ready to respond to the gesture in a substantive manner, it queries
+ the `FalsingManager`.
+ - Dragging animations, touch ripples, and other purely visual effects should not query.
+ - Query once you are ready to launch a new feature or dialogue, or are otherwise going to
+ change the state of the UI.
+ - Generally, wait until `MotionEvent.ACTION_UP` to query or `View.OnClickListener#onClick`.
+ - Only query once per gesture, at the end.
+ * If the `FalsingManager` says it looks good, respond to the touch.
+4. The `FalsingManager` checks to see if anyone queried about the gesture. If not, mark it as
+ accidental.
+
+There is also an event fired by the `FalsingManager` that can be listened to by anyone, that
+indicates that the the `FalsingManager` believes the phone is actively being pocket-dialed. When
+fired, modal features, such as quick settings, keyguard bouncer, and others should retract
+themselves to prevent further pocket-dialing.
+
+## Falsing "Belief" and History
+
+The `FalsingManager` maintains a recent history of false analyses. Using
+Bayesian statistics, it updates a "belief" in whether recent
+gestures are intentional or not. Any gesture that it is not explicitly queried about is treated as
+accidental, increasing the overall belief in
+false-iness. Gestures that are explicitly queried and that pass the relevant heuristics
+reduce belief that falsing is occurring. This information is tracked within the `HistoryTracker`.
+
+Changes in belief may influence internal heurstics within the `FalsingManager`,
+making it easier or harder for an owner to interact with their device. (An owner
+will always be able to interact with their device, but we may require double
+taps, or more deliberate swipes.)
+
+## Responding to Touch Events
+
+The methods below inform the `FalsingManager` that a tap is occurring within an expected touch
+target. Match the methods with the gesture you expect the device owner to use.
+
+### Single Tap
+
+`FalsingManager#isFalseTap(boolean robustCheck, double falsePenalty)`. This
+method tells the `FalsingManager` that you want to validate a single tap. It
+returns true if it thinks the tap should be rejected (i.e. the tap looks more
+like a swipe) and false otherwise.
+
+`robustCheck` determines what heuristics are used. If set to false, the method
+performs a only very basic checking, checking that observed `MotionEvent`s are
+all within some small x & y region ("touch slop").
+
+When `robustCheck` is set to true, several more advanced rules are additionally
+applied:
+
+1. If the device recognizes a face (i.e. face-auth) the tap is **accepted**.
+2. If the tap is the _second_ tap in recent history and looks like a valid Double Tap
+ the tap is **accepted**. This works exactly like `FalsingManager#isFalseDoubleTap`.
+3. If the `HistoryTracker` reports strong belief in recent falsing, the tap is
+ **rejected**.
+4. Otherwise the tap is **accepted**.
+
+All the above rules are applied only after first confirming the gesture does
+in fact look like a basic tap.
+
+`falsePenalty` is a measure of how much the `HistoryTracker`'s belief should be
+penalized in the event that the tap is rejected. This value is only used if
+`robustCheck` is set to true.
+
+A value of `0` means no change in belief. A value of `1` means a _very_ strong
+confidence in a false tap. In general, as a single tap on the screen is not
+verifiable, a small value should be supplied - on the order of `0.1`. Pass `0`
+if you don't want to penalize belief at all. Pass a higher value
+the earlier in the UX flow your interaction occurs. Once an owner is farther
+along in a UX flow (multiple taps or swipes), its safer to assume that a single
+accidental tap should cause less of a penalty.
+
+### Double Tap
+
+`FalsingManager#isFalseDoubleTap()`. This method tells the `FalsingManager` that
+your UI wants to validate a double tap. There are no parameters to pass to this method.
+Call this when you explicitly receive and want to verify a double tap, _not_ a single tap.
+
+Note that `FalsingManager#isFalseTap(boolean robustCheck, double falsePenalty)`
+will also check for double taps when `robustCheck` is set to true. If you are
+willing to use single taps, use that instead.
+
+### Swipes and Other Gestures
+
+`FalsingManager#isFalseTouch(@Classifier.InteractionType int interactionType)`.
+Use this for any non-tap interactions. This includes expanding notifications,
+expanding quick settings, pulling up the bouncer, and more. You must pass
+the type of interaction you are evaluating when calling it. A large set of
+heuristics will be applied to analyze the gesture, and the exact rules vary depending upon
+the `InteractionType`.
+
+### Ignoring A Gesture
+
+`FalsingCollector#avoidGesture()`. Tell the `FalsingManager` to pretend like the
+observed gesture never happened. **This method must be called when the observed
+`MotionEvent` is `MotionEvent.ACTION_DOWN`.** Attempting to call this method
+later in a gesture will not work.
+
+Notice that this method is actually a method on `FalsingCollector`. It is
+forcefully telling the `FalsingManager` to wholly pretend the gesture never
+happened. This is intended for security and PII sensitive gestures, such as
+password inputs. Please don't use this as a shortcut for avoiding the
+FalsingManager. Falsing works better the more behavior it is told about.
+
+### Other Considerations
+
+Please try to call the `FalsingManager` only once per gesture. Wait until you
+are ready to act on the owner's action, and then query the `FalsingManager`. The `FalsingManager`
+will update its belief in pocket dialing based only on the last call made, so multiple calls per
+gesture are not well defined.
+
+The `FalsingManager` does not update its belief in pocket-dialing until a new
+gesture starts. That is to say, if the owner makes a bad tap on your feature,
+the belief in pocket dialing will not incorporate this new data until the
+following gesture begins.
+
+If you expect a mix of taps, double taps, and swipes on your feature, segment them
+accordingly. Figure out which `FalsingManager` method you need to call first, rather than relying
+on multiple calls to the `FalsingManager` to act as a sieve.
+
+Don't:
+```
+if (!mFalsingManager.isFalseTap(false, 0)) {
+ // its a tap
+} else if (!mFalsingManager.isFalseTouch(GESTURE_A) {
+ // do thing a
+} else if (!mFalsingManager.isFalseTouch(GESTURE_B) {
+ // do thing b
+} else {
+ // must be a false.
+}
+```
+
+Do:
+```
+void onTap() {
+ if (!mFalsingManager.isFalseTap(false, 0)) {
+ // its a tap
+}
+
+void onGestureA() {
+ if (!mFalsingManager.isFalseTouch(GESTURE_A) {
+ // do thing a
+ }
+}
+
+void onGestureB() {
+ if (!mFalsingManager.isFalseTouch(GESTURE_B) {
+ // do thing b
+ }
+}
+```
+
+
+## Influencing Belief
+
+`FalsingCollector#updateFalseConfidence(FalsingClassifier.Result result)`. This
+method allows you to directly change the `FalsingManager`'s belief in the state
+of pocket dialing. If the owner does something unusual with their phone that you
+think indicates pocket dialing, you can call:
+
+```
+ mFalsingCollector.updateFalseConfidence(
+ FalsingClassifier.Result.falsed(0.6, "Owner is doing something fishy"));
+```
+
+A belief value of `1` indicates a 100% confidence of false behavior. A belief
+value of `0` would make no change in the `FalsingManager` and should be avoided
+as it simply creates noise in the logs. Generally, a middle value between the
+two extremes makes sense.
+
+A good example of where this is used is in the "Pattern" password input. We
+avoid recording those gestures in the `FalsingManager`, but we have the pattern input update
+the `FalsingManager` directly in some cases. If the owner simply taps on the pattern input, we
+record it as a false, (patterns are always 4 "cells" long, so single "cell" inputs are penalized).
+
+Conversely, if you think the owner does something that deserves a nice reward:
+
+```
+ mFalsingCollector.updateFalseConfidence(
+ FalsingClassifier.Result.passed(0.6));
+```
+
+Again, useful on password inputs where the FalsingManager is avoiding recording
+the gesture. This is used on the "pin" password input, to recognize successful
+taps on the input buttons.
+
+## Global Falsing Event
+
+If the `FalsingManager`'s belief in falsing crosses some internally defined
+threshold, it will fire an event that other parts of the system can listen for.
+This even indicates that the owner is likely actively pocket-dialing, and any
+currently open activities on the phone should retract themselves.
+
+To subscribe to this event, call
+`FalsingManager#addFalsingBeliefListener(FalsingBeliefListener listener)`.
+`FalsingBeliefListener` is a simple one method interface that will be called
+after when activities should retract themselves.
+
+**Do Listen For This**. Your code will work without it, but it is a handy,
+universal signal that will save the phone owner a lot of accidents. A simple
+implementation looks like:
+
+```
+ mFalsingManager.addFalsingBeliefListener(MyFeatureClass::hide);
+```
diff --git a/packages/SystemUI/res/color/remote_input_hint.xml b/packages/SystemUI/res/color/remote_input_hint.xml
new file mode 100644
index 0000000..7fe58db
--- /dev/null
+++ b/packages/SystemUI/res/color/remote_input_hint.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?android:attr/textColorPrimary" android:alpha=".6" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/remote_input_text.xml b/packages/SystemUI/res/color/remote_input_text.xml
index 33eeb77..3622c91 100644
--- a/packages/SystemUI/res/color/remote_input_text.xml
+++ b/packages/SystemUI/res/color/remote_input_text.xml
@@ -16,6 +16,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="true" android:color="?android:attr/textColorTertiary" />
- <item android:color="?android:attr/textColorTertiary" android:alpha=".6" />
+ <item android:state_enabled="true" android:color="?android:attr/textColorPrimary" />
+ <item android:color="?android:attr/textColorPrimary" android:alpha=".6" />
</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
index 41140a7..f8f455d 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
@@ -17,7 +17,8 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true">
- <item android:id="@+id/slider_foreground">
+ <item android:id="@+id/slider_foreground"
+ android:height="@dimen/rounded_slider_height">
<shape>
<size android:height="@dimen/rounded_slider_height" />
<solid android:color="?android:attr/colorControlActivated" />
diff --git a/packages/SystemUI/res/drawable/ic_reduce_bright_colors.xml b/packages/SystemUI/res/drawable/ic_reduce_bright_colors.xml
new file mode 100644
index 0000000..fe4cc78
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_reduce_bright_colors.xml
@@ -0,0 +1,49 @@
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M17,12.1L15.59,10.69L13.05,13.22V7.05H11.05V13.22L8.51,10.69L7.1,12.1L12.05,17.05L17,12.1Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M2.05,13.05H4.05C4.6,13.05 5.05,12.6 5.05,12.05C5.05,11.5 4.6,11.05 4.05,11.05H2.05C1.5,11.05 1.05,11.5 1.05,12.05C1.05,12.6 1.5,13.05 2.05,13.05Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M20.05,13.05H22.05C22.6,13.05 23.05,12.6 23.05,12.05C23.05,11.5 22.6,11.05 22.05,11.05H20.05C19.5,11.05 19.05,11.5 19.05,12.05C19.05,12.6 19.5,13.05 20.05,13.05Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M11.05,2.05V4.05C11.05,4.6 11.5,5.05 12.05,5.05C12.6,5.05 13.05,4.6 13.05,4.05V2.05C13.05,1.5 12.6,1.05 12.05,1.05C11.5,1.05 11.05,1.5 11.05,2.05Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M11.05,20.05V22.05C11.05,22.6 11.5,23.05 12.05,23.05C12.6,23.05 13.05,22.6 13.05,22.05V20.05C13.05,19.5 12.6,19.05 12.05,19.05C11.5,19.05 11.05,19.5 11.05,20.05Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M6.04,4.63C5.65,4.24 5.01,4.24 4.63,4.63C4.24,5.02 4.24,5.66 4.63,6.04L5.69,7.1C6.08,7.49 6.72,7.49 7.1,7.1C7.49,6.71 7.49,6.07 7.1,5.69L6.04,4.63Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M18.41,17C18.02,16.61 17.38,16.61 17,17C16.61,17.39 16.61,18.03 17,18.41L18.06,19.47C18.45,19.86 19.09,19.86 19.47,19.47C19.86,19.08 19.86,18.44 19.47,18.06L18.41,17Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M19.47,6.04C19.86,5.65 19.86,5.01 19.47,4.63C19.08,4.24 18.44,4.24 18.06,4.63L17,5.69C16.61,6.08 16.61,6.72 17,7.1C17.39,7.49 18.03,7.49 18.41,7.1L19.47,6.04Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M7.1,18.41C7.49,18.02 7.49,17.38 7.1,17C6.71,16.61 6.07,16.61 5.69,17L4.63,18.06C4.24,18.45 4.24,19.09 4.63,19.47C5.02,19.86 5.66,19.86 6.04,19.47L7.1,18.41Z"
+ android:fillColor="#000000"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/notif_footer_btn_background.xml b/packages/SystemUI/res/drawable/notif_footer_btn_background.xml
new file mode 100644
index 0000000..f35f5d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notif_footer_btn_background.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid
+ android:color="@color/notif_pill_background"
+ />
+ <corners android:radius="20dp" />
+
+ <padding
+ android:left="20dp"
+ android:right="20dp">
+ </padding>
+
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/remote_input_view_text_bg.xml b/packages/SystemUI/res/drawable/remote_input_view_text_bg.xml
new file mode 100644
index 0000000..5d374a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/remote_input_view_text_bg.xml
@@ -0,0 +1,31 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <solid android:color="?android:attr/colorBackgroundFloating" />
+ <stroke
+ android:width="@dimen/remote_input_view_text_stroke"
+ android:color="?android:attr/colorAccent"/>
+ <padding
+ android:bottom="12dp"
+ android:left="12dp"
+ android:right="12dp"
+ android:top="12dp"/>
+
+ <corners android:radius="24dp" />
+
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
index 44f52ef..bbf69a9 100644
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
@@ -18,32 +18,52 @@
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/quick_qs_status_icons"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/qs_header_top_padding"
- android:paddingBottom="@dimen/qs_header_bottom_padding"
- android:layout_below="@id/quick_status_bar_system_icons"
+ android:layout_height="@*android:dimen/quick_qs_offset_height"
android:clipChildren="false"
android:clipToPadding="false"
- android:minHeight="20dp"
+ android:minHeight="48dp"
android:clickable="false"
android:focusable="true"
android:theme="@style/QSHeaderTheme">
- <com.android.systemui.statusbar.policy.DateView
- android:id="@+id/date"
+ <com.android.systemui.statusbar.policy.Clock
+ android:id="@+id/clock"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start|center_vertical"
- android:gravity="center_vertical"
+ android:layout_height="match_parent"
+ android:minWidth="48dp"
+ android:minHeight="48dp"
+ android:gravity="center_vertical|start"
+ android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
+ android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status"
- systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock" />
+
+ <View
+ android:layout_height="match_parent"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ />
+
+ <!-- Will hold security footer in landscape with media -->
+ <FrameLayout
+ android:id="@+id/header_text_container"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:gravity="center"
+ />
+
+ <include layout="@layout/qs_carrier_group"
+ android:id="@+id/carrier_group"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:minHeight="48dp"
+ android:layout_gravity="end|center_vertical"
+ android:focusable="false"/>
<com.android.systemui.statusbar.phone.StatusIconContainer
android:id="@+id/statusIcons"
- android:layout_width="0dp"
+ android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_weight="1"
android:paddingEnd="@dimen/signal_cluster_battery_padding" />
<com.android.systemui.BatteryMeterView
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml
index 4f4b2af..6cee38d 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml
@@ -16,8 +16,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:layout_gravity="center"
- style="@style/BrightnessDialogContainer">
+ android:layout_gravity="center">
<com.android.systemui.settings.brightness.BrightnessSliderView
android:id="@+id/brightness_slider"
@@ -35,6 +34,8 @@
android:minHeight="48dp"
android:thumb="@null"
android:background="@null"
+ android:paddingStart="0dp"
+ android:paddingEnd="0dp"
android:progressDrawable="@drawable/brightness_progress_drawable_thick"
android:splitTrack="false"
/>
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
deleted file mode 100644
index fb82304..0000000
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ /dev/null
@@ -1,101 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/header_text_container"
- android:layout_width="match_parent"
- android:layout_height="@dimen/qs_header_tooltip_height"
- android:layout_below="@id/quick_status_bar_system_icons"
- android:visibility="invisible"
- android:theme="@style/QSHeaderTheme"
- android:forceHasOverlappingRendering="false">
-
- <com.android.systemui.qs.QSHeaderInfoLayout
- android:id="@+id/status_container"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:id = "@+id/alarm_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center_vertical"
- android:focusable="true"
- android:clickable="true">
-
- <ImageView
- android:id="@+id/next_alarm_icon"
- android:layout_width="@dimen/qs_header_alarm_icon_size"
- android:layout_height="@dimen/qs_header_alarm_icon_size"
- android:src="@drawable/ic_alarm"
- android:contentDescription="@string/accessibility_quick_settings_alarm_set"
- android:visibility="gone"/>
-
- <com.android.systemui.util.AutoMarqueeTextView
- android:id="@+id/next_alarm_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:marqueeRepeatLimit="marquee_forever"
- android:layout_marginStart="@dimen/qs_header_alarm_text_margin_start"
- android:textAppearance="@style/TextAppearance.QS.Status"
- android:visibility="gone"/>
- </LinearLayout>
-
- <View
- android:id="@+id/status_separator"
- android:layout_width="@dimen/qs_header_separator_width"
- android:layout_height="match_parent"
- android:visibility="gone"/>
-
- <LinearLayout
- android:id = "@+id/ringer_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center_vertical"
- android:focusable="true"
- android:clickable="true">
-
- <ImageView
- android:id="@+id/ringer_mode_icon"
- android:layout_width="@dimen/qs_header_alarm_icon_size"
- android:layout_height="@dimen/qs_header_alarm_icon_size"
- android:visibility="gone"/>
-
- <com.android.systemui.util.AutoMarqueeTextView
- android:id="@+id/ringer_mode_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:marqueeRepeatLimit="marquee_forever"
- android:layout_marginStart="@dimen/qs_header_alarm_text_margin_start"
- android:textAppearance="@style/TextAppearance.QS.Status"
- android:visibility="gone"/>
- </LinearLayout>
- </com.android.systemui.qs.QSHeaderInfoLayout>
-
- <include layout="@layout/qs_carrier_group"
- android:id="@+id/carrier_group"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginStart="@dimen/qs_status_separator"
- android:layout_gravity="end|center_vertical"
- android:focusable="false"/>
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 059bda3..5bf6919 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -32,26 +32,32 @@
android:paddingStart="0dp"
android:elevation="4dp" >
- <!-- The clock -->
- <include layout="@layout/quick_status_bar_header_system_icons" />
+ <!-- Date and privacy. Only visible in QS -->
+ <include layout="@layout/quick_status_bar_header_date_privacy"/>
- <!-- Status icons within the panel itself (and not in the top-most status bar) -->
- <include layout="@layout/quick_qs_status_icons" />
-
- <!-- Layout containing tooltips, alarm text, etc. -->
- <include layout="@layout/quick_settings_header_info" />
+ <RelativeLayout
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:clipChildren="false"
+ android:clipToPadding="false">
+ <!-- Time, icons and Carrier (only in QS) -->
+ <include layout="@layout/quick_qs_status_icons"/>
<com.android.systemui.qs.QuickQSPanel
android:id="@+id/quick_qs_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/quick_qs_status_icons"
- android:accessibilityTraversalAfter="@+id/date_time_group"
+ android:layout_marginTop="8dp"
+ android:accessibilityTraversalAfter="@id/quick_qs_status_icons"
android:accessibilityTraversalBefore="@id/expand_indicator"
android:clipChildren="false"
android:clipToPadding="false"
android:focusable="true"
android:paddingBottom="10dp"
android:importantForAccessibility="yes" />
+ </RelativeLayout>
</com.android.systemui.qs.QuickStatusBarHeader>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
similarity index 72%
rename from packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
rename to packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
index f663ab4e..22cf2cb 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
@@ -17,33 +17,35 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/quick_status_bar_system_icons"
+ android:id="@+id/quick_status_bar_date_privacy"
android:layout_width="match_parent"
android:layout_height="@*android:dimen/quick_qs_offset_height"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
+ android:layout_gravity="top"
android:orientation="horizontal"
android:clickable="true"
- android:paddingTop="@dimen/status_bar_padding_top" >
+ android:paddingTop="@dimen/status_bar_padding_top"
+ android:minHeight="48dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
+ android:minHeight="48dp"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center_vertical|start" >
- <com.android.systemui.statusbar.policy.Clock
- android:id="@+id/clock"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:minWidth="48dp"
- android:gravity="center_vertical|start"
- android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
- android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock" />
+ <com.android.systemui.statusbar.policy.DateView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start|center_vertical"
+ android:gravity="center_vertical"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.QS.Status"
+ systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
</LinearLayout>
<android.widget.Space
@@ -56,6 +58,7 @@
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
+ android:minHeight="48dp"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center_vertical|end" >
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index 43182eb..ae3adb8 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -25,26 +25,25 @@
<view class="com.android.systemui.statusbar.policy.RemoteInputView$RemoteEditText"
android:id="@+id/remote_input_text"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:paddingTop="2dp"
- android:paddingBottom="4dp"
android:paddingStart="16dp"
android:paddingEnd="12dp"
- android:layout_marginRight="5dp"
+ android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="5dp"
- android:layout_marginBottom="20dp"
- android:gravity="start|center_vertical"
+ android:layout_marginBottom="16dp"
+ android:layout_gravity="start|center_vertical"
android:textAppearance="?android:attr/textAppearance"
android:textColor="@color/remote_input_text"
android:textColorHint="@color/remote_input_hint"
android:textSize="16sp"
android:background="@null"
- android:singleLine="true"
+ android:maxLines="4"
android:ellipsize="start"
- android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
+ android:inputType="textShortMessage|textMultiLine|textAutoCorrect|textCapSentences"
android:imeOptions="actionSend|flagNoExtractUi|flagNoFullscreen" />
<FrameLayout
@@ -53,12 +52,12 @@
android:layout_gravity="center_vertical">
<ImageButton
- android:layout_width="wrap_content"
+ android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
- android:paddingBottom="20dp"
- android:paddingStart="12dp"
- android:paddingEnd="24dp"
+ android:paddingLeft="10dp"
+ android:layout_marginBottom="12dp"
+ android:layout_marginEnd="12dp"
android:id="@+id/remote_input_send"
android:src="@drawable/ic_send"
android:contentDescription="@*android:string/ime_action_send"
@@ -70,9 +69,8 @@
android:id="@+id/remote_input_progress"
android:layout_width="24dp"
android:layout_height="24dp"
- android:layout_marginBottom="10dp"
- android:layout_marginEnd="6dp"
- android:layout_gravity="center"
+ android:layout_marginBottom="12dp"
+ android:layout_gravity="center_vertical"
android:visibility="invisible"
android:indeterminate="true"
style="?android:attr/progressBarStyleSmall" />
diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
index 5a1e5c4..5c77d16 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_footer.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
@@ -30,9 +30,11 @@
style="@style/TextAppearance.NotificationSectionHeaderButton"
android:id="@+id/manage_text"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="40dp"
android:layout_gravity="start"
+ android:background="@drawable/notif_footer_btn_background"
android:focusable="true"
+ android:textColor="@color/notif_pill_text"
android:contentDescription="@string/manage_notifications_history_text"
android:text="@string/manage_notifications_history_text"
/>
@@ -40,8 +42,9 @@
style="@style/TextAppearance.NotificationSectionHeaderButton"
android:id="@+id/dismiss_text"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="40dp"
android:layout_gravity="end"
+ android:background="@drawable/notif_footer_btn_background"
android:focusable="true"
android:contentDescription="@string/accessibility_clear_all"
android:text="@string/clear_all_notifications_text"
diff --git a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
index e9c8389..7aca9f8 100644
--- a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
+++ b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
@@ -46,7 +46,7 @@
// Transform it using the S curve created by the smoothstep. This will increase the contrast.
lum = smoothstep(0., 1., lum) + 0.001;
- lum = relativeExposureCompensation(lum, mix(-15., 10., uExposure));
+ lum = relativeExposureCompensation(lum, mix(-5., 10., uExposure));
lum = mix(clamp(lum, 0.0, 1.0), 1.0, normalizedRange(uExposure, 0.55, 1.0));
color.rgb *= lum;
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 9959c67..c10add2 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -33,6 +33,9 @@
<!-- The color of the text inside a notification -->
<color name="notification_primary_text_color">@*android:color/notification_primary_text_color_dark</color>
+ <color name="notif_pill_background">@android:color/system_neutral1_800</color>
+ <color name="notif_pill_text">@android:color/system_neutral1_50</color>
+
<color name="notification_guts_link_icon_tint">@color/GM2_grey_500</color>
<color name="notification_guts_sub_text_color">@color/GM2_grey_300</color>
<color name="notification_guts_header_text_color">@color/GM2_grey_200</color>
@@ -74,7 +77,7 @@
<!-- Biometric dialog colors -->
<color name="biometric_dialog_gray">#ffcccccc</color>
- <color name="biometric_dialog_accent">#ff80cbc4</color> <!-- light teal -->
+ <color name="biometric_dialog_accent">@android:color/system_accent1_300</color>
<color name="biometric_dialog_error">#fff28b82</color> <!-- red 300 -->
<!-- UDFPS colors -->
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 4e3e64a..e505863 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -151,8 +151,8 @@
<color name="minimize_dock_shadow_end">#00000000</color>
<color name="default_remote_input_background">@*android:color/notification_default_color</color>
- <color name="remote_input_hint">#99ffffff</color>
-
+ <color name="notif_pill_background">@android:color/system_neutral2_100</color>
+ <color name="notif_pill_text">@android:color/system_neutral1_900</color>
<color name="remote_input_accent">?android:attr/colorAccent</color>
<color name="quick_step_track_background_background_dark">#1F000000</color>
@@ -177,7 +177,7 @@
<!-- Biometric dialog colors -->
<color name="biometric_dialog_dim_color">#80000000</color> <!-- 50% black -->
<color name="biometric_dialog_gray">#ff757575</color>
- <color name="biometric_dialog_accent">#ff008577</color> <!-- dark teal -->
+ <color name="biometric_dialog_accent">@android:color/system_accent1_600</color>
<color name="biometric_dialog_error">#ffd93025</color> <!-- red 600 -->
<!-- UDFPS colors -->
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 6e61148..d37d239 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -589,6 +589,10 @@
<!-- Determines whether the shell features all run on another thread. -->
<bool name="config_enableShellMainThread">false</bool>
+ <!-- package name of a built-in camera app to use to restrict implicit intent resolution
+ when the double-press power gesture is used. Ignored if empty. -->
+ <string translatable="false" name="config_cameraGesturePackage"></string>
+
<!-- Determines whether to allow the nav bar handle to be forced to be opaque. -->
<bool name="allow_force_nav_bar_handle_opaque">true</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d5c6398..f722c94 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -19,6 +19,8 @@
<!-- Recommended minimum clickable element dimension -->
<dimen name="min_clickable_item_size">48dp</dimen>
+ <dimen name="remote_input_view_text_stroke">3dp</dimen>
+
<!-- Amount to offset bottom of notification peek window from top of status bar. -->
<dimen name="peek_window_y_offset">-12dp</dimen>
@@ -1396,4 +1398,19 @@
<dimen name="rounded_slider_track_width">8dp</dimen>
<!-- rounded_slider_track_width / 2 -->
<dimen name="rounded_slider_track_corner_radius">4dp</dimen>
+
+ <!-- Location on the screen of the center of the physical power button. This is a reasonable
+ default that should be overridden by device-specific overlays. -->
+ <dimen name="physical_power_button_center_screen_location_y">620px</dimen>
+
+ <!-- Location on the screen of the center of the physical volume up/down buttons. This is a
+ reasonable default that should be overridden by device-specific overlays. -->
+ <dimen name="physical_volume_up_button_center_screen_location_y">950px</dimen>
+ <dimen name="physical_volume_down_button_center_screen_location_y">1150px</dimen>
+
+ <!-- Location on the screen of the center of the fingerprint sensor. For devices with under
+ display fingerprint sensors, this directly corresponds to the fingerprint sensor's location.
+ For devices with sensors on the back of the device, this corresponds to the location on the
+ screen directly in front of the sensor. -->
+ <dimen name="physical_fingerprint_sensor_center_screen_location_y">610px</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3ca885a..a815318 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -424,6 +424,12 @@
<string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
<!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_fingerprint_dialog_fingerprint_icon">Fingerprint icon</string>
+ <!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
+ <string name="fingerprint_dialog_use_fingerprint_instead">Can\u2019t recognize face. Use fingerprint instead.</string>
+ <!-- Message shown to ask the user to use fingerprint to continue.[CHAR LIMIT=50] -->
+ <string name="fingerprint_dialog_use_fingerprint">Use your fingerprint to continue</string>
+ <!-- Message shown to ask the user to use screenlock to continue.[CHAR LIMIT=NONE] -->
+ <string name="fingerprint_dialog_cant_recognize_fp_use_screenlock">Can\u2019t recognize fingerprint. Use screen lock instead.</string>
<!-- Message shown when the system-provided face dialog is shown, asking for authentication [CHAR LIMIT=30] -->
<string name="face_dialog_looking_for_face">Looking for you\u2026</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
index f50c3c92..7cd7c9e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
@@ -16,11 +16,15 @@
package com.android.systemui.shared.pip;
+import static android.graphics.Matrix.MSCALE_X;
+import static android.graphics.Matrix.MSCALE_Y;
+
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.Choreographer;
import android.view.SurfaceControl;
+import android.window.PictureInPictureSurfaceTransaction;
/**
* TODO(b/171721389): unify this class with
@@ -28,22 +32,32 @@
* source of truth on enabling/disabling and the actual value of corner radius.
*/
public class PipSurfaceTransactionHelper {
+ /** corner radius is currently disabled. */
+ private final float mCornerRadius = 0f;
+
private final Matrix mTmpTransform = new Matrix();
private final float[] mTmpFloat9 = new float[9];
private final RectF mTmpSourceRectF = new RectF();
private final RectF mTmpDestinationRectF = new RectF();
private final Rect mTmpDestinationRect = new Rect();
- public void scale(SurfaceControl.Transaction tx, SurfaceControl leash,
+ public PictureInPictureSurfaceTransaction scale(
+ SurfaceControl.Transaction tx, SurfaceControl leash,
Rect sourceBounds, Rect destinationBounds) {
mTmpSourceRectF.set(sourceBounds);
mTmpDestinationRectF.set(destinationBounds);
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
- .setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top);
+ .setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top)
+ .setCornerRadius(leash, mCornerRadius);
+ return new PictureInPictureSurfaceTransaction(
+ mTmpDestinationRectF.left, mTmpDestinationRectF.top,
+ mTmpFloat9[MSCALE_X], mTmpFloat9[MSCALE_Y],
+ 0 /* rotation*/, mCornerRadius, sourceBounds);
}
- public void scale(SurfaceControl.Transaction tx, SurfaceControl leash,
+ public PictureInPictureSurfaceTransaction scale(
+ SurfaceControl.Transaction tx, SurfaceControl leash,
Rect sourceBounds, Rect destinationBounds,
float degree, float positionX, float positionY) {
mTmpSourceRectF.set(sourceBounds);
@@ -51,10 +65,16 @@
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
mTmpTransform.postRotate(degree, 0, 0);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
- .setPosition(leash, positionX, positionY);
+ .setPosition(leash, positionX, positionY)
+ .setCornerRadius(leash, mCornerRadius);
+ return new PictureInPictureSurfaceTransaction(
+ positionX, positionY,
+ mTmpFloat9[MSCALE_X], mTmpFloat9[MSCALE_Y],
+ degree, mCornerRadius, sourceBounds);
}
- public void scaleAndCrop(SurfaceControl.Transaction tx, SurfaceControl leash,
+ public PictureInPictureSurfaceTransaction scaleAndCrop(
+ SurfaceControl.Transaction tx, SurfaceControl leash,
Rect sourceBounds, Rect destinationBounds, Rect insets) {
mTmpSourceRectF.set(sourceBounds);
mTmpDestinationRect.set(sourceBounds);
@@ -69,10 +89,14 @@
mTmpTransform.setScale(scale, scale);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
- .setPosition(leash, left, top);
+ .setPosition(leash, left, top)
+ .setCornerRadius(leash, mCornerRadius);
+ return new PictureInPictureSurfaceTransaction(
+ left, top, scale, scale, 0 /* rotation */, mCornerRadius, mTmpDestinationRect);
}
- public void scaleAndRotate(SurfaceControl.Transaction tx, SurfaceControl leash,
+ public PictureInPictureSurfaceTransaction scaleAndRotate(
+ SurfaceControl.Transaction tx, SurfaceControl leash,
Rect sourceBounds, Rect destinationBounds, Rect insets,
float degree, float positionX, float positionY) {
mTmpSourceRectF.set(sourceBounds);
@@ -87,17 +111,10 @@
mTmpTransform.postScale(scale, scale);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
- .setPosition(leash, positionX, positionY);
- }
-
- public void resetCornerRadius(SurfaceControl.Transaction tx, SurfaceControl leash) {
- tx.setCornerRadius(leash, 0);
- }
-
- public void crop(SurfaceControl.Transaction tx, SurfaceControl leash,
- Rect destinationBounds) {
- tx.setWindowCrop(leash, destinationBounds.width(), destinationBounds.height())
- .setPosition(leash, destinationBounds.left, destinationBounds.top);
+ .setPosition(leash, positionX, positionY)
+ .setCornerRadius(leash, mCornerRadius);
+ return new PictureInPictureSurfaceTransaction(
+ positionX, positionY, scale, scale, degree, mCornerRadius, mTmpDestinationRect);
}
/** @return {@link SurfaceControl.Transaction} instance with vsync-id */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index bf0d29a..dde20c1 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -20,6 +20,7 @@
import android.os.RemoteException;
import android.util.Log;
import android.view.IRecentsAnimationController;
+import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -76,14 +77,12 @@
* accordingly. This should be called before `finish`
* @param taskId Task id of the Activity in PiP mode.
* @param destinationBounds Bounds of the PiP window on home.
- * @param windowCrop bounds to crop as part of final transform.
- * @param float9 An array of 9 floats to be used as matrix transform.
+ * @param finishTransaction leash operations for the final transform.
*/
- public void setFinishTaskBounds(int taskId, Rect destinationBounds, Rect windowCrop,
- float[] float9) {
+ public void setFinishTaskBounds(int taskId, Rect destinationBounds,
+ PictureInPictureSurfaceTransaction finishTransaction) {
try {
- mAnimationController.setFinishTaskBounds(taskId, destinationBounds, windowCrop,
- float9);
+ mAnimationController.setFinishTaskBounds(taskId, destinationBounds, finishTransaction);
} catch (RemoteException e) {
Log.d(TAG, "Failed to set finish task bounds", e);
}
@@ -152,4 +151,4 @@
Log.e(TAG, "Failed to detach the navigation bar from app", e);
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 246476a..7b3aa92 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -16,6 +16,8 @@
package com.android.systemui.shared.system;
+import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
+
import android.app.PictureInPictureParams;
import android.app.WindowConfiguration;
import android.graphics.Point;
@@ -57,6 +59,7 @@
public final Rect contentInsets;
public final PictureInPictureParams pictureInPictureParams;
public final int rotationChange;
+ public final int windowType;
private final SurfaceControl mStartLeash;
@@ -78,6 +81,7 @@
rotationChange = 0;
mStartLeash = app.startLeash;
+ windowType = app.windowType;
}
private static int newModeToLegacyMode(int newMode) {
@@ -118,6 +122,7 @@
pictureInPictureParams = null;
mStartLeash = null;
rotationChange = change.getEndRotation() - change.getStartRotation();
+ windowType = INVALID_WINDOW_TYPE;
}
public static RemoteAnimationTargetCompat[] wrap(RemoteAnimationTarget[] apps) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index 06155bc..4f3f86a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -32,6 +32,7 @@
import android.view.SurfaceControl;
import android.window.IRemoteTransition;
import android.window.IRemoteTransitionFinishedCallback;
+import android.window.PictureInPictureSurfaceTransaction;
import android.window.TransitionFilter;
import android.window.TransitionInfo;
import android.window.WindowContainerToken;
@@ -49,6 +50,8 @@
*/
@DataClass
public class RemoteTransitionCompat implements Parcelable {
+ private static final String TAG = "RemoteTransitionCompat";
+
@NonNull final IRemoteTransition mTransition;
@Nullable TransitionFilter mFilter = null;
@@ -56,6 +59,23 @@
mTransition = transition;
}
+ public RemoteTransitionCompat(RemoteTransitionRunner runner) {
+ mTransition = new IRemoteTransition.Stub() {
+ @Override
+ public void startAnimation(TransitionInfo info, SurfaceControl.Transaction t,
+ IRemoteTransitionFinishedCallback finishedCallback) {
+ final Runnable finishAdapter = () -> {
+ try {
+ finishedCallback.onTransitionFinished(null /* wct */);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to call transition finished callback", e);
+ }
+ };
+ runner.startAnimation(info, t, finishAdapter);
+ }
+ };
+ }
+
/** Constructor specifically for recents animation */
public RemoteTransitionCompat(RecentsAnimationListener recents,
RecentsAnimationControllerCompat controller) {
@@ -138,9 +158,9 @@
}
@Override public void setFinishTaskBounds(int taskId, Rect destinationBounds,
- Rect windowCrop, float[] float9) {
+ PictureInPictureSurfaceTransaction finishTransaction) {
if (mWrapped != null) {
- mWrapped.setFinishTaskBounds(taskId, destinationBounds, windowCrop, float9);
+ mWrapped.setFinishTaskBounds(taskId, destinationBounds, finishTransaction);
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionRunner.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionRunner.java
new file mode 100644
index 0000000..6002bca
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionRunner.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.system;
+
+import android.view.SurfaceControl;
+import android.window.TransitionInfo;
+
+/** Interface for something that runs a remote transition animation. */
+public interface RemoteTransitionRunner {
+ /**
+ * Starts a transition animation. Once complete, the implementation should call
+ * `finishCallback`.
+ */
+ void startAnimation(TransitionInfo info, SurfaceControl.Transaction t,
+ Runnable finishCallback);
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 9abc1e7..27a2ac3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -66,8 +66,10 @@
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
@@ -241,8 +243,10 @@
private final boolean mIsPrimaryUser;
private final boolean mIsAutomotive;
private final AuthController mAuthController;
+ private final PowerManager mPowerManager;
private final StatusBarStateController mStatusBarStateController;
private int mStatusBarState;
+ private boolean mDozing;
private final StatusBarStateController.StateListener mStatusBarStateControllerListener =
new StatusBarStateController.StateListener() {
@Override
@@ -250,6 +254,11 @@
mStatusBarState = newState;
updateBiometricListeningState();
}
+
+ @Override
+ public void onDozingChanged(boolean dozing) {
+ mDozing = dozing;
+ }
};
HashMap<Integer, SimData> mSimDatas = new HashMap<>();
@@ -1294,16 +1303,19 @@
private final FingerprintManager.AuthenticationCallback mFingerprintAuthenticationCallback
= new AuthenticationCallback() {
+ private boolean mIsUdfpsRunningWhileDozing;
@Override
public void onAuthenticationFailed() {
handleFingerprintAuthFailed();
+ cancelAodInterrupt();
}
@Override
public void onAuthenticationSucceeded(AuthenticationResult result) {
Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
handleFingerprintAuthenticated(result.getUserId(), result.isStrongBiometric());
+ cancelAodInterrupt();
Trace.endSection();
}
@@ -1315,6 +1327,7 @@
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
handleFingerprintError(errMsgId, errString.toString());
+ cancelAodInterrupt();
}
@Override
@@ -1325,12 +1338,25 @@
@Override
public void onUdfpsPointerDown(int sensorId) {
Log.d(TAG, "onUdfpsPointerDown, sensorId: " + sensorId);
+
+ if (mDozing) {
+ mIsUdfpsRunningWhileDozing = true;
+ }
}
@Override
public void onUdfpsPointerUp(int sensorId) {
Log.d(TAG, "onUdfpsPointerUp, sensorId: " + sensorId);
}
+
+ private void cancelAodInterrupt() {
+ if (mIsUdfpsRunningWhileDozing) {
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
+ "com.android.systemui:AOD_INTERRUPT_END");
+ }
+ mAuthController.onCancelAodInterrupt();
+ mIsUdfpsRunningWhileDozing = false;
+ }
};
private final FaceManager.FaceDetectionCallback mFaceDetectionCallback
@@ -1617,6 +1643,7 @@
LockPatternUtils lockPatternUtils,
AuthController authController,
TelephonyListenerManager telephonyListenerManager,
+ PowerManager powerManager,
FeatureFlags featureFlags) {
mContext = context;
mSubscriptionManager = SubscriptionManager.from(context);
@@ -1629,8 +1656,10 @@
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(mStatusBarStateControllerListener);
mStatusBarState = mStatusBarStateController.getState();
+ mDozing = mStatusBarStateController.isDozing();
mLockPatternUtils = lockPatternUtils;
mAuthController = authController;
+ mPowerManager = powerManager;
dumpManager.registerDumpable(getClass().getName(), this);
mHandler = new Handler(mainLooper) {
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java
index cd3d6a8..d7e0efc 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java
@@ -24,15 +24,15 @@
private int mCode;
private int mUid;
private String mPackageName;
- private long mTimeStarted;
+ private long mTimeStartedElapsed;
private StringBuilder mState;
private boolean mIsDisabled;
- public AppOpItem(int code, int uid, String packageName, long timeStarted) {
+ public AppOpItem(int code, int uid, String packageName, long timeStartedElapsed) {
this.mCode = code;
this.mUid = uid;
this.mPackageName = packageName;
- this.mTimeStarted = timeStarted;
+ this.mTimeStartedElapsed = timeStartedElapsed;
mState = new StringBuilder()
.append("AppOpItem(")
.append("Op code=").append(code).append(", ")
@@ -53,8 +53,8 @@
return mPackageName;
}
- public long getTimeStarted() {
- return mTimeStarted;
+ public long getTimeStartedElapsed() {
+ return mTimeStartedElapsed;
}
public void setDisabled(boolean misDisabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index e53f5c9..74f855b 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -50,6 +50,7 @@
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.util.Assert;
+import com.android.systemui.util.time.SystemClock;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -83,8 +84,8 @@
private final AppOpsManager mAppOps;
private final AudioManager mAudioManager;
private final LocationManager mLocationManager;
- private final PackageManager mPackageManager;
private final IndividualSensorPrivacyController mSensorPrivacyController;
+ private final SystemClock mClock;
// mLocationProviderPackages are cached and updated only occasionally
private static final long LOCATION_PROVIDER_UPDATE_FREQUENCY_MS = 30000;
@@ -126,7 +127,8 @@
PermissionFlagsCache cache,
AudioManager audioManager,
IndividualSensorPrivacyController sensorPrivacyController,
- BroadcastDispatcher dispatcher
+ BroadcastDispatcher dispatcher,
+ SystemClock clock
) {
mDispatcher = dispatcher;
mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
@@ -142,8 +144,8 @@
|| mSensorPrivacyController.isSensorBlocked(MICROPHONE);
mCameraDisabled = mSensorPrivacyController.isSensorBlocked(CAMERA);
mLocationManager = context.getSystemService(LocationManager.class);
- mPackageManager = context.getPackageManager();
mContext = context;
+ mClock = clock;
dumpManager.registerDumpable(TAG, this);
}
@@ -252,7 +254,7 @@
synchronized (mActiveItems) {
AppOpItem item = getAppOpItemLocked(mActiveItems, code, uid, packageName);
if (item == null && active) {
- item = new AppOpItem(code, uid, packageName, System.currentTimeMillis());
+ item = new AppOpItem(code, uid, packageName, mClock.elapsedRealtime());
if (code == AppOpsManager.OP_RECORD_AUDIO) {
item.setDisabled(isAnyRecordingPausedLocked(uid));
} else if (code == AppOpsManager.OP_CAMERA) {
@@ -294,7 +296,7 @@
synchronized (mNotedItems) {
item = getAppOpItemLocked(mNotedItems, code, uid, packageName);
if (item == null) {
- item = new AppOpItem(code, uid, packageName, System.currentTimeMillis());
+ item = new AppOpItem(code, uid, packageName, mClock.elapsedRealtime());
mNotedItems.add(item);
if (DEBUG) Log.w(TAG, "Added item: " + item.toString());
createdNew = true;
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index a7c1451..b2c620d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -59,7 +59,7 @@
*
* @param type one of INVOCATION_TYPE_GESTURE, INVOCATION_TYPE_ACTIVE_EDGE,
* INVOCATION_TYPE_VOICE, INVOCATION_TYPE_QUICK_SEARCH_BAR,
- * INVOCATION_HOME_BUTTON_LONG_PRESS
+ * INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS
* @param progress a float between 0 and 1 inclusive. 0 represents the beginning of the
* gesture; 1 represents the end.
*/
@@ -86,18 +86,27 @@
private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state";
- public static final String INVOCATION_TYPE_KEY = "invocation_type";
protected static final String ACTION_KEY = "action";
protected static final String SHOW_ASSIST_HANDLES_ACTION = "show_assist_handles";
protected static final String SET_ASSIST_GESTURE_CONSTRAINED_ACTION =
"set_assist_gesture_constrained";
protected static final String CONSTRAINED_KEY = "should_constrain";
- public static final int INVOCATION_TYPE_GESTURE = 1;
- public static final int INVOCATION_TYPE_OTHER = 2;
- public static final int INVOCATION_TYPE_VOICE = 3;
- public static final int INVOCATION_TYPE_QUICK_SEARCH_BAR = 4;
- public static final int INVOCATION_HOME_BUTTON_LONG_PRESS = 5;
+ public static final String INVOCATION_TYPE_KEY = "invocation_type";
+ public static final int INVOCATION_TYPE_UNKNOWN =
+ AssistUtils.INVOCATION_TYPE_UNKNOWN;
+ public static final int INVOCATION_TYPE_GESTURE =
+ AssistUtils.INVOCATION_TYPE_GESTURE;
+ public static final int INVOCATION_TYPE_OTHER =
+ AssistUtils.INVOCATION_TYPE_PHYSICAL_GESTURE;
+ public static final int INVOCATION_TYPE_VOICE =
+ AssistUtils.INVOCATION_TYPE_VOICE;
+ public static final int INVOCATION_TYPE_QUICK_SEARCH_BAR =
+ AssistUtils.INVOCATION_TYPE_QUICK_SEARCH_BAR;
+ public static final int INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS =
+ AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS;
+ public static final int INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS =
+ AssistUtils.INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS;
public static final int DISMISS_REASON_INVOCATION_CANCELLED = 1;
public static final int DISMISS_REASON_TAP = 2;
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistantInvocationEvent.kt b/packages/SystemUI/src/com/android/systemui/assist/AssistantInvocationEvent.kt
index fb5f1d1..f57acf6 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistantInvocationEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistantInvocationEvent.kt
@@ -59,15 +59,18 @@
ASSISTANT_INVOCATION_START_TOUCH_GESTURE(531),
@UiEvent(doc = "Assistant invocation started by physical gesture")
- ASSISTANT_INVOCATION_START_PHYSICAL_GESTURE(532);
+ ASSISTANT_INVOCATION_START_PHYSICAL_GESTURE(532),
+
+ @UiEvent(doc = "Assistant invoked by long press on the physical power button")
+ ASSISTANT_INVOCATION_POWER_LONG_PRESS(758);
override fun getId(): Int {
return id
}
companion object {
- fun eventFromLegacyInvocationType(legacyInvocationType: Int, isInvocationComplete: Boolean)
- : AssistantInvocationEvent {
+ fun eventFromLegacyInvocationType(legacyInvocationType: Int, isInvocationComplete: Boolean):
+ AssistantInvocationEvent {
return if (isInvocationComplete) {
when (legacyInvocationType) {
AssistManager.INVOCATION_TYPE_GESTURE ->
@@ -82,9 +85,12 @@
AssistManager.INVOCATION_TYPE_QUICK_SEARCH_BAR ->
ASSISTANT_INVOCATION_QUICK_SEARCH_BAR
- AssistManager.INVOCATION_HOME_BUTTON_LONG_PRESS ->
+ AssistManager.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS ->
ASSISTANT_INVOCATION_HOME_LONG_PRESS
+ AssistManager.INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS ->
+ ASSISTANT_INVOCATION_POWER_LONG_PRESS
+
else ->
ASSISTANT_INVOCATION_UNKNOWN
}
@@ -138,4 +144,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 7d06dd6..94b4c5f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -290,7 +290,7 @@
* called when authentication either succeeds or fails. Failing to cancel the scan will leave
* the screen in high brightness mode.
*/
- private void onCancelAodInterrupt() {
+ public void onCancelAodInterrupt() {
if (mUdfpsController == null) {
return;
}
@@ -397,10 +397,14 @@
showDialog(args, skipAnimation, null /* savedState */);
}
+ /**
+ * Only called via BiometricService for the biometric prompt. Will not be called for
+ * authentication directly requested through FingerprintManager. For
+ * example, KeyguardUpdateMonitor has its own {@link FingerprintManager.AuthenticationCallback}.
+ */
@Override
public void onBiometricAuthenticated() {
mCurrentDialog.onAuthenticationSucceeded();
- onCancelAodInterrupt();
}
@Override
@@ -428,6 +432,11 @@
}
}
+ /**
+ * Only called via BiometricService for the biometric prompt. Will not be called for
+ * authentication directly requested through FingerprintManager. For
+ * example, KeyguardUpdateMonitor has its own {@link FingerprintManager.AuthenticationCallback}.
+ */
@Override
public void onBiometricError(int modality, int error, int vendorCode) {
if (DEBUG) {
@@ -455,7 +464,6 @@
if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage);
mCurrentDialog.onError(errorMessage);
}
- onCancelAodInterrupt();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
new file mode 100644
index 0000000..464bee1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.camera
+
+import android.content.Context
+import android.content.Intent
+import android.provider.MediaStore
+import android.text.TextUtils
+
+import com.android.systemui.R
+
+interface CameraIntents {
+ companion object {
+ const val DEFAULT_SECURE_CAMERA_INTENT_ACTION =
+ MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE
+ const val DEFAULT_INSECURE_CAMERA_INTENT_ACTION =
+ MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA
+
+ @JvmStatic
+ fun getOverrideCameraPackage(context: Context): String? {
+ context.resources.getString(R.string.config_cameraGesturePackage)?.let {
+ if (!TextUtils.isEmpty(it)) {
+ return it
+ }
+ }
+ return null
+ }
+
+ @JvmStatic
+ fun getInsecureCameraIntent(context: Context): Intent {
+ val intent = Intent(DEFAULT_INSECURE_CAMERA_INTENT_ACTION)
+ getOverrideCameraPackage(context)?.let {
+ intent.setPackage(it)
+ }
+ return intent
+ }
+
+ @JvmStatic
+ fun getSecureCameraIntent(context: Context): Intent {
+ val intent = Intent(DEFAULT_SECURE_CAMERA_INTENT_ACTION)
+ getOverrideCameraPackage(context)?.let {
+ intent.setPackage(it)
+ }
+ return intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+ }
+
+ @JvmStatic
+ fun isSecureCameraIntent(intent: Intent): Boolean {
+ return intent.getAction().equals(DEFAULT_SECURE_CAMERA_INTENT_ACTION)
+ }
+
+ @JvmStatic
+ fun isInsecureCameraIntent(intent: Intent): Boolean {
+ return intent.getAction().equals(DEFAULT_INSECURE_CAMERA_INTENT_ACTION)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
index c7ad3e8..47b41f5 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
@@ -37,6 +37,7 @@
public static final int GENERIC = 7;
public static final int BOUNCER_UNLOCK = 8;
public static final int PULSE_EXPAND = 9;
+ public static final int BRIGHTNESS_SLIDER = 10;
@IntDef({
QUICK_SETTINGS,
@@ -48,7 +49,8 @@
RIGHT_AFFORDANCE,
GENERIC,
BOUNCER_UNLOCK,
- PULSE_EXPAND
+ PULSE_EXPAND,
+ BRIGHTNESS_SLIDER
})
@Retention(RetentionPolicy.SOURCE)
public @interface InteractionType {}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
index 5a9c386..80d7863 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
@@ -148,6 +148,10 @@
Result calculateFalsingResult(
@Classifier.InteractionType int interactionType,
double historyBelief, double historyConfidence) {
+ if (interactionType == Classifier.BRIGHTNESS_SLIDER) {
+ return Result.passed(0);
+ }
+
return !getPassedFlingThreshold() ? falsed(0.5, getReason()) : Result.passed(0.5);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
index ac330f0..6f80010 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
@@ -17,6 +17,7 @@
package com.android.systemui.classifier;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
import android.provider.DeviceConfig;
@@ -115,7 +116,7 @@
Result calculateFalsingResult(
@Classifier.InteractionType int interactionType,
double historyBelief, double historyConfidence) {
- if (interactionType == QUICK_SETTINGS) {
+ if (interactionType == QUICK_SETTINGS || interactionType == BRIGHTNESS_SLIDER) {
return Result.passed(0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
index 427c2ef..f665565 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
@@ -18,6 +18,7 @@
import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
import static com.android.systemui.classifier.Classifier.LEFT_AFFORDANCE;
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS;
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
@@ -45,6 +46,7 @@
boolean up = isUp();
boolean right = isRight();
+ double confidence = 1;
boolean wrongDirection = true;
switch (interactionType) {
case QUICK_SETTINGS:
@@ -52,6 +54,11 @@
case NOTIFICATION_DRAG_DOWN:
wrongDirection = !vertical || up;
break;
+ case BRIGHTNESS_SLIDER:
+ confidence = 0; // Owners may return to original brightness.
+ // A more sophisticated thing to do here would be to look at the size of the
+ // vertical change relative to the screen size. _Some_ amount of vertical
+ // change should be expected.
case NOTIFICATION_DISMISS:
wrongDirection = vertical;
break;
@@ -70,7 +77,7 @@
break;
}
- return wrongDirection ? falsed(1, getReason(interactionType)) : Result.passed(0.5);
+ return wrongDirection ? falsed(confidence, getReason(interactionType)) : Result.passed(0.5);
}
private String getReason(int interactionType) {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
index 1d413af..d9197ef 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
@@ -20,6 +20,7 @@
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_X_SECONDARY_DEVIANCE;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
import android.graphics.Point;
import android.provider.DeviceConfig;
@@ -87,6 +88,10 @@
Result calculateFalsingResult(
@Classifier.InteractionType int interactionType,
double historyBelief, double historyConfidence) {
+ if (interactionType == BRIGHTNESS_SLIDER) {
+ return Result.passed(0);
+ }
+
List<MotionEvent> motionEvents = getRecentMotionEvents();
// Rotate horizontal gestures to be horizontal between their first and last point.
// Rotate vertical gestures to be vertical between their first and last point.
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 04b4670..aa66b75 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -531,9 +531,13 @@
Assert.isMainThread();
mDozeHost.extendPulse(reason);
+ // we can't determine the dozing state if we're currently transitioning
+ final DozeMachine.State dozeState =
+ mMachine.isExecutingTransition() ? null : mMachine.getState();
+
// When already pulsing we're allowed to show the wallpaper directly without
// requesting a new pulse.
- if (mMachine.getState() == DozeMachine.State.DOZE_PULSING
+ if (dozeState == DozeMachine.State.DOZE_PULSING
&& reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
mMachine.requestState(DozeMachine.State.DOZE_PULSING_BRIGHT);
return;
@@ -541,8 +545,7 @@
if (mPulsePending || !mAllowPulseTriggers || !canPulse()) {
if (mAllowPulseTriggers) {
- mDozeLog.tracePulseDropped(mPulsePending, mMachine.getState(),
- mDozeHost.isPulsingBlocked());
+ mDozeLog.tracePulseDropped(mPulsePending, dozeState, mDozeHost.isPulsingBlocked());
}
runIfNotNull(onPulseSuppressedListener);
return;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 9d43e0c..594c0af 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -209,6 +209,8 @@
private @TransitionMode int mNavigationBarMode;
private ContentResolver mContentResolver;
private boolean mAssistantAvailable;
+ private boolean mLongPressHomeEnabled;
+ private boolean mAssistantTouchGestureEnabled;
private int mDisabledFlags1;
private int mDisabledFlags2;
@@ -309,7 +311,7 @@
// Send the assistant availability upon connection
if (isConnected) {
- sendAssistantAvailability(mAssistantAvailable);
+ updateAssistantEntrypoints();
}
}
@@ -404,12 +406,7 @@
new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange, Uri uri) {
- boolean available = mAssistManagerLazy.get()
- .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
- if (mAssistantAvailable != available) {
- sendAssistantAvailability(available);
- mAssistantAvailable = available;
- }
+ updateAssistantEntrypoints();
}
};
@@ -531,6 +528,13 @@
mContentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
+ mContentResolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED),
+ false, mAssistContentObserver, UserHandle.USER_ALL);
+ mContentResolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED),
+ false, mAssistContentObserver, UserHandle.USER_ALL);
+ updateAssistantEntrypoints();
if (savedState != null) {
mDisabledFlags1 = savedState.getInt(EXTRA_DISABLE_STATE, 0);
@@ -823,7 +827,7 @@
|| mNavigationBarView.getHomeButton().getCurrentView() == null) {
return;
}
- if (mHomeButtonLongPressDurationMs.isPresent()) {
+ if (mHomeButtonLongPressDurationMs.isPresent() || !mLongPressHomeEnabled) {
mNavigationBarView.getHomeButton().getCurrentView().setLongClickable(false);
mNavigationBarView.getHomeButton().getCurrentView().setHapticFeedbackEnabled(false);
mNavigationBarView.getHomeButton().setOnLongClickListener(null);
@@ -845,6 +849,8 @@
pw.println(" mStartingQuickSwitchRotation=" + mStartingQuickSwitchRotation);
pw.println(" mCurrentRotation=" + mCurrentRotation);
pw.println(" mHomeButtonLongPressDurationMs=" + mHomeButtonLongPressDurationMs);
+ pw.println(" mLongPressHomeEnabled=" + mLongPressHomeEnabled);
+ pw.println(" mAssistantTouchGestureEnabled=" + mAssistantTouchGestureEnabled);
if (mNavigationBarView != null) {
pw.println(" mNavigationBarWindowState="
@@ -1206,9 +1212,11 @@
return true;
}
}
- mHomeButtonLongPressDurationMs.ifPresent(longPressDuration -> {
- mHandler.postDelayed(mOnVariableDurationHomeLongClick, longPressDuration);
- });
+ if (mLongPressHomeEnabled) {
+ mHomeButtonLongPressDurationMs.ifPresent(longPressDuration -> {
+ mHandler.postDelayed(mOnVariableDurationHomeLongClick, longPressDuration);
+ });
+ }
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
@@ -1243,7 +1251,8 @@
mUiEventLogger.log(NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS);
Bundle args = new Bundle();
args.putInt(
- AssistManager.INVOCATION_TYPE_KEY, AssistManager.INVOCATION_HOME_BUTTON_LONG_PRESS);
+ AssistManager.INVOCATION_TYPE_KEY,
+ AssistManager.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
mAssistManagerLazy.get().startAssist(args);
mStatusBarLazy.get().awakenDreams();
@@ -1480,15 +1489,23 @@
| (requestingServices >= 2 ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0);
}
- private void sendAssistantAvailability(boolean available) {
+ private void updateAssistantEntrypoints() {
+ mAssistantAvailable = mAssistManagerLazy.get()
+ .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
+ mLongPressHomeEnabled = Settings.Secure.getInt(mContentResolver,
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, 1) != 0;
+ mAssistantTouchGestureEnabled = Settings.Secure.getInt(mContentResolver,
+ Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, 1) != 0;
if (mOverviewProxyService.getProxy() != null) {
try {
- mOverviewProxyService.getProxy().onAssistantAvailable(available
+ mOverviewProxyService.getProxy().onAssistantAvailable(mAssistantAvailable
+ && mAssistantTouchGestureEnabled
&& QuickStepContract.isGesturalMode(mNavBarMode));
} catch (RemoteException e) {
Log.w(TAG, "Unable to send assistant availability data to launcher");
}
}
+ reconfigureHomeLongClick();
}
// ----- Methods that DisplayNavigationBarController talks to -----
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
index 8a429e2..4c617ed 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
@@ -50,8 +50,14 @@
fun getIcon(context: Context) = context.resources.getDrawable(iconId, context.theme)
}
-data class PrivacyItem(val privacyType: PrivacyType, val application: PrivacyApplication) {
- fun toLog(): String = "(${privacyType.logName}, ${application.packageName}(${application.uid}))"
+private const val UNKNOWN_TIMESTAMP = -1L
+data class PrivacyItem(
+ val privacyType: PrivacyType,
+ val application: PrivacyApplication,
+ val timeStampElapsed: Long = UNKNOWN_TIMESTAMP
+) {
+ val log = "(${privacyType.logName}, ${application.packageName}(${application.uid}), " +
+ "$timeStampElapsed)"
}
data class PrivacyApplication(val packageName: String, val uid: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 03d6154..f7e2a31 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -36,6 +36,7 @@
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.DeviceConfigProxy
import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.time.SystemClock
import java.io.FileDescriptor
import java.io.PrintWriter
import java.lang.ref.WeakReference
@@ -50,6 +51,7 @@
private val deviceConfigProxy: DeviceConfigProxy,
private val userTracker: UserTracker,
private val logger: PrivacyLogger,
+ private val systemClock: SystemClock,
dumpManager: DumpManager
) : Dumpable {
@@ -70,10 +72,9 @@
const val TAG = "PrivacyItemController"
private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED
private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED
- private const val DEFAULT_ALL_INDICATORS = false
private const val DEFAULT_MIC_CAMERA = true
private const val DEFAULT_LOCATION = false
- const val TIME_TO_HOLD_INDICATORS = 5000L
+ @VisibleForTesting const val TIME_TO_HOLD_INDICATORS = 5000L
}
@VisibleForTesting
@@ -95,8 +96,8 @@
private var listening = false
private val callbacks = mutableListOf<WeakReference<Callback>>()
private val internalUiExecutor = MyExecutor(uiExecutor)
- private var holdingIndicators = false
- private var holdIndicatorsCancelled: Runnable? = null
+
+ private var holdingRunnableCanceler: Runnable? = null
private val notifyChanges = Runnable {
val list = privacyList
@@ -108,11 +109,6 @@
uiExecutor.execute(notifyChanges)
}
- private val stopHoldingAndNotifyChanges = Runnable {
- updatePrivacyList(true)
- uiExecutor.execute(notifyChanges)
- }
-
var micCameraAvailable = isMicCameraEnabled()
private set
var locationAvailable = isLocationEnabled()
@@ -189,14 +185,6 @@
userTracker.addCallback(userTrackerCallback, bgExecutor)
}
- private fun setHoldTimer() {
- holdIndicatorsCancelled?.run()
- holdingIndicators = true
- holdIndicatorsCancelled = bgExecutor.executeDelayed({
- stopHoldingAndNotifyChanges.run()
- }, TIME_TO_HOLD_INDICATORS)
- }
-
private fun update(updateUsers: Boolean) {
bgExecutor.execute {
if (updateUsers) {
@@ -261,14 +249,12 @@
removeCallback(WeakReference(callback))
}
- private fun updatePrivacyList(stopHolding: Boolean = false) {
+ private fun updatePrivacyList() {
+ holdingRunnableCanceler?.run()?.also {
+ holdingRunnableCanceler = null
+ }
if (!listening) {
privacyList = emptyList()
- if (holdingIndicators) {
- holdIndicatorsCancelled?.run()
- logger.cancelIndicatorsHold()
- holdingIndicators = false
- }
return
}
val list = appOpsController.getActiveAppOpsForUser(UserHandle.USER_ALL).filter {
@@ -276,43 +262,36 @@
it.code == AppOpsManager.OP_PHONE_CALL_MICROPHONE ||
it.code == AppOpsManager.OP_PHONE_CALL_CAMERA
}.mapNotNull { toPrivacyItem(it) }.distinct()
- processNewList(list, stopHolding)
+ privacyList = processNewList(list)
}
/**
- * The controller will only go from indicators to no indicators (and notify its listeners), if
- * [TIME_TO_HOLD_INDICATORS] has passed since it received an empty list from [AppOpsController].
+ * Figure out which items have not been around for long enough and put them back in the list.
*
- * If holding the last list (in the [TIME_TO_HOLD_INDICATORS] period) and a new non-empty list
- * is retrieved from [AppOpsController], it will stop holding and notify about the new list.
+ * Also schedule when we should check again to remove expired items. Because we always retrieve
+ * the current list, we have the latest info.
+ *
+ * @param list map of list retrieved from [AppOpsController].
+ * @return a list that may have added items that should be kept for some time.
*/
- private fun processNewList(list: List<PrivacyItem>, stopHolding: Boolean) {
- if (list.isNotEmpty()) {
- // The new elements is not empty, so regardless of whether we are holding or not, we
- // clear the holding flag and cancel the delayed runnable.
- if (holdingIndicators) {
- holdIndicatorsCancelled?.run()
- logger.cancelIndicatorsHold()
- holdingIndicators = false
- }
- logger.logUpdatedPrivacyItemsList(
- list.joinToString(separator = ", ", transform = PrivacyItem::toLog))
- privacyList = list
- } else if (holdingIndicators && stopHolding) {
- // We are holding indicators, received an empty list and were told to stop holding.
- logger.finishIndicatorsHold()
- logger.logUpdatedPrivacyItemsList("")
- holdingIndicators = false
- privacyList = list
- } else if (holdingIndicators && !stopHolding) {
- // Empty list while we are holding. Ignore
- } else if (!holdingIndicators && privacyList.isNotEmpty()) {
- // We are not holding, we were showing some indicators but now we should show nothing.
- // Start holding.
- logger.startIndicatorsHold(TIME_TO_HOLD_INDICATORS)
- setHoldTimer()
+ private fun processNewList(list: List<PrivacyItem>): List<PrivacyItem> {
+ logger.logRetrievedPrivacyItemsList(list)
+
+ // Anything earlier than this timestamp can be removed
+ val removeBeforeTime = systemClock.elapsedRealtime() - TIME_TO_HOLD_INDICATORS
+ val mustKeep = privacyList.filter { it.timeStampElapsed > removeBeforeTime && it !in list }
+
+ // There are items we must keep because they haven't been around for enough time.
+ if (mustKeep.isNotEmpty()) {
+ logger.logPrivacyItemsToHold(mustKeep)
+ val earliestTime = mustKeep.minByOrNull { it.timeStampElapsed }!!.timeStampElapsed
+
+ // Update the list again when the earliest item should be removed.
+ val delay = earliestTime - removeBeforeTime
+ logger.logPrivacyItemsUpdateScheduled(delay)
+ holdingRunnableCanceler = bgExecutor.executeDelayed(updateListAndNotifyChanges, delay)
}
- // Else. We are not holding, we were not showing anything and the new list is empty. Ignore.
+ return list + mustKeep
}
private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
@@ -329,7 +308,7 @@
return null
}
val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid)
- return PrivacyItem(type, app)
+ return PrivacyItem(type, app, appOpItem.timeStartedElapsed)
}
interface Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt b/packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
index ebf6ae9..acce945 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
@@ -22,10 +22,13 @@
import com.android.systemui.log.LogMessage
import com.android.systemui.log.dagger.PrivacyLog
import com.android.systemui.privacy.PrivacyDialog
+import com.android.systemui.privacy.PrivacyItem
+import java.text.SimpleDateFormat
+import java.util.Locale
import javax.inject.Inject
private const val TAG = "PrivacyLog"
-
+private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
class PrivacyLogger @Inject constructor(
@PrivacyLog private val buffer: LogBuffer
) {
@@ -41,31 +44,29 @@
})
}
- fun logUpdatedPrivacyItemsList(listAsString: String) {
+ fun logRetrievedPrivacyItemsList(list: List<PrivacyItem>) {
log(LogLevel.INFO, {
- str1 = listAsString
+ str1 = listToString(list)
}, {
- "Updated list: $str1"
+ "Retrieved list to process: $str1"
})
}
- fun startIndicatorsHold(time: Long) {
+ fun logPrivacyItemsToHold(list: List<PrivacyItem>) {
log(LogLevel.DEBUG, {
- int1 = time.toInt() / 1000
+ str1 = listToString(list)
}, {
- "Starting privacy indicators hold for $int1 seconds"
+ "Holding items: $str1"
})
}
- fun cancelIndicatorsHold() {
- log(LogLevel.VERBOSE, {}, {
- "Cancel privacy indicators hold"
- })
- }
-
- fun finishIndicatorsHold() {
- log(LogLevel.DEBUG, {}, {
- "Finish privacy indicators hold"
+ fun logPrivacyItemsUpdateScheduled(delay: Long) {
+ log(LogLevel.INFO, {
+ val scheduledFor = System.currentTimeMillis() + delay
+ val formattedTimestamp = DATE_FORMAT.format(scheduledFor)
+ str1 = formattedTimestamp
+ }, {
+ "Updating items scheduled for $str1"
})
}
@@ -130,6 +131,10 @@
})
}
+ private fun listToString(list: List<PrivacyItem>): String {
+ return list.joinToString(separator = ", ", transform = PrivacyItem::log)
+ }
+
private inline fun log(
logLevel: LogLevel,
initializer: LogMessage.() -> Unit,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index fcb56a4..32723b4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -87,6 +87,10 @@
attrs, R.styleable.PagedTileLayout, 0, 0);
mSideLabels = t.getBoolean(R.styleable.PagedTileLayout_sideLabels, false);
t.recycle();
+ if (mSideLabels) {
+ setPageMargin(context.getResources().getDimensionPixelOffset(
+ R.dimen.qs_tile_margin_horizontal));
+ }
}
private int mLastMaxHeight = -1;
@@ -341,6 +345,9 @@
// Update bottom padding, useful for removing extra space once the panel page indicator is
// hidden.
Resources res = getContext().getResources();
+ if (mSideLabels) {
+ setPageMargin(res.getDimensionPixelOffset(R.dimen.qs_tile_margin_horizontal));
+ }
setPadding(0, 0, 0,
getContext().getResources().getDimensionPixelSize(
R.dimen.qs_paged_tile_layout_padding_bottom));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index b8823e1..a089a05 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -65,12 +65,14 @@
private final QuickQSPanel mQuickQsPanel;
private final QSPanelController mQsPanelController;
private final QuickQSPanelController mQuickQSPanelController;
+ private final QuickStatusBarHeader mQuickStatusBarHeader;
private final QSSecurityFooter mSecurityFooter;
private final QS mQs;
private PagedTileLayout mPagedLayout;
private boolean mOnFirstPage = true;
+ private QSExpansionPathInterpolator mQSExpansionPathInterpolator;
private TouchAnimator mFirstPageAnimator;
private TouchAnimator mFirstPageDelayedAnimator;
private TouchAnimator mTranslationXAnimator;
@@ -98,19 +100,22 @@
private final FeatureFlags mFeatureFlags;
@Inject
- public QSAnimator(QS qs, QuickQSPanel quickPanel, QSPanelController qsPanelController,
+ public QSAnimator(QS qs, QuickQSPanel quickPanel, QuickStatusBarHeader quickStatusBarHeader,
+ QSPanelController qsPanelController,
QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost,
QSSecurityFooter securityFooter, @Main Executor executor, TunerService tunerService,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags, QSExpansionPathInterpolator qsExpansionPathInterpolator) {
mQs = qs;
mQuickQsPanel = quickPanel;
mQsPanelController = qsPanelController;
mQuickQSPanelController = quickQSPanelController;
+ mQuickStatusBarHeader = quickStatusBarHeader;
mSecurityFooter = securityFooter;
mHost = qsTileHost;
mExecutor = executor;
mTunerService = tunerService;
mFeatureFlags = featureFlags;
+ mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
mHost.addCallback(this);
mQsPanelController.addOnAttachStateChangeListener(this);
qs.getView().addOnLayoutChangeListener(this);
@@ -228,116 +233,128 @@
boolean qsSideLabelsEnabled = mFeatureFlags.isQSLabelsEnabled();
int qqsTileHeight = 0;
- for (QSTile tile : tiles) {
- QSTileView tileView = mQsPanelController.getTileView(tile);
- if (tileView == null) {
- Log.e(TAG, "tileView is null " + tile.getTileSpec());
- continue;
- }
- final View tileIcon = tileView.getIcon().getIconView();
- View view = mQs.getView();
+ if (mQsPanelController.areThereTiles()) {
+ for (QSTile tile : tiles) {
+ QSTileView tileView = mQsPanelController.getTileView(tile);
+ if (tileView == null) {
+ Log.e(TAG, "tileView is null " + tile.getTileSpec());
+ continue;
+ }
+ final View tileIcon = tileView.getIcon().getIconView();
+ View view = mQs.getView();
- // This case: less tiles to animate in small displays.
- if (count < mQuickQSPanelController.getTileLayout().getNumVisibleTiles()
- && mAllowFancy) {
- // Quick tiles.
- QSTileView quickTileView = mQuickQSPanelController.getTileView(tile);
- if (quickTileView == null) continue;
+ // This case: less tiles to animate in small displays.
+ if (count < mQuickQSPanelController.getTileLayout().getNumVisibleTiles()
+ && mAllowFancy) {
+ // Quick tiles.
+ QSTileView quickTileView = mQuickQSPanelController.getTileView(tile);
+ if (quickTileView == null) continue;
- getRelativePosition(loc1, quickTileView.getIcon().getIconView(), view);
- getRelativePosition(loc2, tileIcon, view);
- final int xDiff = loc2[0] - loc1[0];
- int yDiff = loc2[1] - loc1[1];
+ getRelativePosition(loc1, quickTileView.getIcon().getIconView(), view);
+ getRelativePosition(loc2, tileIcon, view);
+ final int xDiff = loc2[0] - loc1[0];
+ int yDiff = loc2[1] - loc1[1];
- if (count < tileLayout.getNumVisibleTiles()) {
- getRelativePosition(loc1, quickTileView, view);
- getRelativePosition(loc2, tileView, view);
- int yOffset = qsSideLabelsEnabled ? loc2[1] - loc1[1] : 0;
- // Move the quick tile right from its location to the new one.
- View v = qsSideLabelsEnabled ? quickTileView.getIcon() : quickTileView;
- translationXBuilder.addFloat(v, "translationX", 0, xDiff);
- translationYBuilder.addFloat(v, "translationY", 0, yDiff - yOffset);
- mAllViews.add(v);
+ if (count < tileLayout.getNumVisibleTiles()) {
+ getRelativePosition(loc1, quickTileView, view);
+ getRelativePosition(loc2, tileView, view);
+ int yOffset = qsSideLabelsEnabled
+ ? loc2[1] - loc1[1]
+ : mQuickStatusBarHeader.getOffsetTranslation();
+ // Move the quick tile right from its location to the new one.
+ View v = qsSideLabelsEnabled ? quickTileView.getIcon() : quickTileView;
+ translationXBuilder.addFloat(v, "translationX", 0, xDiff);
+ translationYBuilder.addFloat(v, "translationY", 0, yDiff - yOffset);
+ mAllViews.add(v);
- // Move the real tile from the quick tile position to its final
- // location.
- v = qsSideLabelsEnabled ? tileIcon : tileView;
- translationXBuilder.addFloat(v, "translationX", -xDiff, 0);
- translationYBuilder.addFloat(v, "translationY", -yDiff + yOffset, 0);
+ // Move the real tile from the quick tile position to its final
+ // location.
+ v = qsSideLabelsEnabled ? tileIcon : tileView;
+ translationXBuilder.addFloat(v, "translationX", -xDiff, 0);
+ translationYBuilder.addFloat(v, "translationY", -yDiff + yOffset, 0);
if (qsSideLabelsEnabled) {
- translationYBuilder.addFloat(quickTileView, "translationY", 0, yOffset);
- translationYBuilder.addFloat(tileView, "translationY", -yOffset, 0);
+ // Offset the translation animation on the views
+ // (that goes from 0 to getOffsetTranslation)
+ int offsetWithQSBHTranslation =
+ yOffset - mQuickStatusBarHeader.getOffsetTranslation();
+ translationYBuilder.addFloat(quickTileView, "translationY", 0,
+ offsetWithQSBHTranslation);
+ translationYBuilder.addFloat(tileView, "translationY",
+ -offsetWithQSBHTranslation, 0);
- if (mQQSTileHeightAnimator == null) {
- mQQSTileHeightAnimator = new HeightExpansionAnimator(this,
- quickTileView.getHeight(), tileView.getHeight());
- qqsTileHeight = quickTileView.getHeight();
+ if (mQQSTileHeightAnimator == null) {
+ mQQSTileHeightAnimator = new HeightExpansionAnimator(this,
+ quickTileView.getHeight(), tileView.getHeight());
+ qqsTileHeight = quickTileView.getHeight();
+ }
+
+ mQQSTileHeightAnimator.addView(quickTileView);
+ View qqsLabelContainer = quickTileView.getLabelContainer();
+ View qsLabelContainer = tileView.getLabelContainer();
+
+ getRelativePosition(loc1, qqsLabelContainer, view);
+ getRelativePosition(loc2, qsLabelContainer, view);
+ yDiff = loc2[1] - loc1[1] - yOffset;
+
+ translationYBuilder.addFloat(qqsLabelContainer, "translationY", 0,
+ yDiff);
+ translationYBuilder.addFloat(qsLabelContainer, "translationY", -yDiff,
+ 0);
+ mAllViews.add(qqsLabelContainer);
+ mAllViews.add(qsLabelContainer);
}
- mQQSTileHeightAnimator.addView(quickTileView);
- View qqsLabelContainer = quickTileView.getLabelContainer();
- View qsLabelContainer = tileView.getLabelContainer();
+ } else { // These tiles disappear when expanding
+ firstPageBuilder.addFloat(quickTileView, "alpha", 1, 0);
+ translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
- getRelativePosition(loc1, qqsLabelContainer, view);
- getRelativePosition(loc2, qsLabelContainer, view);
- yDiff = loc2[1] - loc1[1] - yOffset;
-
- translationYBuilder.addFloat(qqsLabelContainer, "translationY", 0, yDiff);
- translationYBuilder.addFloat(qsLabelContainer, "translationY", -yDiff, 0);
- mAllViews.add(qqsLabelContainer);
- mAllViews.add(qsLabelContainer);
+ // xDiff is negative here and this makes it "more" negative
+ final int translationX =
+ mQsPanelController.isLayoutRtl() ? xDiff - width : xDiff + width;
+ translationXBuilder.addFloat(quickTileView, "translationX", 0,
+ translationX);
}
- } else { // These tiles disappear when expanding
- firstPageBuilder.addFloat(quickTileView, "alpha", 1, 0);
- translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
+ if (qsSideLabelsEnabled) {
+ mQuickQsViews.add(tileView);
+ } else {
+ mQuickQsViews.add(tileView.getIconWithBackground());
+ }
+ mAllViews.add(tileView.getIcon());
+ mAllViews.add(quickTileView);
+ } else if (mFullRows && isIconInAnimatedRow(count)) {
- // xDiff is negative here and this makes it "more" negative
- final int translationX =
- mQsPanelController.isLayoutRtl() ? xDiff - width : xDiff + width;
- translationXBuilder.addFloat(quickTileView, "translationX", 0,
- translationX);
- }
-
- if (qsSideLabelsEnabled) {
- mQuickQsViews.add(tileView);
- } else {
- mQuickQsViews.add(tileView.getIconWithBackground());
- }
- mAllViews.add(tileView.getIcon());
- mAllViews.add(quickTileView);
- } else if (mFullRows && isIconInAnimatedRow(count)) {
-
- firstPageBuilder.addFloat(tileView, "translationY", -heightDiff, 0);
-
- mAllViews.add(tileIcon);
- } else {
- if (!qsSideLabelsEnabled) {
- firstPageBuilder.addFloat(tileView, "alpha", 0, 1);
firstPageBuilder.addFloat(tileView, "translationY", -heightDiff, 0);
- } else {
- // Pretend there's a corresponding QQS tile (for the position) that we are
- // expanding from.
- SideLabelTileLayout qqsLayout =
- (SideLabelTileLayout) mQuickQsPanel.getTileLayout();
- getRelativePosition(loc1, qqsLayout, view);
- getRelativePosition(loc2, tileView, view);
- int diff = loc2[1] - (loc1[1] + qqsLayout.getPhantomTopPosition(count));
- translationYBuilder.addFloat(tileView, "translationY", -diff, 0);
- if (mOtherTilesExpandAnimator == null) {
- mOtherTilesExpandAnimator =
- new HeightExpansionAnimator(
- this, qqsTileHeight, tileView.getHeight());
- }
- mOtherTilesExpandAnimator.addView(tileView);
- tileView.setClipChildren(true);
- tileView.setClipToPadding(true);
- }
- }
- mAllViews.add(tileView);
- count++;
+ mAllViews.add(tileIcon);
+ } else {
+ if (!qsSideLabelsEnabled) {
+ firstPageBuilder.addFloat(tileView, "alpha", 0, 1);
+ firstPageBuilder.addFloat(tileView, "translationY", -heightDiff, 0);
+ } else {
+ // Pretend there's a corresponding QQS tile (for the position) that we are
+ // expanding from.
+ SideLabelTileLayout qqsLayout =
+ (SideLabelTileLayout) mQuickQsPanel.getTileLayout();
+ getRelativePosition(loc1, qqsLayout, view);
+ getRelativePosition(loc2, tileView, view);
+ int diff = loc2[1] - (loc1[1] + qqsLayout.getPhantomTopPosition(count));
+ translationYBuilder.addFloat(tileView, "translationY", -diff, 0);
+ if (mOtherTilesExpandAnimator == null) {
+ mOtherTilesExpandAnimator =
+ new HeightExpansionAnimator(
+ this, qqsTileHeight, tileView.getHeight());
+ }
+ mOtherTilesExpandAnimator.addView(tileView);
+ tileView.setClipChildren(true);
+ tileView.setClipToPadding(true);
+ }
+ }
+
+ mAllViews.add(tileView);
+ count++;
+ }
}
if (mAllowFancy) {
@@ -375,22 +392,23 @@
}
float px = 0;
- float py = 1;
if (tiles.size() <= 3) {
px = 1;
} else if (tiles.size() <= 6) {
px = .4f;
}
- PathInterpolatorBuilder interpolatorBuilder = new PathInterpolatorBuilder(0, 0, px, py);
- translationXBuilder.setInterpolator(interpolatorBuilder.getXInterpolator());
- translationYBuilder.setInterpolator(interpolatorBuilder.getYInterpolator());
+ mQSExpansionPathInterpolator.setControlX2(px);
+ translationXBuilder.setInterpolator(mQSExpansionPathInterpolator.getXInterpolator());
+ translationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator());
mTranslationXAnimator = translationXBuilder.build();
mTranslationYAnimator = translationYBuilder.build();
if (mQQSTileHeightAnimator != null) {
- mQQSTileHeightAnimator.setInterpolator(interpolatorBuilder.getYInterpolator());
+ mQQSTileHeightAnimator.setInterpolator(
+ mQSExpansionPathInterpolator.getYInterpolator());
}
if (mOtherTilesExpandAnimator != null) {
- mOtherTilesExpandAnimator.setInterpolator(interpolatorBuilder.getYInterpolator());
+ mOtherTilesExpandAnimator.setInterpolator(
+ mQSExpansionPathInterpolator.getYInterpolator());
}
}
mNonfirstPageAnimator = new TouchAnimator.Builder()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt b/packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt
new file mode 100644
index 0000000..d351b89
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs
+
+import android.view.animation.Interpolator
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class QSExpansionPathInterpolator @Inject constructor() {
+
+ private var pathInterpolatorBuilder = PathInterpolatorBuilder(0f, 0f, 0f, 1f)
+ private var lastX = 0f
+ val xInterpolator: Interpolator
+ get() = pathInterpolatorBuilder.xInterpolator
+
+ val yInterpolator: Interpolator
+ get() = pathInterpolatorBuilder.yInterpolator
+
+ fun setControlX2(value: Float) {
+ if (value != lastX) {
+ lastX = value
+ pathInterpolatorBuilder = PathInterpolatorBuilder(0f, 0f, lastX, 1f)
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHeaderInfoLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/QSHeaderInfoLayout.kt
deleted file mode 100644
index c654621..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHeaderInfoLayout.kt
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.qs
-
-import android.content.Context
-import android.util.AttributeSet
-import android.view.View
-import android.widget.FrameLayout
-import com.android.systemui.R
-
-/**
- * Container for the Next Alarm and Ringer status texts in [QuickStatusBarHeader].
- *
- * If both elements are visible, it splits the available space according to the following rules:
- * * If both views add up to less than the total space, they take all the space they need.
- * * If both views are larger than half the space, each view takes half the space.
- * * Otherwise, the smaller view takes the space it needs and the larger one takes all remaining
- * space.
- */
-class QSHeaderInfoLayout @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyle: Int = 0,
- defStyleRes: Int = 0
-) : FrameLayout(context, attrs, defStyle, defStyleRes) {
-
- private lateinit var alarmContainer: View
- private lateinit var ringerContainer: View
- private lateinit var statusSeparator: View
- private val location = Location(0, 0)
-
- override fun onFinishInflate() {
- super.onFinishInflate()
- alarmContainer = findViewById(R.id.alarm_container)
- ringerContainer = findViewById(R.id.ringer_container)
- statusSeparator = findViewById(R.id.status_separator)
- }
-
- override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
- // At most one view is there
- if (statusSeparator.visibility == View.GONE) super.onLayout(changed, l, t, r, b)
- else {
- val layoutRTL = isLayoutRtl
- val width = r - l
- val height = b - t
- var offset = 0
-
- offset += alarmContainer.layoutView(width, height, offset, layoutRTL)
- offset += statusSeparator.layoutView(width, height, offset, layoutRTL)
- ringerContainer.layoutView(width, height, offset, layoutRTL)
- }
- }
-
- private fun View.layoutView(pWidth: Int, pHeight: Int, offset: Int, RTL: Boolean): Int {
- location.setLocationFromOffset(pWidth, offset, this.measuredWidth, RTL)
- layout(location.left, 0, location.right, pHeight)
- return this.measuredWidth
- }
-
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- super.onMeasure(
- MeasureSpec.makeMeasureSpec(
- MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST),
- heightMeasureSpec)
- val width = MeasureSpec.getSize(widthMeasureSpec)
- // Once we measure the views, using as much space as they need, we need to remeasure them
- // assigning them their final width. This is because TextViews decide whether to MARQUEE
- // after onMeasure.
- if (statusSeparator.visibility != View.GONE) {
- val alarmWidth = alarmContainer.measuredWidth
- val separatorWidth = statusSeparator.measuredWidth
- val ringerWidth = ringerContainer.measuredWidth
- val availableSpace = MeasureSpec.getSize(width) - separatorWidth
- if (alarmWidth < availableSpace / 2) {
- measureChild(
- ringerContainer,
- MeasureSpec.makeMeasureSpec(
- Math.min(ringerWidth, availableSpace - alarmWidth),
- MeasureSpec.AT_MOST),
- heightMeasureSpec)
- } else if (ringerWidth < availableSpace / 2) {
- measureChild(alarmContainer,
- MeasureSpec.makeMeasureSpec(
- Math.min(alarmWidth, availableSpace - ringerWidth),
- MeasureSpec.AT_MOST),
- heightMeasureSpec)
- } else {
- measureChild(
- alarmContainer,
- MeasureSpec.makeMeasureSpec(availableSpace / 2, MeasureSpec.AT_MOST),
- heightMeasureSpec)
- measureChild(
- ringerContainer,
- MeasureSpec.makeMeasureSpec(availableSpace / 2, MeasureSpec.AT_MOST),
- heightMeasureSpec)
- }
- }
- setMeasuredDimension(width, measuredHeight)
- }
-
- private data class Location(var left: Int, var right: Int) {
- /**
- * Sets the [left] and [right] with the correct values for laying out the child, respecting
- * RTL. Only set the variable through here to prevent concurrency issues.
- * This is done to prevent allocation of [Pair] in [onLayout].
- */
- fun setLocationFromOffset(parentWidth: Int, offset: Int, width: Int, RTL: Boolean) {
- if (RTL) {
- left = parentWidth - offset - width
- right = parentWidth - offset
- } else {
- left = offset
- right = offset + width
- }
- }
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index c794a21..27cc268 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -391,20 +391,13 @@
index++;
if (mSecurityFooter != null) {
- LinearLayout.LayoutParams layoutParams =
- (LayoutParams) mSecurityFooter.getLayoutParams();
if (mUsingHorizontalLayout && mHeaderContainer != null) {
// Adding the security view to the header, that enables us to avoid scrolling
- layoutParams.width = 0;
- layoutParams.weight = 1.6f;
- switchToParent(mSecurityFooter, mHeaderContainer, 1 /* always in second place */);
+ switchToParent(mSecurityFooter, mHeaderContainer, 0);
} else {
- layoutParams.width = LayoutParams.WRAP_CONTENT;
- layoutParams.weight = 0;
switchToParent(mSecurityFooter, parent, index);
index++;
}
- mSecurityFooter.setLayoutParams(layoutParams);
}
if (mFooter != null) {
@@ -656,7 +649,7 @@
if (mFooter != null) {
int footerMargin = 0;
int indicatorMargin = 0;
- if (mUsingHorizontalLayout) {
+ if (mUsingHorizontalLayout && !mSideLabels) {
footerMargin = mFooterMarginStartHorizontal;
indicatorMargin = footerMargin - mVisualMarginEnd;
}
@@ -684,15 +677,19 @@
}
public Pair<Integer, Integer> getVisualSideMargins() {
- return new Pair(mVisualMarginStart, mUsingHorizontalLayout ? 0 : mVisualMarginEnd);
+ if (mSideLabels) {
+ return new Pair(0, 0);
+ } else {
+ return new Pair(mVisualMarginStart, mUsingHorizontalLayout ? 0 : mVisualMarginEnd);
+ }
}
private void updateTileLayoutMargins() {
int marginEnd = mVisualMarginEnd;
- if (mUsingHorizontalLayout) {
+ if (mUsingHorizontalLayout || mSideLabels) {
marginEnd = 0;
}
- updateMargins((View) mTileLayout, mVisualMarginStart, marginEnd);
+ updateMargins((View) mTileLayout, mSideLabels ? 0 : mVisualMarginStart, marginEnd);
}
private void updateDividerMargin() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 6386365..86836f9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -228,6 +228,9 @@
return mHost.createTile(subPanel);
}
+ boolean areThereTiles() {
+ return !mRecords.isEmpty();
+ }
QSTileView getTileView(QSTile tile) {
for (QSPanelControllerBase.TileRecord r : mRecords) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index a0bf584..8aaf84b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -17,15 +17,14 @@
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import android.annotation.ColorInt;
-import android.app.AlarmManager.AlarmClockInfo;
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
+
import android.content.Context;
-import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
-import android.media.AudioManager;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.util.Pair;
@@ -34,66 +33,46 @@
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.FrameLayout;
-import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
import android.widget.Space;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.LifecycleRegistry;
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.privacy.OngoingPrivacyChip;
import com.android.systemui.qs.QSDetail.Callback;
+import com.android.systemui.statusbar.StatusBarMobileView;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
import com.android.systemui.statusbar.phone.StatusBarWindowView;
+import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.policy.Clock;
-import java.util.Locale;
-import java.util.Objects;
-
/**
- * View that contains the top-most bits of the screen (primarily the status bar with date, time, and
- * battery) and also contains the {@link QuickQSPanel} along with some of the panel's inner
- * contents.
+ * View that contains the top-most bits of the QS panel (primarily the status bar with date, time,
+ * battery, carrier info and privacy icons) and also contains the {@link QuickQSPanel}.
*/
-public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwner {
-
- public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
+public class QuickStatusBarHeader extends FrameLayout {
private boolean mExpanded;
private boolean mQsDisabled;
+ private TouchAnimator mAlphaAnimator;
+ private TouchAnimator mTranslationAnimator;
+
protected QuickQSPanel mHeaderQsPanel;
- private TouchAnimator mStatusIconsAlphaAnimator;
- private TouchAnimator mHeaderTextContainerAlphaAnimator;
+ private View mDatePrivacyView;
+ private View mClockIconsView;
+ private View mContainer;
- private View mSystemIconsView;
- private View mQuickQsStatusIcons;
- private View mHeaderTextContainerView;
-
- private ImageView mNextAlarmIcon;
- /** {@link TextView} containing the actual text indicating when the next alarm will go off. */
- private TextView mNextAlarmTextView;
- private View mNextAlarmContainer;
- private View mStatusSeparator;
- private ImageView mRingerModeIcon;
- private TextView mRingerModeTextView;
- private View mRingerContainer;
+ private View mQSCarriers;
private Clock mClockView;
- private OngoingPrivacyChip mPrivacyChip;
private Space mSpace;
private BatteryMeterView mBatteryRemainingIcon;
- private TintedIconManager mTintedIconManager;
+ private StatusIconContainer mIconContainer;
- // Used for RingerModeTracker
- private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
+
+ private TintedIconManager mTintedIconManager;
+ private QSExpansionPathInterpolator mQSExpansionPathInterpolator;
private int mStatusBarPaddingTop = 0;
private int mRoundedCornerPadding = 0;
@@ -102,12 +81,26 @@
private int mWaterfallTopInset;
private int mCutOutPaddingLeft;
private int mCutOutPaddingRight;
- private float mExpandedHeaderAlpha = 1.0f;
+ private float mClockIconsAlpha = 1.0f;
+ private float mDatePrivacyAlpha = 1.0f;
private float mKeyguardExpansionFraction;
private int mTextColorPrimary = Color.TRANSPARENT;
+ private int mTopViewMeasureHeight;
+
+ private final String mMobileSlotName;
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
+ mMobileSlotName = context.getString(com.android.internal.R.string.status_bar_mobile);
+ }
+
+ /**
+ * How much the view containing the clock and QQS will translate down when QS is fully expanded.
+ *
+ * This matches the measured height of the view containing the date and privacy icons.
+ */
+ public int getOffsetTranslation() {
+ return mTopViewMeasureHeight;
}
@Override
@@ -115,19 +108,12 @@
super.onFinishInflate();
mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
- mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
- mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
+ mDatePrivacyView = findViewById(R.id.quick_status_bar_date_privacy);
+ mClockIconsView = findViewById(R.id.quick_qs_status_icons);
+ mQSCarriers = findViewById(R.id.carrier_group);
+ mContainer = findViewById(R.id.container);
+ mIconContainer = findViewById(R.id.statusIcons);
- // Views corresponding to the header info section (e.g. ringer and next alarm).
- mHeaderTextContainerView = findViewById(R.id.header_text_container);
- mStatusSeparator = findViewById(R.id.status_separator);
- mNextAlarmIcon = findViewById(R.id.next_alarm_icon);
- mNextAlarmTextView = findViewById(R.id.next_alarm_text);
- mNextAlarmContainer = findViewById(R.id.alarm_container);
- mRingerModeIcon = findViewById(R.id.ringer_mode_icon);
- mRingerModeTextView = findViewById(R.id.ringer_mode_text);
- mRingerContainer = findViewById(R.id.ringer_container);
- mPrivacyChip = findViewById(R.id.privacy_chip);
mClockView = findViewById(R.id.clock);
mSpace = findViewById(R.id.space);
// Tint for the battery icons are handled in setupHost()
@@ -140,79 +126,34 @@
// QS will always show the estimate, and BatteryMeterView handles the case where
// it's unavailable or charging
mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
- mRingerModeTextView.setSelected(true);
- mNextAlarmTextView.setSelected(true);
}
- void onAttach(TintedIconManager iconManager) {
+ void onAttach(TintedIconManager iconManager,
+ QSExpansionPathInterpolator qsExpansionPathInterpolator) {
mTintedIconManager = iconManager;
int fillColor = Utils.getColorAttrDefaultColor(getContext(),
android.R.attr.textColorPrimary);
// Set the correct tint for the status icons so they contrast
iconManager.setTint(fillColor);
- mNextAlarmIcon.setImageTintList(ColorStateList.valueOf(fillColor));
- mRingerModeIcon.setImageTintList(ColorStateList.valueOf(fillColor));
+
+ mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
+ updateAnimators();
}
public QuickQSPanel getHeaderQsPanel() {
return mHeaderQsPanel;
}
- void updateStatusText(int ringerMode, AlarmClockInfo nextAlarm, boolean zenOverridingRinger,
- boolean use24HourFormat) {
- boolean changed = updateRingerStatus(ringerMode, zenOverridingRinger)
- || updateAlarmStatus(nextAlarm, use24HourFormat);
-
- if (changed) {
- boolean alarmVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
- boolean ringerVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
- mStatusSeparator.setVisibility(alarmVisible && ringerVisible ? View.VISIBLE
- : View.GONE);
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ if (mDatePrivacyView.getMeasuredHeight() != mTopViewMeasureHeight) {
+ mTopViewMeasureHeight = mDatePrivacyView.getMeasuredHeight();
+ updateAnimators();
}
}
- private boolean updateRingerStatus(int ringerMode, boolean zenOverridingRinger) {
- boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
- CharSequence originalRingerText = mRingerModeTextView.getText();
-
- boolean ringerVisible = false;
- if (!zenOverridingRinger) {
- if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
- mRingerModeIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
- mRingerModeTextView.setText(R.string.qs_status_phone_vibrate);
- ringerVisible = true;
- } else if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
- mRingerModeIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
- mRingerModeTextView.setText(R.string.qs_status_phone_muted);
- ringerVisible = true;
- }
- }
- mRingerModeIcon.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
- mRingerModeTextView.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
- mRingerContainer.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
-
- return isOriginalVisible != ringerVisible ||
- !Objects.equals(originalRingerText, mRingerModeTextView.getText());
- }
-
- private boolean updateAlarmStatus(AlarmClockInfo nextAlarm, boolean use24HourFormat) {
- boolean isOriginalVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
- CharSequence originalAlarmText = mNextAlarmTextView.getText();
-
- boolean alarmVisible = false;
- if (nextAlarm != null) {
- alarmVisible = true;
- mNextAlarmTextView.setText(formatNextAlarm(nextAlarm, use24HourFormat));
- }
- mNextAlarmIcon.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
- mNextAlarmTextView.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
- mNextAlarmContainer.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
-
- return isOriginalVisible != alarmVisible ||
- !Objects.equals(originalAlarmText, mNextAlarmTextView.getText());
- }
-
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -225,40 +166,27 @@
updateResources();
}
- /**
- * The height of QQS should always be the status bar height + 128dp. This is normally easy, but
- * when there is a notch involved the status bar can remain a fixed pixel size.
- */
- private void updateMinimumHeight() {
- int sbHeight = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- int qqsHeight = mContext.getResources().getDimensionPixelSize(
- R.dimen.qs_quick_header_panel_height);
-
- setMinimumHeight(sbHeight + qqsHeight);
- }
-
void updateResources() {
Resources resources = mContext.getResources();
- updateMinimumHeight();
mRoundedCornerPadding = resources.getDimensionPixelSize(
R.dimen.rounded_corner_content_padding);
mStatusBarPaddingTop = resources.getDimensionPixelSize(R.dimen.status_bar_padding_top);
- // Update height for a few views, especially due to landscape mode restricting space.
- mHeaderTextContainerView.getLayoutParams().height =
- resources.getDimensionPixelSize(R.dimen.qs_header_tooltip_height);
- mHeaderTextContainerView.setLayoutParams(mHeaderTextContainerView.getLayoutParams());
-
- mSystemIconsView.getLayoutParams().height = resources.getDimensionPixelSize(
+ int qsOffsetHeight = resources.getDimensionPixelSize(
com.android.internal.R.dimen.quick_qs_offset_height);
- mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
+
+ mDatePrivacyView.getLayoutParams().height =
+ Math.max(qsOffsetHeight, mDatePrivacyView.getMinimumHeight());
+ mDatePrivacyView.setLayoutParams(mDatePrivacyView.getLayoutParams());
+
+ mClockIconsView.getLayoutParams().height =
+ Math.max(qsOffsetHeight, mClockIconsView.getMinimumHeight());
+ mClockIconsView.setLayoutParams(mClockIconsView.getLayoutParams());
ViewGroup.LayoutParams lp = getLayoutParams();
if (mQsDisabled) {
- lp.height = resources.getDimensionPixelSize(
- com.android.internal.R.dimen.quick_qs_offset_height);
+ lp.height = mClockIconsView.getLayoutParams().height;
} else {
lp.height = WRAP_CONTENT;
}
@@ -276,21 +204,45 @@
mBatteryRemainingIcon.updateColors(mTextColorPrimary, textColorSecondary,
mTextColorPrimary);
}
-
- updateStatusIconAlphaAnimator();
- updateHeaderTextContainerAlphaAnimator();
+ updateHeadersPadding();
+ updateAnimators();
}
- private void updateStatusIconAlphaAnimator() {
- mStatusIconsAlphaAnimator = new TouchAnimator.Builder()
- .addFloat(mQuickQsStatusIcons, "alpha", 1, 0, 0)
+ private void updateAnimators() {
+ updateAlphaAnimator();
+ int offset = mTopViewMeasureHeight;
+
+ mTranslationAnimator = new TouchAnimator.Builder()
+ .addFloat(mContainer, "translationY", 0, offset)
+ .setInterpolator(mQSExpansionPathInterpolator != null
+ ? mQSExpansionPathInterpolator.getYInterpolator()
+ : null)
.build();
}
- private void updateHeaderTextContainerAlphaAnimator() {
- mHeaderTextContainerAlphaAnimator = new TouchAnimator.Builder()
- .addFloat(mHeaderTextContainerView, "alpha", 0, 0, mExpandedHeaderAlpha)
- .build();
+ private void updateAlphaAnimator() {
+ StatusBarMobileView icon =
+ ((StatusBarMobileView) mIconContainer.getViewForSlot(mMobileSlotName));
+ TouchAnimator.Builder builder = new TouchAnimator.Builder()
+ .addFloat(mQSCarriers, "alpha", 0, 1)
+ .addFloat(mDatePrivacyView, "alpha", 0, mDatePrivacyAlpha);
+ if (icon != null) {
+ builder.addFloat(icon, "alpha", 1, 0);
+ builder.setListener(new TouchAnimator.ListenerAdapter() {
+ @Override
+ public void onAnimationAtEnd() {
+ icon.forceHidden(true);
+ icon.setVisibleState(STATE_HIDDEN);
+ }
+
+ @Override
+ public void onAnimationStarted() {
+ icon.forceHidden(false);
+ icon.setVisibleState(STATE_ICON);
+ }
+ });
+ }
+ mAlphaAnimator = builder.build();
}
/** */
@@ -312,25 +264,19 @@
public void setExpansion(boolean forceExpanded, float expansionFraction,
float panelTranslationY) {
final float keyguardExpansionFraction = forceExpanded ? 1f : expansionFraction;
- if (mStatusIconsAlphaAnimator != null) {
- mStatusIconsAlphaAnimator.setPosition(keyguardExpansionFraction);
- }
+ if (mAlphaAnimator != null) {
+ mAlphaAnimator.setPosition(keyguardExpansionFraction);
+ }
+ if (mTranslationAnimator != null) {
+ mTranslationAnimator.setPosition(keyguardExpansionFraction);
+ }
+ // If forceExpanded (we are opening QS from lockscreen), the animators have been set to
+ // position = 1f.
if (forceExpanded) {
- // If the keyguard is showing, we want to offset the text so that it comes in at the
- // same time as the panel as it slides down.
- mHeaderTextContainerView.setTranslationY(panelTranslationY);
+ setTranslationY(panelTranslationY);
} else {
- mHeaderTextContainerView.setTranslationY(0f);
- }
-
- if (mHeaderTextContainerAlphaAnimator != null) {
- mHeaderTextContainerAlphaAnimator.setPosition(keyguardExpansionFraction);
- if (keyguardExpansionFraction > 0) {
- mHeaderTextContainerView.setVisibility(VISIBLE);
- } else {
- mHeaderTextContainerView.setVisibility(INVISIBLE);
- }
+ setTranslationY(0);
}
mKeyguardExpansionFraction = keyguardExpansionFraction;
@@ -341,28 +287,21 @@
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
mHeaderQsPanel.setDisabledByPolicy(disabled);
- mHeaderTextContainerView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
- mQuickQsStatusIcons.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
+ mClockIconsView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
updateResources();
}
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- // Handle padding of the clock
+ // Handle padding of the views
DisplayCutout cutout = insets.getDisplayCutout();
Pair<Integer, Integer> cornerCutoutPadding = StatusBarWindowView.cornerCutoutMargins(
cutout, getDisplay());
Pair<Integer, Integer> padding =
StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
cutout, cornerCutoutPadding, -1);
- if (padding == null) {
- mSystemIconsView.setPaddingRelative(
- getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0,
- getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), 0);
- } else {
- mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
-
- }
+ mDatePrivacyView.setPadding(padding.first, 0, padding.second, 0);
+ mClockIconsView.setPadding(padding.first, 0, padding.second, 0);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams();
boolean cornerCutout = cornerCutoutPadding != null
&& (cornerCutoutPadding.first == 0 || cornerCutoutPadding.second == 0);
@@ -380,13 +319,13 @@
mCutOutPaddingLeft = padding.first;
mCutOutPaddingRight = padding.second;
mWaterfallTopInset = cutout == null ? 0 : cutout.getWaterfallInsets().top;
- updateClockPadding();
+ updateHeadersPadding();
return super.onApplyWindowInsets(insets);
}
- private void updateClockPadding() {
- int clockPaddingLeft = 0;
- int clockPaddingRight = 0;
+ private void updateHeadersPadding() {
+ int paddingLeft = 0;
+ int paddingRight = 0;
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
int leftMargin = lp.leftMargin;
@@ -399,18 +338,22 @@
// if there's a cutout, let's use at least the rounded corner inset
int cutoutPadding = Math.max(mCutOutPaddingLeft, mRoundedCornerPadding);
int contentMarginLeft = isLayoutRtl() ? mContentMarginEnd : mContentMarginStart;
- clockPaddingLeft = Math.max(cutoutPadding - contentMarginLeft - leftMargin, 0);
+ paddingLeft = Math.max(cutoutPadding - contentMarginLeft - leftMargin, 0);
}
if (mCutOutPaddingRight > 0) {
// if there's a cutout, let's use at least the rounded corner inset
int cutoutPadding = Math.max(mCutOutPaddingRight, mRoundedCornerPadding);
int contentMarginRight = isLayoutRtl() ? mContentMarginStart : mContentMarginEnd;
- clockPaddingRight = Math.max(cutoutPadding - contentMarginRight - rightMargin, 0);
+ paddingRight = Math.max(cutoutPadding - contentMarginRight - rightMargin, 0);
}
- mSystemIconsView.setPadding(clockPaddingLeft,
+ mDatePrivacyView.setPadding(paddingLeft,
mWaterfallTopInset + mStatusBarPaddingTop,
- clockPaddingRight,
+ paddingRight,
+ 0);
+ mClockIconsView.setPadding(paddingLeft,
+ mWaterfallTopInset + mStatusBarPaddingTop,
+ paddingRight,
0);
}
@@ -422,61 +365,56 @@
mHeaderQsPanel.setCallback(qsPanelCallback);
}
- private String formatNextAlarm(AlarmClockInfo info, boolean use24HourFormat) {
- if (info == null) {
- return "";
- }
- String skeleton = use24HourFormat ? "EHm" : "Ehma";
- String pattern = android.text.format.DateFormat
- .getBestDateTimePattern(Locale.getDefault(), skeleton);
- return android.text.format.DateFormat.format(pattern, info.getTriggerTime()).toString();
- }
-
- public static float getColorIntensity(@ColorInt int color) {
- return color == Color.WHITE ? 0 : 1;
- }
-
- @NonNull
- @Override
- public Lifecycle getLifecycle() {
- return mLifecycle;
- }
-
/** */
public void setContentMargins(int marginStart, int marginEnd,
QuickQSPanelController quickQSPanelController) {
mContentMarginStart = marginStart;
mContentMarginEnd = marginEnd;
- for (int i = 0; i < getChildCount(); i++) {
- View view = getChildAt(i);
- if (view == mHeaderQsPanel) {
- // QS panel doesn't lays out some of its content full width
- quickQSPanelController.setContentMargins(marginStart, marginEnd);
- } else {
- MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
- lp.setMarginStart(marginStart);
- lp.setMarginEnd(marginEnd);
- view.setLayoutParams(lp);
- }
- }
- updateClockPadding();
+ // The clock and QQS are not direct children, but the container should be just a wrapper to
+ // be able to move them together. So we set the margins to the actual views.
+ quickQSPanelController.setContentMargins(0, 0);
+ setContentMargins(mDatePrivacyView, marginStart, marginEnd);
+ setContentMargins(mClockIconsView, marginStart, marginEnd);
+ updateHeadersPadding();
}
+ private void setContentMargins(View view, int marginStart, int marginEnd) {
+ MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
+ lp.setMarginStart(marginStart);
+ lp.setMarginEnd(marginEnd);
+ view.setLayoutParams(lp);
+ }
+
+ /**
+ * When QS is scrolling, mClockIconsAlpha should scroll away and fade out.
+ *
+ * For a given scroll level, this method does the following:
+ * <ol>
+ * <li>Determine the alpha that {@code mClockIconsView} should have when the panel is fully
+ * expanded.</li>
+ * <li>Set the scroll of {@code mClockIconsView} to the same of {@code QSPanel}.</li>
+ * <li>Set the alpha of {@code mClockIconsView} to that determined by the expansion of
+ * the panel, interpolated between 1 (no expansion) and {@code mClockIconsAlpha} (fully
+ * expanded), matching the animator.</li>
+ * </ol>
+ *
+ * @param scrollY the scroll of the QSPanel container
+ */
public void setExpandedScrollAmount(int scrollY) {
// The scrolling of the expanded qs has changed. Since the header text isn't part of it,
// but would overlap content, we're fading it out.
float newAlpha = 1.0f;
- if (mHeaderTextContainerView.getHeight() > 0) {
- newAlpha = MathUtils.map(0, mHeaderTextContainerView.getHeight() / 2.0f, 1.0f, 0.0f,
+ if (mClockIconsView.getHeight() > 0) {
+ newAlpha = MathUtils.map(0, mClockIconsView.getHeight() / 2.0f, 1.0f, 0.0f,
scrollY);
newAlpha = Interpolators.ALPHA_OUT.getInterpolation(newAlpha);
}
- mHeaderTextContainerView.setScrollY(scrollY);
- if (newAlpha != mExpandedHeaderAlpha) {
- mExpandedHeaderAlpha = newAlpha;
- mHeaderTextContainerView.setAlpha(MathUtils.lerp(0.0f, mExpandedHeaderAlpha,
+ mClockIconsView.setScrollY(scrollY);
+ if (newAlpha != mClockIconsAlpha) {
+ mClockIconsAlpha = newAlpha;
+ mClockIconsView.setAlpha(MathUtils.lerp(1.0f, mClockIconsAlpha,
mKeyguardExpansionFraction));
- updateHeaderTextContainerAlphaAnimator();
+ updateAlphaAnimator();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index b1689f6..3aafea98 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -16,21 +16,13 @@
package com.android.systemui.qs;
-import android.app.AlarmManager.AlarmClockInfo;
import android.content.Intent;
-import android.media.AudioManager;
import android.os.Bundle;
import android.provider.AlarmClock;
-import android.provider.Settings;
-import android.service.notification.ZenModeConfig;
-import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import androidx.annotation.NonNull;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.LifecycleRegistry;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.logging.UiEventLogger;
@@ -47,15 +39,9 @@
import com.android.systemui.privacy.logging.PrivacyLogger;
import com.android.systemui.qs.carrier.QSCarrierGroupController;
import com.android.systemui.qs.dagger.QSScope;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.policy.Clock;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
-import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeController.Callback;
-import com.android.systemui.util.RingerModeTracker;
import com.android.systemui.util.ViewController;
import java.util.ArrayList;
@@ -70,75 +56,29 @@
class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> {
private static final String TAG = "QuickStatusBarHeader";
- private final ZenModeController mZenModeController;
- private final NextAlarmController mNextAlarmController;
private final PrivacyItemController mPrivacyItemController;
- private final RingerModeTracker mRingerModeTracker;
private final ActivityStarter mActivityStarter;
private final UiEventLogger mUiEventLogger;
private final QSCarrierGroupController mQSCarrierGroupController;
private final QuickQSPanelController mHeaderQsPanelController;
- private final LifecycleRegistry mLifecycle;
private final OngoingPrivacyChip mPrivacyChip;
private final Clock mClockView;
- private final View mNextAlarmContainer;
- private final View mRingerContainer;
- private final QSTileHost mQSTileHost;
private final StatusBarIconController mStatusBarIconController;
private final DemoModeController mDemoModeController;
- private final UserTracker mUserTracker;
private final StatusIconContainer mIconContainer;
private final StatusBarIconController.TintedIconManager mIconManager;
private final DemoMode mDemoModeReceiver;
private final PrivacyLogger mPrivacyLogger;
private final PrivacyDialogController mPrivacyDialogController;
+ private final QSExpansionPathInterpolator mQSExpansionPathInterpolator;
private boolean mListening;
- private AlarmClockInfo mNextAlarm;
private boolean mMicCameraIndicatorsEnabled;
private boolean mLocationIndicatorsEnabled;
private boolean mPrivacyChipLogged;
private SysuiColorExtractor mColorExtractor;
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
- private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
-
- private final ZenModeController.Callback mZenModeControllerCallback = new Callback() {
- @Override
- public void onZenChanged(int zen) {
- mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
- use24HourFormat());
- }
-
- @Override
- public void onConfigChanged(ZenModeConfig config) {
- mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
- use24HourFormat());
- }
- };
-
- private boolean use24HourFormat() {
- return android.text.format.DateFormat.is24HourFormat(
- mView.getContext(), mUserTracker.getUserId());
-
- }
-
- private final NextAlarmChangeCallback mNextAlarmChangeCallback = new NextAlarmChangeCallback() {
- @Override
- public void onNextAlarmChanged(AlarmClockInfo nextAlarm) {
- mNextAlarm = nextAlarm;
- mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
- use24HourFormat());
- }
- };
-
- private final LifecycleOwner mLifecycleOwner = new LifecycleOwner() {
- @NonNull
- @Override
- public Lifecycle getLifecycle() {
- return mLifecycle;
- }
- };
private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
@Override
@@ -176,63 +116,43 @@
if (v == mClockView) {
mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
AlarmClock.ACTION_SHOW_ALARMS), 0);
- } else if (v == mNextAlarmContainer && mNextAlarmContainer.isVisibleToUser()) {
- if (mNextAlarm.getShowIntent() != null) {
- mActivityStarter.postStartActivityDismissingKeyguard(
- mNextAlarm.getShowIntent());
- } else {
- Log.d(TAG, "No PendingIntent for next alarm. Using default intent");
- mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
- AlarmClock.ACTION_SHOW_ALARMS), 0);
- }
} else if (v == mPrivacyChip) {
// If the privacy chip is visible, it means there were some indicators
mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK);
mPrivacyDialogController.showDialog(getContext());
- } else if (v == mRingerContainer && mRingerContainer.isVisibleToUser()) {
- mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
- Settings.ACTION_SOUND_SETTINGS), 0);
}
}
};
@Inject
QuickStatusBarHeaderController(QuickStatusBarHeader view,
- ZenModeController zenModeController, NextAlarmController nextAlarmController,
- PrivacyItemController privacyItemController, RingerModeTracker ringerModeTracker,
+ PrivacyItemController privacyItemController,
ActivityStarter activityStarter, UiEventLogger uiEventLogger,
- QSTileHost qsTileHost, StatusBarIconController statusBarIconController,
+ StatusBarIconController statusBarIconController,
DemoModeController demoModeController,
- UserTracker userTracker, QuickQSPanelController quickQSPanelController,
+ QuickQSPanelController quickQSPanelController,
QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder,
PrivacyLogger privacyLogger,
SysuiColorExtractor colorExtractor,
- PrivacyDialogController privacyDialogController) {
+ PrivacyDialogController privacyDialogController,
+ QSExpansionPathInterpolator qsExpansionPathInterpolator) {
super(view);
- mZenModeController = zenModeController;
- mNextAlarmController = nextAlarmController;
mPrivacyItemController = privacyItemController;
- mRingerModeTracker = ringerModeTracker;
mActivityStarter = activityStarter;
mUiEventLogger = uiEventLogger;
- mQSTileHost = qsTileHost;
mStatusBarIconController = statusBarIconController;
mDemoModeController = demoModeController;
- mUserTracker = userTracker;
- mLifecycle = new LifecycleRegistry(mLifecycleOwner);
mHeaderQsPanelController = quickQSPanelController;
mPrivacyLogger = privacyLogger;
mPrivacyDialogController = privacyDialogController;
+ mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
mQSCarrierGroupController = qsCarrierGroupControllerBuilder
.setQSCarrierGroup(mView.findViewById(R.id.carrier_group))
.build();
-
mPrivacyChip = mView.findViewById(R.id.privacy_chip);
- mNextAlarmContainer = mView.findViewById(R.id.alarm_container);
mClockView = mView.findViewById(R.id.clock);
- mRingerContainer = mView.findViewById(R.id.ringer_container);
mIconContainer = mView.findViewById(R.id.statusIcons);
mIconManager = new StatusBarIconController.TintedIconManager(mIconContainer);
@@ -247,15 +167,7 @@
@Override
protected void onViewAttached() {
- mRingerModeTracker.getRingerModeInternal().observe(mLifecycleOwner, ringer -> {
- mRingerMode = ringer;
- mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
- use24HourFormat());
- });
-
mClockView.setOnClickListener(mOnClickListener);
- mNextAlarmContainer.setOnClickListener(mOnClickListener);
- mRingerContainer.setOnClickListener(mOnClickListener);
mPrivacyChip.setOnClickListener(mOnClickListener);
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
@@ -268,18 +180,15 @@
setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
- mView.onAttach(mIconManager);
+ mView.onAttach(mIconManager, mQSExpansionPathInterpolator);
mDemoModeController.addCallback(mDemoModeReceiver);
}
@Override
protected void onViewDetached() {
- mRingerModeTracker.getRingerModeInternal().removeObservers(mLifecycleOwner);
mClockView.setOnClickListener(null);
mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
- mNextAlarmContainer.setOnClickListener(null);
- mRingerContainer.setOnClickListener(null);
mPrivacyChip.setOnClickListener(null);
mStatusBarIconController.removeIconGroup(mIconManager);
mDemoModeController.removeCallback(mDemoModeReceiver);
@@ -304,17 +213,11 @@
}
if (listening) {
- mZenModeController.addCallback(mZenModeControllerCallback);
- mNextAlarmController.addCallback(mNextAlarmChangeCallback);
- mLifecycle.setCurrentState(Lifecycle.State.RESUMED);
// Get the most up to date info
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
mPrivacyItemController.addCallback(mPICCallback);
} else {
- mZenModeController.removeCallback(mZenModeControllerCallback);
- mNextAlarmController.removeCallback(mNextAlarmChangeCallback);
- mLifecycle.setCurrentState(Lifecycle.State.CREATED);
mPrivacyItemController.removeCallback(mPICCallback);
mPrivacyChipLogged = false;
}
@@ -357,11 +260,6 @@
return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled;
}
- private boolean isZenOverridingRinger() {
- return ZenModeConfig.isZenOverridingRinger(mZenModeController.getZen(),
- mZenModeController.getConsolidatedPolicy());
- }
-
public void setContentMargins(int contentPaddingStart, int contentPaddingEnd) {
mView.setContentMargins(contentPaddingStart, contentPaddingEnd, mHeaderQsPanelController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
index 0ebadfd..1ba11ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
@@ -18,6 +18,7 @@
import android.content.Context
import android.util.AttributeSet
+import com.android.systemui.R
open class SideLabelTileLayout(
context: Context,
@@ -26,7 +27,7 @@
override fun updateResources(): Boolean {
return super.updateResources().also {
- mMaxAllowedRows = 4
+ mMaxAllowedRows = context.resources.getInteger(R.integer.quick_settings_max_rows)
}
}
@@ -34,6 +35,10 @@
return mRecords.size >= maxTiles()
}
+ override fun useSidePadding(): Boolean {
+ return false
+ }
+
/**
* Return the position from the top of the layout of the tile with this index.
*
@@ -44,4 +49,19 @@
val row = index / mColumns
return getRowTop(row)
}
+
+ override fun updateMaxRows(allowedHeight: Int, tilesCount: Int): Boolean {
+ val previousRows = mRows
+ mRows = mMaxAllowedRows
+ // We want at most mMaxAllowedRows, but it could be that we don't have enough tiles to fit
+ // that many rows. In that case, we want
+ // `tilesCount = (mRows - 1) * mColumns + X`
+ // where X is some remainder between 1 and `mColumns - 1`
+ // Adding `mColumns - 1` will guarantee that the final value F will satisfy
+ // `mRows * mColumns <= F < (mRows + 1) * mColumns
+ if (mRows > (tilesCount + mColumns - 1) / mColumns) {
+ mRows = (tilesCount + mColumns - 1) / mColumns
+ }
+ return previousRows != mRows
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 9e0aa5a..96712bd9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -121,6 +121,7 @@
updateColumns();
mMaxCellHeight = mContext.getResources().getDimensionPixelSize(mCellHeightResId);
mCellMarginHorizontal = res.getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal);
+ mSidePadding = useSidePadding() ? mCellMarginHorizontal / 2 : 0;
mCellMarginVertical= res.getDimensionPixelSize(R.dimen.qs_tile_margin_vertical);
mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
mMaxAllowedRows = Math.max(1, getResources().getInteger(R.integer.quick_settings_max_rows));
@@ -132,6 +133,10 @@
return false;
}
+ protected boolean useSidePadding() {
+ return true;
+ }
+
private boolean updateColumns() {
int oldColumns = mColumns;
mColumns = Math.min(mResourceColumns, mMaxColumns);
@@ -150,8 +155,9 @@
if (heightMode == MeasureSpec.UNSPECIFIED) {
mRows = (numTiles + mColumns - 1) / mColumns;
}
+ final int gaps = mColumns - 1;
mCellWidth =
- (availableWidth - (mCellMarginHorizontal * mColumns)) / mColumns;
+ (availableWidth - (mCellMarginHorizontal * gaps) - mSidePadding * 2) / mColumns;
// Measure each QS tile.
View previousView = this;
@@ -241,8 +247,8 @@
}
protected int getColumnStart(int column) {
- return getPaddingStart() + mCellMarginHorizontal / 2 +
- column * (mCellWidth + mCellMarginHorizontal);
+ return getPaddingStart() + mSidePadding
+ + column * (mCellWidth + mCellMarginHorizontal);
}
@Override
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 0adc844..e9abef4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -35,6 +35,7 @@
import androidx.annotation.Nullable;
import androidx.core.view.AccessibilityDelegateCompat;
import androidx.core.view.ViewCompat;
+import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
@@ -118,11 +119,12 @@
mUiEventLogger = uiEventLogger;
mItemTouchHelper = new ItemTouchHelper(mCallbacks);
mDecoration = new TileItemDecoration(context);
- mMarginDecoration = new MarginTileDecoration();
+ mMarginDecoration = new MarginTileDecoration(!useHorizontalTiles);
mMinNumTiles = context.getResources().getInteger(R.integer.quick_settings_min_num_tiles);
mNumColumns = context.getResources().getInteger(NUM_COLUMNS_ID);
mAccessibilityDelegate = new TileAdapterDelegate();
mUseHorizontalTiles = useHorizontalTiles;
+ mSizeLookup.setSpanIndexCacheEnabled(true);
}
@Override
@@ -708,6 +710,11 @@
private static class MarginTileDecoration extends ItemDecoration {
private int mHalfMargin;
+ private final boolean mUseOutsideMargins;
+
+ private MarginTileDecoration(boolean useOutsideMargins) {
+ mUseOutsideMargins = useOutsideMargins;
+ }
public void setHalfMargin(int halfMargin) {
mHalfMargin = halfMargin;
@@ -716,11 +723,30 @@
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view,
@NonNull RecyclerView parent, @NonNull State state) {
+ if (parent.getLayoutManager() == null) return;
+
+ GridLayoutManager lm = ((GridLayoutManager) parent.getLayoutManager());
+ SpanSizeLookup span = lm.getSpanSizeLookup();
+ ViewHolder holder = parent.getChildViewHolder(view);
+ int column = span.getSpanIndex(holder.getLayoutPosition(), lm.getSpanCount());
+
if (view instanceof TextView) {
super.getItemOffsets(outRect, view, parent, state);
} else {
- outRect.left = mHalfMargin;
- outRect.right = mHalfMargin;
+ if (mUseOutsideMargins || (column != 0 && column != lm.getSpanCount() - 1)) {
+ // Using outside margins or in a column that's not leftmost or rightmost
+ // (half of the margin between columns).
+ outRect.left = mHalfMargin;
+ outRect.right = mHalfMargin;
+ } else if (column == 0) {
+ // Leftmost column when not using side margins. Should only have margin on the
+ // right.
+ outRect.right = mHalfMargin;
+ } else {
+ // Rightmost column when not using side margins. Should only have margin on the
+ // left.
+ outRect.left = mHalfMargin;
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index f9d1def..a17aeba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -56,7 +56,6 @@
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.Utils;
import com.android.systemui.Dumpable;
-import com.android.systemui.Prefs;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
@@ -67,7 +66,6 @@
import com.android.systemui.qs.PagedTileLayout.TilePage;
import com.android.systemui.qs.QSEvent;
import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.QuickStatusBarHeader;
import com.android.systemui.qs.logging.QSLogger;
import java.io.FileDescriptor;
@@ -300,11 +298,6 @@
getInstanceId());
mQSLogger.logTileLongClick(mTileSpec, mStatusBarStateController.getState(), mState.state);
mHandler.sendEmptyMessage(H.LONG_CLICK);
-
- Prefs.putInt(
- mContext,
- Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT,
- QuickStatusBarHeader.MAX_TOOLTIP_SHOWN_COUNT);
}
public LogMaker populate(LogMaker logMaker) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
index 03a6689..44eeaf4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
@@ -27,6 +27,7 @@
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R.drawable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -45,8 +46,7 @@
public class ReduceBrightColorsTile extends QSTileImpl<QSTile.BooleanState>
implements ReduceBrightColorsController.Listener{
- //TODO(b/170973645): get icon drawable
- private final Icon mIcon = null;
+ private final Icon mIcon = ResourceIcon.get(drawable.ic_reduce_bright_colors);
private final boolean mIsAvailable;
private final ReduceBrightColorsController mReduceBrightColorsController;
private boolean mIsListening;
@@ -108,6 +108,7 @@
state.label = mContext.getString(R.string.reduce_bright_colors_feature_name);
state.expandedAccessibilityClassName = Switch.class.getName();
state.contentDescription = state.label;
+ state.icon = mIcon;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
index 0b40e22..5d964a4 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
@@ -27,7 +27,10 @@
import androidx.annotation.Nullable;
import com.android.settingslib.RestrictedLockUtils;
+import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
+import com.android.systemui.classifier.Classifier;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.util.ViewController;
@@ -42,9 +45,7 @@
*
* @see BrightnessMirrorController
*/
-public class BrightnessSlider
- extends ViewController<View>
- implements ToggleSlider {
+public class BrightnessSlider extends ViewController<View> implements ToggleSlider {
private Listener mListener;
private ToggleSlider mMirror;
@@ -52,15 +53,34 @@
private BrightnessMirrorController mMirrorController;
private boolean mTracking;
private final boolean mUseMirror;
+ private final FalsingManager mFalsingManager;
+
+ private final Gefingerpoken mOnInterceptListener = new Gefingerpoken() {
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ int action = ev.getActionMasked();
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ mFalsingManager.isFalseTouch(Classifier.BRIGHTNESS_SLIDER);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ return false;
+ }
+ };
BrightnessSlider(
View rootView,
BrightnessSliderView brightnessSliderView,
- boolean useMirror
- ) {
+ boolean useMirror,
+ FalsingManager falsingManager) {
super(rootView);
mBrightnessSliderView = brightnessSliderView;
mUseMirror = useMirror;
+ mFalsingManager = falsingManager;
}
/**
@@ -78,6 +98,7 @@
protected void onViewAttached() {
mBrightnessSliderView.setOnSeekBarChangeListener(mSeekListener);
mBrightnessSliderView.setOnCheckedChangeListener(mCheckListener);
+ mBrightnessSliderView.setOnInterceptListener(mOnInterceptListener);
}
@Override
@@ -85,6 +106,7 @@
mBrightnessSliderView.setOnSeekBarChangeListener(null);
mBrightnessSliderView.setOnCheckedChangeListener(null);
mBrightnessSliderView.setOnDispatchTouchEventListener(null);
+ mBrightnessSliderView.setOnInterceptListener(null);
}
@Override
@@ -247,10 +269,12 @@
public static class Factory {
BrightnessControllerSettings mSettings;
+ private final FalsingManager mFalsingManager;
@Inject
- public Factory(BrightnessControllerSettings settings) {
+ public Factory(BrightnessControllerSettings settings, FalsingManager falsingManager) {
mSettings = settings;
+ mFalsingManager = falsingManager;
}
/**
@@ -270,7 +294,7 @@
private BrightnessSlider fromTree(ViewGroup root, boolean useMirror) {
BrightnessSliderView v = root.requireViewById(R.id.brightness_slider);
- return new BrightnessSlider(root, v, useMirror);
+ return new BrightnessSlider(root, v, useMirror, mFalsingManager);
}
/** Get the layout to inflate based on what slider to use */
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index cbf4e88..5b71c62 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -31,6 +31,7 @@
import androidx.annotation.Nullable;
import com.android.settingslib.RestrictedLockUtils;
+import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
/**
@@ -54,6 +55,7 @@
private TextView mLabel;
private final CharSequence mText;
private DispatchTouchEventListener mListener;
+ private Gefingerpoken mOnInterceptListener;
public BrightnessSliderView(Context context) {
this(context, null);
@@ -105,6 +107,15 @@
return super.dispatchTouchEvent(ev);
}
+ @Override
+ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ // We prevent disallowing on this view, but bubble it up to our parents.
+ // We need interception to handle falsing.
+ if (mParent != null) {
+ mParent.requestDisallowInterceptTouchEvent(disallowIntercept);
+ }
+ }
+
/**
* Attaches a listener to the {@link ToggleSeekBar} in the view so changes can be observed
* @param seekListener use {@code null} to remove listener
@@ -195,6 +206,18 @@
return mSlider.getProgress();
}
+ public void setOnInterceptListener(Gefingerpoken onInterceptListener) {
+ mOnInterceptListener = onInterceptListener;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (mOnInterceptListener != null) {
+ return mOnInterceptListener.onInterceptTouchEvent(ev);
+ }
+ return super.onInterceptTouchEvent(ev);
+ }
+
/**
* Interface to attach a listener for {@link View#dispatchTouchEvent}.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 138c811..ab17ee0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -59,6 +59,7 @@
private View mMobileRoamingSpace;
private int mVisibleState = -1;
private DualToneHandler mDualToneHandler;
+ private boolean mForceHidden;
public static StatusBarMobileView fromContext(Context context, String slot) {
LayoutInflater inflater = LayoutInflater.from(context);
@@ -150,7 +151,7 @@
private void initViewState() {
setContentDescription(mState.contentDescription);
- if (!mState.visible) {
+ if (!mState.visible || mForceHidden) {
mMobileGroup.setVisibility(View.GONE);
} else {
mMobileGroup.setVisibility(View.VISIBLE);
@@ -176,8 +177,9 @@
boolean needsLayout = false;
setContentDescription(state.contentDescription);
- if (mState.visible != state.visible) {
- mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
+ int newVisibility = state.visible && !mForceHidden ? View.VISIBLE : View.GONE;
+ if (newVisibility != mMobileGroup.getVisibility()) {
+ mMobileGroup.setVisibility(newVisibility);
needsLayout = true;
}
if (mState.strengthId != state.strengthId) {
@@ -252,7 +254,7 @@
@Override
public boolean isIconVisible() {
- return mState.visible;
+ return mState.visible && !mForceHidden;
}
@Override
@@ -279,6 +281,23 @@
}
}
+ /**
+ * Forces the state to be hidden (views will be GONE) and if necessary updates the layout.
+ *
+ * Makes sure that the {@link StatusBarIconController} cannot make it visible while this flag
+ * is enabled.
+ * @param forceHidden {@code true} if the icon should be GONE in its view regardless of its
+ * state.
+ * {@code false} if the icon should show as determined by its controller.
+ */
+ public void forceHidden(boolean forceHidden) {
+ if (mForceHidden != forceHidden) {
+ mForceHidden = forceHidden;
+ updateState(mState);
+ requestLayout();
+ }
+ }
+
@Override
public int getVisibleState() {
return mVisibleState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 50cbbd5d..91a4f94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -393,6 +393,11 @@
override fun onDozingChanged(isDozing: Boolean) {
if (isDozing) {
setNotificationsVisible(visible = false, animate = false, increaseSpeed = false)
+ } else {
+ // We only unset the flag once we fully went asleep. If the user interrupts the
+ // animation in the middle, we have to abort the animation as well to make sure
+ // the notifications are visible again.
+ animatingScreenOff = false
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index 609ca97c..3728388 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -25,7 +25,6 @@
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import com.android.systemui.R;
@@ -102,28 +101,6 @@
}
};
- /**
- * Get the relative start padding of a view relative to this view. This recursively walks up the
- * hierarchy and does the corresponding measuring.
- *
- * @param view the view to get the padding for. The requested view has to be a child of this
- * notification.
- * @return the start padding
- */
- public int getRelativeStartPadding(View view) {
- boolean isRtl = isLayoutRtl();
- int startPadding = 0;
- while (view.getParent() instanceof ViewGroup) {
- View parent = (View) view.getParent();
- startPadding += isRtl ? parent.getWidth() - view.getRight() : view.getLeft();
- view = parent;
- if (view == this) {
- return startPadding;
- }
- }
- return startPadding;
- }
-
protected Path getClipPath(boolean ignoreTranslation) {
int left;
int top;
@@ -132,17 +109,15 @@
int height;
float topRoundness = mAlwaysRoundBothCorners
? mOutlineRadius : getCurrentBackgroundRadiusTop();
-
if (!mCustomOutline) {
- // Extend left/right clip bounds beyond the notification by the
- // 1) space between the notification and edge of screen
- // 2) corner radius (so we do not see any rounding as the notification goes off screen)
- left = (int) (-getRelativeStartPadding(this) - mOutlineRadius);
- right = (int) (((View) getParent()).getWidth() + mOutlineRadius);
-
+ int translation = mShouldTranslateContents && !ignoreTranslation
+ ? (int) getTranslation() : 0;
+ int halfExtraWidth = (int) (mExtraWidthForClipping / 2.0f);
+ left = Math.max(translation, 0) - halfExtraWidth;
+ top = mClipTopAmount + mBackgroundTop;
+ right = getWidth() + halfExtraWidth + Math.min(translation, 0);
// If the top is rounded we want the bottom to be at most at the top roundness, in order
// to avoid the shadow changing when scrolling up.
- top = mClipTopAmount + mBackgroundTop;
bottom = Math.max(mMinimumHeightForClipping,
Math.max(getActualHeight() - mClipBottomAmount, (int) (top + topRoundness)));
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 1086d67..73e0804 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -69,8 +69,6 @@
private float mContentTranslation;
protected boolean mLastInSection;
protected boolean mFirstInSection;
- private float mOutlineRadius;
- private float mParentWidth;
public ExpandableView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -81,7 +79,6 @@
private void initDimens() {
mContentShift = getResources().getDimensionPixelSize(
R.dimen.shelf_transform_content_shift);
- mOutlineRadius = getResources().getDimensionPixelSize(R.dimen.notification_corner_radius);
}
@Override
@@ -153,9 +150,6 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- if (getParent() != null) {
- mParentWidth = ((View) getParent()).getWidth();
- }
updateClipping();
}
@@ -442,15 +436,11 @@
protected void updateClipping() {
if (mClipToActualHeight && shouldClipToActualHeight()) {
- final int top = getClipTopAmount();
- final int bottom = Math.max(Math.max(getActualHeight() + getExtraBottomPadding()
+ int top = getClipTopAmount();
+ int bottom = Math.max(Math.max(getActualHeight() + getExtraBottomPadding()
- mClipBottomAmount, top), mMinimumHeightForClipping);
- // Extend left/right clip bounds beyond the notification by the
- // 1) space between the notification and edge of screen
- // 2) corner radius (so we do not see any rounding as the notification goes off screen)
- final int left = (int) (-getRelativeStartPadding(this) - mOutlineRadius);
- final int right = (int) (mParentWidth + mOutlineRadius);
- mClipRect.set(left, top, right, bottom);
+ int halfExtraWidth = (int) (mExtraWidthForClipping / 2.0f);
+ mClipRect.set(-halfExtraWidth, top, getWidth() + halfExtraWidth, bottom);
setClipBounds(mClipRect);
} else {
setClipBounds(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index 3ec8c23..4ed5056 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -93,6 +93,13 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
+ mDismissButton.setBackground(
+ getResources().getDrawable(R.drawable.notif_footer_btn_background));
+ mDismissButton.setTextColor(getResources().getColor(R.color.notif_pill_text));
+ mManageButton.setBackground(
+ getResources().getDrawable(R.drawable.notif_footer_btn_background));
+ mManageButton.setTextColor(getResources().getColor(R.color.notif_pill_text));
+ mManageButton = findViewById(R.id.manage_text);
mDismissButton.setText(R.string.clear_all_notifications_text);
mDismissButton.setContentDescription(
mContext.getString(R.string.accessibility_clear_all));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 55a27b2..c3ccba4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1291,9 +1291,14 @@
}
}
}
-
- if (existing != null && entry.getSbn().getNotification().isColorized()) {
- existing.overrideBackgroundTintColor(entry.getSbn().getNotification().color);
+ if (existing != null) {
+ if (entry.getSbn().getNotification().isColorized()) {
+ existing.setBackgroundTintColor(
+ entry.getSbn().getNotification().color, true);
+ } else {
+ existing.setBackgroundTintColor(
+ entry.getRow().getCurrentBackgroundTint(), false);
+ }
}
return existing;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 80109cb..b891e6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -73,6 +73,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.camera.CameraIntents;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.IntentButtonProvider;
import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
@@ -110,11 +111,6 @@
private static final String RIGHT_BUTTON_PLUGIN
= "com.android.systemui.action.PLUGIN_LOCKSCREEN_RIGHT_BUTTON";
- private static final Intent SECURE_CAMERA_INTENT =
- new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
- .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- public static final Intent INSECURE_CAMERA_INTENT =
- new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
@@ -498,7 +494,7 @@
intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
boolean wouldLaunchResolverActivity = mActivityIntentHelper.wouldLaunchResolverActivity(
intent, KeyguardUpdateMonitor.getCurrentUser());
- if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
+ if (CameraIntents.isSecureCameraIntent(intent) && !wouldLaunchResolverActivity) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
@@ -855,7 +851,11 @@
public Intent getIntent() {
boolean canDismissLs = mKeyguardStateController.canDismissLockScreen();
boolean secure = mKeyguardStateController.isMethodSecure();
- return (secure && !canDismissLs) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
+ if (secure && !canDismissLs) {
+ return CameraIntents.getSecureCameraIntent(getContext());
+ } else {
+ return CameraIntents.getInsecureCameraIntent(getContext());
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index d581c4b6..012439e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -150,6 +150,7 @@
import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.camera.CameraIntents;
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -2662,6 +2663,12 @@
for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue());
}
+
+ pw.println("Camera gesture intents:");
+ pw.println(" Insecure camera: " + CameraIntents.getInsecureCameraIntent(mContext));
+ pw.println(" Secure camera: " + CameraIntents.getSecureCameraIntent(mContext));
+ pw.println(" Override package: "
+ + String.valueOf(CameraIntents.getOverrideCameraPackage(mContext)));
}
public static void dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions) {
@@ -2734,7 +2741,7 @@
null /* remoteAnimation */));
options.setDisallowEnterPictureInPictureWhileLaunching(
disallowEnterPictureInPictureWhileLaunching);
- if (intent == KeyguardBottomAreaView.INSECURE_CAMERA_INTENT) {
+ if (CameraIntents.isInsecureCameraIntent(intent)) {
// Normally an activity will set it's requested rotation
// animation on its window. However when launching an activity
// causes the orientation to change this is too late. In these cases
@@ -2964,7 +2971,7 @@
}
mPowerButtonReveal = new PowerButtonReveal(mContext.getResources().getDimensionPixelSize(
- R.dimen.global_actions_top_padding));
+ com.android.systemui.R.dimen.physical_power_button_center_screen_location_y));
}
// Visibility reporting
@@ -4023,7 +4030,8 @@
}
if (!mStatusBarKeyguardViewManager.isShowing()) {
- startActivityDismissingKeyguard(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT,
+ final Intent cameraIntent = CameraIntents.getInsecureCameraIntent(mContext);
+ startActivityDismissingKeyguard(cameraIntent,
false /* onlyProvisioned */, true /* dismissShade */,
true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index c6f7983..779ba1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -33,6 +33,8 @@
import android.view.WindowInsets;
import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
+
import com.android.systemui.util.leak.RotationUtils;
/**
@@ -91,6 +93,7 @@
* @param roundedCornerContentPadding
* @return
*/
+ @NonNull
public static Pair<Integer, Integer> paddingNeededForCutoutAndRoundedCorner(
DisplayCutout cutout, Pair<Integer, Integer> cornerCutoutPadding,
int roundedCornerContentPadding) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index f65f97a..64a497d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -262,6 +262,25 @@
}
/**
+ * Returns the view corresponding to a particular slot.
+ *
+ * Use it solely to manipulate how it is presented.
+ * @param slot name of the slot to find. Names are defined in
+ * {@link com.android.internal.R.config_statusBarIcons}
+ * @return a view for the slot if this container has it, else {@code null}
+ */
+ public View getViewForSlot(String slot) {
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ if (child instanceof StatusIconDisplayable
+ && ((StatusIconDisplayable) child).getSlot().equals(slot)) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ /**
* Layout is happening from end -> start
*/
private void calculateIconTranslations() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index f72d2ae..5a78ea8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -32,7 +32,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ShortcutManager;
import android.content.res.ColorStateList;
-import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Rect;
@@ -74,6 +73,7 @@
import androidx.annotation.NonNull;
+import com.android.internal.graphics.ColorUtils;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.statusbar.IStatusBarService;
@@ -130,6 +130,9 @@
private int mRevealCy;
private int mRevealR;
+ private boolean mColorized;
+ private int mTint;
+
private boolean mResetting;
private NotificationViewWrapper mWrapper;
private Consumer<Boolean> mOnVisibilityChangedListener;
@@ -143,35 +146,63 @@
mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
mStatusBarManagerService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ TypedArray ta = getContext().getTheme().obtainStyledAttributes(new int[]{
+ com.android.internal.R.attr.colorAccent,
+ com.android.internal.R.attr.colorBackgroundFloating,
+ });
+ mTint = ta.getColor(0, 0);
+ ta.recycle();
}
/**
* The remote view needs to adapt to colorized notifications when set
+ * It overrides the background of itself as well as all of its childern
* @param color colorized notification color
*/
- public void overrideBackgroundTintColor(int color) {
- mEditText.setBackgroundTintColor(color);
- final boolean dark = !ContrastColorUtil.isColorLight(color);
- int[][] states = new int[][] {
- new int[] {android.R.attr.state_enabled},
- new int[] {},
+ public void setBackgroundTintColor(int color, boolean colorized) {
+ if (colorized == mColorized && color == mTint) return;
+ mColorized = colorized;
+ mTint = color;
+ final int[][] states = new int[][]{
+ new int[]{com.android.internal.R.attr.state_enabled},
+ new int[]{},
};
+ final int[] colors;
+ if (colorized) {
+ final boolean dark = !ContrastColorUtil.isColorLight(color);
+ final int finalColor = dark
+ ? Color.WHITE
+ : Color.BLACK;
+ colors = new int[]{
+ finalColor,
+ finalColor & 0x4DFFFFFF // %30 opacity
+ };
+ mEditText.setUniformBackgroundTintColor(color);
+ mEditText.setUniformForegroundColor(finalColor);
- final int finalColor = dark
- ? Color.WHITE
- : Color.BLACK;
-
- int[] colors = new int[] {
- finalColor,
- finalColor & 0x4DFFFFFF // %30 opacity
- };
-
- final ColorStateList tint = new ColorStateList(states, colors);
+ } else {
+ mEditText.setTextColor(mContext.getColor(R.color.remote_input_text));
+ mEditText.setHintTextColor(mContext.getColorStateList(R.color.remote_input_hint));
+ TypedArray ta = getContext().getTheme().obtainStyledAttributes(new int[]{
+ com.android.internal.R.attr.colorAccent,
+ com.android.internal.R.attr.colorBackgroundFloating,
+ });
+ int colorAccent = ta.getColor(0, 0);
+ int colorBackgroundFloating = ta.getColor(1, 0);
+ ta.recycle();
+ mEditText.setTextBackgroundColors(colorAccent, colorBackgroundFloating);
+ colors = new int[]{
+ colorAccent,
+ colorBackgroundFloating & 0x4DFFFFFF // %30 opacity
+ };
+ }
+ mEditText.setBackgroundColor(color);
+ final ColorStateList tint = new ColorStateList(states, colors);
mSendButton.setImageTintList(tint);
mProgressBar.setProgressTintList(tint);
mProgressBar.setIndeterminateTintList(tint);
mProgressBar.setSecondaryProgressTintList(tint);
- mEditText.setForegroundColor(finalColor);
+ setBackgroundColor(color);
}
@Override
@@ -326,7 +357,7 @@
reveal.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- setVisibility(INVISIBLE);
+ setVisibility(GONE);
if (mWrapper != null) {
mWrapper.setRemoteInputVisible(false);
}
@@ -334,7 +365,7 @@
});
reveal.start();
} else {
- setVisibility(INVISIBLE);
+ setVisibility(GONE);
if (mWrapper != null) {
mWrapper.setRemoteInputVisible(false);
}
@@ -398,12 +429,6 @@
}
}
- @Override
- public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- mEditText.updateCornerRadius(heightMeasureSpec / 2);
- }
-
/** Populates the text field of the remote input with the given content. */
public void setEditTextContent(@Nullable CharSequence editTextContent) {
mEditText.setText(editTextContent);
@@ -700,40 +725,15 @@
boolean mShowImeOnInputConnection;
private LightBarController mLightBarController;
private InputMethodManager mInputMethodManager;
- private int mColor = Notification.COLOR_DEFAULT;
UserHandle mUser;
- private int mStokeWidth;
public RemoteEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mLightBarController = Dependency.get(LightBarController.class);
- mTextBackground = createBackground(context, attrs);
+ mTextBackground = (GradientDrawable)
+ context.getDrawable(R.drawable.remote_input_view_text_bg).mutate();
mBackgroundColor = new ColorDrawable();
mBackground = new LayerDrawable(new Drawable[] {mBackgroundColor, mTextBackground});
- float density = context.getResources().getDisplayMetrics().density;
- mStokeWidth = (int) (2 * density);
- setDefaultColors();
- }
-
- private void setDefaultColors() {
- Resources.Theme theme = getContext().getTheme();
- TypedArray ta = theme.obtainStyledAttributes(
- new int[]{android.R.attr.colorAccent,
- com.android.internal.R.attr.colorBackgroundFloating});
- mTextBackground.setStroke(mStokeWidth,
- ta.getColor(0, Notification.COLOR_DEFAULT));
- mColor = ta.getColor(1, Notification.COLOR_DEFAULT);
- mTextBackground.setColor(mColor);
- }
-
- private GradientDrawable createBackground(Context context, AttributeSet attrs) {
- float density = context.getResources().getDisplayMetrics().density;
- int padding = (int) (12 * density);
- GradientDrawable d = new GradientDrawable();
- d.setShape(GradientDrawable.RECTANGLE);
- d.setPadding(padding, padding, padding, padding);
- d.setCornerRadius(padding);
- return d;
}
void setSupportedMimeTypes(@Nullable Collection<String> mimeTypes) {
@@ -796,16 +796,17 @@
}
}
- protected void setBackgroundTintColor(int color) {
+ protected void setUniformBackgroundTintColor(int color) {
mBackgroundColor.setColor(color);
mTextBackground.setColor(color);
}
- protected void setForegroundColor(int color) {
- mTextBackground.setStroke(mStokeWidth, color);
+ protected void setUniformForegroundColor(int color) {
+ int stroke = getContext().getResources()
+ .getDimensionPixelSize(R.dimen.remote_input_view_text_stroke);
+ mTextBackground.setStroke(stroke, color);
setTextColor(color);
- // %60
- setHintTextColor(color & 0x99FFFFFF);
+ setHintTextColor(ColorUtils.setAlphaComponent(color, 0x99));
setTextCursorDrawable(null);
}
@@ -896,10 +897,6 @@
setSelection(getText().length());
}
- void updateCornerRadius(float radius) {
- mTextBackground.setCornerRadius(radius);
- }
-
void setInnerFocusable(boolean focusable) {
setFocusableInTouchMode(focusable);
setFocusable(focusable);
@@ -924,16 +921,28 @@
if (clip.getItemCount() > 1
|| description.getMimeTypeCount() < 1
|| remainingItems != null) {
- // TODO(b/172363500): Update to loop over all the items
+ // Direct-reply in notifications currently only supports only one uri item
+ // at a time and requires the MIME type to be set.
+ Log.w(TAG, "Invalid payload: " + payload);
return payload;
}
Uri contentUri = clip.getItemAt(0).getUri();
String mimeType = description.getMimeType(0);
Intent dataIntent =
mRemoteInputView.prepareRemoteInputFromData(mimeType, contentUri);
+ // We can release the uri permissions granted to us as soon as we've created the
+ // grant for the target app in the call above.
+ payload.releasePermissions();
mRemoteInputView.sendRemoteInput(dataIntent);
}
return remainingItems;
}
+
+ protected void setTextBackgroundColors(int strokeColor, int textBackground) {
+ mTextBackground.setColor(textBackground);
+ int stroke = getContext().getResources()
+ .getDimensionPixelSize(R.dimen.remote_input_view_text_stroke);
+ mTextBackground.setStroke(stroke, strokeColor);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
index 278663b..3c1e123 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
@@ -15,6 +15,7 @@
*/
package com.android.systemui.theme;
+import android.annotation.AnyThread;
import android.content.om.FabricatedOverlay;
import android.content.om.OverlayIdentifier;
import android.content.om.OverlayInfo;
@@ -159,44 +160,48 @@
FabricatedOverlay[] pendingCreation,
int currentUser,
Set<UserHandle> managedProfiles) {
- // Disable all overlays that have not been specified in the user setting.
- final Set<String> overlayCategoriesToDisable = new HashSet<>(THEME_CATEGORIES);
- final Set<String> targetPackagesToQuery = overlayCategoriesToDisable.stream()
- .map(category -> mCategoryToTargetPackage.get(category))
- .collect(Collectors.toSet());
- final List<OverlayInfo> overlays = new ArrayList<>();
- targetPackagesToQuery.forEach(targetPackage -> overlays.addAll(mOverlayManager
- .getOverlayInfosForTarget(targetPackage, UserHandle.SYSTEM)));
- final List<Pair<String, String>> overlaysToDisable = overlays.stream()
- .filter(o ->
- mTargetPackageToCategories.get(o.targetPackageName).contains(o.category))
- .filter(o -> overlayCategoriesToDisable.contains(o.category))
- .filter(o -> !categoryToPackage.containsValue(new OverlayIdentifier(o.packageName)))
- .filter(o -> o.isEnabled())
- .map(o -> new Pair<>(o.category, o.packageName))
- .collect(Collectors.toList());
-
- OverlayManagerTransaction.Builder transaction = getTransactionBuilder();
- if (pendingCreation != null) {
- for (FabricatedOverlay overlay : pendingCreation) {
- transaction.registerFabricatedOverlay(overlay);
- }
- }
-
- for (Pair<String, String> packageToDisable : overlaysToDisable) {
- OverlayIdentifier overlayInfo = new OverlayIdentifier(packageToDisable.second);
- setEnabled(transaction, overlayInfo, packageToDisable.first, currentUser,
- managedProfiles, false);
- }
-
- for (String category : THEME_CATEGORIES) {
- if (categoryToPackage.containsKey(category)) {
- OverlayIdentifier overlayInfo = categoryToPackage.get(category);
- setEnabled(transaction, overlayInfo, category, currentUser, managedProfiles, true);
- }
- }
-
mExecutor.execute(() -> {
+
+ // Disable all overlays that have not been specified in the user setting.
+ final Set<String> overlayCategoriesToDisable = new HashSet<>(THEME_CATEGORIES);
+ final Set<String> targetPackagesToQuery = overlayCategoriesToDisable.stream()
+ .map(category -> mCategoryToTargetPackage.get(category))
+ .collect(Collectors.toSet());
+ final List<OverlayInfo> overlays = new ArrayList<>();
+ targetPackagesToQuery.forEach(targetPackage -> overlays.addAll(mOverlayManager
+ .getOverlayInfosForTarget(targetPackage, UserHandle.SYSTEM)));
+ final List<Pair<String, String>> overlaysToDisable = overlays.stream()
+ .filter(o ->
+ mTargetPackageToCategories.get(o.targetPackageName).contains(
+ o.category))
+ .filter(o -> overlayCategoriesToDisable.contains(o.category))
+ .filter(o -> !categoryToPackage.containsValue(
+ new OverlayIdentifier(o.packageName)))
+ .filter(o -> o.isEnabled())
+ .map(o -> new Pair<>(o.category, o.packageName))
+ .collect(Collectors.toList());
+
+ OverlayManagerTransaction.Builder transaction = getTransactionBuilder();
+ if (pendingCreation != null) {
+ for (FabricatedOverlay overlay : pendingCreation) {
+ transaction.registerFabricatedOverlay(overlay);
+ }
+ }
+
+ for (Pair<String, String> packageToDisable : overlaysToDisable) {
+ OverlayIdentifier overlayInfo = new OverlayIdentifier(packageToDisable.second);
+ setEnabled(transaction, overlayInfo, packageToDisable.first, currentUser,
+ managedProfiles, false);
+ }
+
+ for (String category : THEME_CATEGORIES) {
+ if (categoryToPackage.containsKey(category)) {
+ OverlayIdentifier overlayInfo = categoryToPackage.get(category);
+ setEnabled(transaction, overlayInfo, category, currentUser, managedProfiles,
+ true);
+ }
+ }
+
try {
mOverlayManager.commit(transaction.build());
} catch (SecurityException | IllegalStateException e) {
@@ -210,6 +215,7 @@
return new OverlayManagerTransaction.Builder();
}
+ @AnyThread
private void setEnabled(OverlayManagerTransaction.Builder transaction,
OverlayIdentifier identifier, String category, int currentUser,
Set<UserHandle> managedProfiles, boolean enabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index d317712..fc9a35d 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -19,9 +19,9 @@
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_SYSTEM_PALETTE;
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
+import android.app.WallpaperManager.OnColorsChangedListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -49,8 +49,10 @@
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.util.settings.SecureSettings;
import org.json.JSONException;
@@ -92,8 +94,9 @@
private final Executor mMainExecutor;
private final Handler mBgHandler;
private final WallpaperManager mWallpaperManager;
- private final KeyguardStateController mKeyguardStateController;
private final boolean mIsMonetEnabled;
+ private final UserTracker mUserTracker;
+ private DeviceProvisionedController mDeviceProvisionedController;
private WallpaperColors mSystemColors;
// If fabricated overlays were already created for the current theme.
private boolean mNeedsOverlayCreation;
@@ -107,17 +110,76 @@
private FabricatedOverlay mNeutralOverlay;
// If wallpaper color event will be accepted and change the UI colors.
private boolean mAcceptColorEvents = true;
+ // Defers changing themes until Setup Wizard is done.
+ private boolean mDeferredThemeEvaluation;
+
+ private final DeviceProvisionedListener mDeviceProvisionedListener =
+ new DeviceProvisionedListener() {
+ @Override
+ public void onUserSetupChanged() {
+ if (!mDeviceProvisionedController.isCurrentUserSetup()) {
+ return;
+ }
+ if (!mDeferredThemeEvaluation) {
+ return;
+ }
+ Log.i(TAG, "Applying deferred theme");
+ mDeferredThemeEvaluation = false;
+ reevaluateSystemTheme(true /* forceReload */);
+ }
+ };
+
+ private final OnColorsChangedListener mOnColorsChangedListener = (wallpaperColors, which) -> {
+ if (!mAcceptColorEvents) {
+ Log.i(TAG, "Wallpaper color event rejected: " + wallpaperColors);
+ return;
+ }
+ if (wallpaperColors != null) {
+ mAcceptColorEvents = false;
+ }
+
+ if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
+ mSystemColors = wallpaperColors;
+ if (DEBUG) {
+ Log.d(TAG, "got new lock colors: " + wallpaperColors + " where: " + which);
+ }
+ }
+
+ if (mDeviceProvisionedController != null
+ && !mDeviceProvisionedController.isCurrentUserSetup()) {
+ Log.i(TAG, "Wallpaper color event deferred until setup is finished: "
+ + wallpaperColors);
+ mDeferredThemeEvaluation = true;
+ return;
+ }
+ reevaluateSystemTheme(false /* forceReload */);
+ };
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())
+ || Intent.ACTION_MANAGED_PROFILE_ADDED.equals(intent.getAction())) {
+ if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added.");
+ reevaluateSystemTheme(true /* forceReload */);
+ } else if (Intent.ACTION_WALLPAPER_CHANGED.equals(intent.getAction())) {
+ mAcceptColorEvents = true;
+ Log.i(TAG, "Allowing color events again");
+ }
+ }
+ };
@Inject
public ThemeOverlayController(Context context, BroadcastDispatcher broadcastDispatcher,
@Background Handler bgHandler, @Main Executor mainExecutor,
@Background Executor bgExecutor, ThemeOverlayApplier themeOverlayApplier,
SecureSettings secureSettings, WallpaperManager wallpaperManager,
- UserManager userManager, KeyguardStateController keyguardStateController,
- DumpManager dumpManager, FeatureFlags featureFlags) {
+ UserManager userManager, DeviceProvisionedController deviceProvisionedController,
+ UserTracker userTracker, DumpManager dumpManager, FeatureFlags featureFlags) {
super(context);
mIsMonetEnabled = featureFlags.isMonetEnabled();
+ mDeviceProvisionedController = deviceProvisionedController;
mBroadcastDispatcher = broadcastDispatcher;
mUserManager = userManager;
mBgExecutor = bgExecutor;
@@ -126,7 +188,7 @@
mThemeManager = themeOverlayApplier;
mSecureSettings = secureSettings;
mWallpaperManager = wallpaperManager;
- mKeyguardStateController = keyguardStateController;
+ mUserTracker = userTracker;
dumpManager.registerDumpable(TAG, this);
}
@@ -137,19 +199,8 @@
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
filter.addAction(Intent.ACTION_WALLPAPER_CHANGED);
- mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())
- || Intent.ACTION_MANAGED_PROFILE_ADDED.equals(intent.getAction())) {
- if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added.");
- reevaluateSystemTheme(true /* forceReload */);
- } else if (Intent.ACTION_WALLPAPER_CHANGED.equals(intent.getAction())) {
- mAcceptColorEvents = true;
- Log.i(TAG, "Allowing color events again");
- }
- }
- }, filter, mMainExecutor, UserHandle.ALL);
+ mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, mMainExecutor,
+ UserHandle.ALL);
mSecureSettings.registerContentObserverForUser(
Settings.Secure.getUriFor(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES),
false,
@@ -158,12 +209,19 @@
public void onChange(boolean selfChange, Collection<Uri> collection, int flags,
int userId) {
if (DEBUG) Log.d(TAG, "Overlay changed for user: " + userId);
- if (ActivityManager.getCurrentUser() == userId) {
- reevaluateSystemTheme(true /* forceReload */);
+ if (mUserTracker.getUserId() != userId) {
+ return;
}
+ if (!mDeviceProvisionedController.isUserSetup(userId)) {
+ Log.i(TAG, "Theme application deferred when setting changed.");
+ mDeferredThemeEvaluation = true;
+ return;
+ }
+ reevaluateSystemTheme(true /* forceReload */);
}
},
UserHandle.USER_ALL);
+ mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
// Upon boot, make sure we have the most up to date colors
mBgExecutor.execute(() -> {
@@ -174,23 +232,8 @@
reevaluateSystemTheme(false /* forceReload */);
});
});
- mWallpaperManager.addOnColorsChangedListener((wallpaperColors, which) -> {
- if (!mAcceptColorEvents) {
- Log.i(TAG, "Wallpaper color event rejected: " + wallpaperColors);
- return;
- }
- if (wallpaperColors != null && mAcceptColorEvents) {
- mAcceptColorEvents = false;
- }
-
- if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
- mSystemColors = wallpaperColors;
- if (DEBUG) {
- Log.d(TAG, "got new lock colors: " + wallpaperColors + " where: " + which);
- }
- }
- reevaluateSystemTheme(false /* forceReload */);
- }, null, UserHandle.USER_ALL);
+ mWallpaperManager.addOnColorsChangedListener(mOnColorsChangedListener, null,
+ UserHandle.USER_ALL);
}
private void reevaluateSystemTheme(boolean forceReload) {
@@ -252,7 +295,7 @@
}
private void updateThemeOverlays() {
- final int currentUser = ActivityManager.getCurrentUser();
+ final int currentUser = mUserTracker.getUserId();
final String overlayPackageJson = mSecureSettings.getStringForUser(
Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
currentUser);
@@ -360,5 +403,6 @@
pw.println("mIsMonetEnabled=" + mIsMonetEnabled);
pw.println("mNeedsOverlayCreation=" + mNeedsOverlayCreation);
pw.println("mAcceptColorEvents=" + mAcceptColorEvents);
+ pw.println("mDeferredThemeEvaluation=" + mDeferredThemeEvaluation);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
index 3892f31..662e25c 100644
--- a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
@@ -233,7 +233,8 @@
return null;
}
final AppEntry appEntry = appState.getEntry(packageName, userId);
- if (!ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(appEntry)) {
+ if (appEntry.info == null
+ || !ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(appEntry)) {
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index e403cfa..45b0b59 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -416,6 +416,7 @@
static ShellInitImpl provideShellInitImpl(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
+ Optional<BubbleController> bubblesOptional,
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
@@ -427,6 +428,7 @@
return new ShellInitImpl(displayImeController,
dragAndDropController,
shellTaskOrganizer,
+ bubblesOptional,
legacySplitScreenOptional,
splitScreenOptional,
appPairsOptional,
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index d5183f8..af94876 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -37,6 +37,7 @@
import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
+import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
@@ -123,11 +124,12 @@
PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController,
WindowManagerShellWrapper windowManagerShellWrapper,
TaskStackListenerImpl taskStackListener,
+ Optional<OneHandedController> oneHandedController,
@ShellMainThread ShellExecutor mainExecutor) {
return Optional.ofNullable(PipController.create(context, displayController,
pipAppOpsListener, pipBoundsAlgorithm, pipBoundsState, pipMediaController,
phonePipMenuController, pipTaskOrganizer, pipTouchHandler, pipTransitionController,
- windowManagerShellWrapper, taskStackListener, mainExecutor));
+ windowManagerShellWrapper, taskStackListener, oneHandedController, mainExecutor));
}
@WMSingleton
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 160dae5..44c3b26 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -61,6 +61,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IRemoteCallback;
+import android.os.PowerManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.ServiceState;
@@ -164,6 +165,8 @@
@Mock
private AuthController mAuthController;
@Mock
+ private PowerManager mPowerManager;
+ @Mock
private TelephonyListenerManager mTelephonyListenerManager;
@Mock
private FeatureFlags mFeatureFlags;
@@ -518,6 +521,46 @@
}
@Test
+ public void testFingerprintCancelAodInterrupt_onAuthenticationFailed() {
+ // GIVEN on keyguard and listening for fingerprint authentication
+ mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
+ mTestableLooper.processAllMessages();
+
+ ArgumentCaptor<FingerprintManager.AuthenticationCallback> fingerprintCallbackCaptor =
+ ArgumentCaptor.forClass(FingerprintManager.AuthenticationCallback.class);
+ verify(mFingerprintManager).authenticate(any(), any(), fingerprintCallbackCaptor.capture(),
+ any(), anyInt(), anyInt());
+ FingerprintManager.AuthenticationCallback authCallback =
+ fingerprintCallbackCaptor.getValue();
+
+ // WHEN authentication fails
+ authCallback.onAuthenticationFailed();
+
+ // THEN aod interrupt is cancelled
+ verify(mAuthController).onCancelAodInterrupt();
+ }
+
+ @Test
+ public void testFingerprintCancelAodInterrupt_onAuthenticationError() {
+ // GIVEN on keyguard and listening for fingerprint authentication
+ mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
+ mTestableLooper.processAllMessages();
+
+ ArgumentCaptor<FingerprintManager.AuthenticationCallback> fingerprintCallbackCaptor =
+ ArgumentCaptor.forClass(FingerprintManager.AuthenticationCallback.class);
+ verify(mFingerprintManager).authenticate(any(), any(), fingerprintCallbackCaptor.capture(),
+ any(), anyInt(), anyInt());
+ FingerprintManager.AuthenticationCallback authCallback =
+ fingerprintCallbackCaptor.getValue();
+
+ // WHEN authentication errors
+ authCallback.onAuthenticationError(0, "");
+
+ // THEN aod interrupt is cancelled
+ verify(mAuthController).onCancelAodInterrupt();
+ }
+
+ @Test
public void skipsAuthentication_whenStatusBarShadeLocked() {
mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED);
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
@@ -886,7 +929,7 @@
mBroadcastDispatcher, mDumpManager,
mRingerModeTracker, mBackgroundExecutor,
mStatusBarStateController, mLockPatternUtils,
- mAuthController, mTelephonyListenerManager, mFeatureFlags);
+ mAuthController, mTelephonyListenerManager, mPowerManager, mFeatureFlags);
setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index 2526990..8252ff4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -53,6 +53,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -137,7 +138,8 @@
mFlagsCache,
mAudioManager,
mSensorPrivacyController,
- mDispatcher
+ mDispatcher,
+ new FakeSystemClock()
);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index fa190a5..3fe8cee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -509,20 +509,6 @@
verify(mUdfpsController).onAodInterrupt(eq(pos), eq(pos), eq(majorMinor), eq(majorMinor));
}
- @Test
- public void testOnBiometricAuthenticated_OnCancelAodInterrupt() {
- showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
- mAuthController.onBiometricAuthenticated();
- verify(mUdfpsController).onCancelAodInterrupt();
- }
-
- @Test
- public void testOnBiometricError_OnCancelAodInterrupt() {
- showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
- mAuthController.onBiometricError(0, 0, 0);
- verify(mUdfpsController).onCancelAodInterrupt();
- }
-
// Helpers
private void showDialog(int[] sensorIds, boolean credentialAllowed) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
index db06199..c912419 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.classifier;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
+
import static com.google.common.truth.Truth.assertThat;
import android.testing.AndroidTestingRunner;
@@ -96,13 +98,9 @@
}
@Test
- public void testPass_swipe() {
-
+ public void testPass_BrightnessSliderAlwaysPasses() {
mClassifier.onTouchEvent(appendDownEvent(1, 1));
- assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
-
- mClassifier.onTouchEvent(appendMoveEvent(1, mDataProvider.getYdpi() * 3, 3));
- mClassifier.onTouchEvent(appendUpEvent(1, mDataProvider.getYdpi() * 3, 300));
- assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 1).isFalse())
+ .isFalse();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java
index 52423bd..60786f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java
@@ -16,11 +16,12 @@
package com.android.systemui.classifier;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
import static com.android.systemui.classifier.Classifier.GENERIC;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
@@ -72,7 +73,7 @@
public void testPass_uncovered() {
touchDown();
touchUp(10);
- assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse(), is(false));
+ assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse()).isFalse();
}
@Test
@@ -81,7 +82,7 @@
mClassifier.onProximityEvent(createSensorEvent(true, 1));
mClassifier.onProximityEvent(createSensorEvent(false, 2));
touchUp(20);
- assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse(), is(false));
+ assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse()).isFalse();
}
@Test
@@ -90,7 +91,17 @@
mClassifier.onProximityEvent(createSensorEvent(true, 1));
mClassifier.onProximityEvent(createSensorEvent(false, 11));
touchUp(10);
- assertThat(mClassifier.classifyGesture(QUICK_SETTINGS, 0.5, 0).isFalse(), is(false));
+ assertThat(mClassifier.classifyGesture(QUICK_SETTINGS, 0.5, 0).isFalse()).isFalse();
+ }
+
+ @Test
+ public void testPass_brightnessSlider() {
+ touchDown();
+ mClassifier.onProximityEvent(createSensorEvent(true, 1));
+ mClassifier.onProximityEvent(createSensorEvent(false, 11));
+ touchUp(10);
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse())
+ .isFalse();
}
@Test
@@ -99,7 +110,7 @@
mClassifier.onProximityEvent(createSensorEvent(true, 1));
mClassifier.onProximityEvent(createSensorEvent(false, 11));
touchUp(10);
- assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse(), is(true));
+ assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse()).isTrue();
}
@Test
@@ -110,7 +121,7 @@
mClassifier.onProximityEvent(createSensorEvent(true, 96));
mClassifier.onProximityEvent(createSensorEvent(false, 100));
touchUp(100);
- assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse(), is(true));
+ assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse()).isTrue();
}
@Test
@@ -120,7 +131,7 @@
mClassifier.onProximityEvent(createSensorEvent(false, 11));
touchUp(10);
when(mDistanceClassifier.isLongSwipe()).thenReturn(mPassedResult);
- assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse(), is(false));
+ assertThat(mClassifier.classifyGesture(GENERIC, 0.5, 0).isFalse()).isFalse();
}
private void touchDown() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java
index 068a1e5..32537b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.classifier;
import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
import static com.android.systemui.classifier.Classifier.LEFT_AFFORDANCE;
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS;
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
@@ -277,4 +278,46 @@
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.classifyGesture(RIGHT_AFFORDANCE, 0.5, 0).isFalse()).isTrue();
}
+
+ @Test
+ public void testPass_BrightnessSlider() {
+ when(mDataProvider.isVertical()).thenReturn(false);
+
+ when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect.
+ when(mDataProvider.isRight()).thenReturn(false);
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isFalse();
+
+ when(mDataProvider.isUp()).thenReturn(true);
+ when(mDataProvider.isRight()).thenReturn(false);
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isFalse();
+
+ when(mDataProvider.isUp()).thenReturn(false);
+ when(mDataProvider.isRight()).thenReturn(true);
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isFalse();
+
+ when(mDataProvider.isUp()).thenReturn(true);
+ when(mDataProvider.isRight()).thenReturn(true);
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isFalse();
+ }
+
+ @Test
+ public void testFalse_BrightnessSlider() {
+ when(mDataProvider.isVertical()).thenReturn(true);
+
+ when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect.
+ when(mDataProvider.isRight()).thenReturn(false);
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isTrue();
+
+ when(mDataProvider.isUp()).thenReturn(true);
+ when(mDataProvider.isRight()).thenReturn(false);
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isTrue();
+
+ when(mDataProvider.isUp()).thenReturn(false);
+ when(mDataProvider.isRight()).thenReturn(true);
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isTrue();
+
+ when(mDataProvider.isUp()).thenReturn(true);
+ when(mDataProvider.isRight()).thenReturn(true);
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 0).isFalse()).isTrue();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
index e004c30..c343c20 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.classifier;
+import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
+
import static com.google.common.truth.Truth.assertThat;
import android.testing.AndroidTestingRunner;
@@ -82,6 +84,13 @@
assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
}
+ @Test
+ public void testPass_brightnessSliderAlwaysPasses() {
+ appendMoveEvent(0, 0);
+ appendMoveEvent(0, 100);
+ appendMoveEvent(0, 1);
+ assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 1).isFalse()).isFalse();
+ }
@Test
public void testFail_minimumTouchesVertical() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
index f991e71..2a8611f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
@@ -69,7 +69,7 @@
private lateinit var executor: FakeExecutor
private lateinit var deviceConfigProxy: DeviceConfigProxy
- fun PrivacyItemController(): PrivacyItemController {
+ fun createPrivacyItemController(): PrivacyItemController {
return PrivacyItemController(
appOpsController,
executor,
@@ -77,6 +77,7 @@
deviceConfigProxy,
userTracker,
logger,
+ FakeSystemClock(),
dumpManager)
}
@@ -86,7 +87,7 @@
executor = FakeExecutor(FakeSystemClock())
deviceConfigProxy = DeviceConfigProxyFake()
- privacyItemController = PrivacyItemController()
+ privacyItemController = createPrivacyItemController()
privacyItemController.addCallback(callback)
executor.runAllReady()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
index b87c7a6..bba1c6a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -99,7 +99,10 @@
private lateinit var fakeClock: FakeSystemClock
private lateinit var deviceConfigProxy: DeviceConfigProxy
- fun PrivacyItemController(): PrivacyItemController {
+ private val elapsedTime: Long
+ get() = fakeClock.elapsedRealtime()
+
+ fun createPrivacyItemController(): PrivacyItemController {
return PrivacyItemController(
appOpsController,
executor,
@@ -107,6 +110,7 @@
deviceConfigProxy,
userTracker,
logger,
+ fakeClock,
dumpManager)
}
@@ -123,7 +127,7 @@
`when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(CURRENT_USER_ID, "", 0)))
- privacyItemController = PrivacyItemController()
+ privacyItemController = createPrivacyItemController()
}
@Test
@@ -151,7 +155,7 @@
@Test
fun testDistinctItems() {
doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0),
- AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 1)))
+ AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0)))
.`when`(appOpsController).getActiveAppOpsForUser(anyInt())
privacyItemController.addCallback(callback)
@@ -161,6 +165,18 @@
}
@Test
+ fun testSimilarItemsDifferentTimeStamp() {
+ doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0),
+ AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 1)))
+ .`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+
+ privacyItemController.addCallback(callback)
+ executor.runAllReady()
+ verify(callback).onPrivacyItemsChanged(capture(argCaptor))
+ assertEquals(2, argCaptor.value.size)
+ }
+
+ @Test
fun testRegisterCallback() {
privacyItemController.addCallback(callback)
executor.runAllReady()
@@ -251,7 +267,7 @@
@Test
fun testListShouldBeCopy() {
val list = listOf(PrivacyItem(PrivacyType.TYPE_CAMERA,
- PrivacyApplication("", TEST_UID)))
+ PrivacyApplication("", TEST_UID), 0))
privacyItemController.privacyList = list
val privacyList = privacyItemController.privacyList
assertEquals(list, privacyList)
@@ -334,14 +350,15 @@
val expected = PrivacyItem(
PrivacyType.TYPE_LOCATION,
- PrivacyApplication(TEST_PACKAGE_NAME, TEST_UID)
+ PrivacyApplication(TEST_PACKAGE_NAME, TEST_UID),
+ 0
)
- val captor = argumentCaptor<String>()
- verify(logger, atLeastOnce()).logUpdatedPrivacyItemsList(capture(captor))
+ val captor = argumentCaptor<List<PrivacyItem>>()
+ verify(logger, atLeastOnce()).logRetrievedPrivacyItemsList(capture(captor))
// Let's look at the last log
val values = captor.allValues
- assertTrue(values[values.size - 1].contains(expected.toLog()))
+ assertTrue(values[values.size - 1].contains(expected))
}
@Test
@@ -424,7 +441,7 @@
@Test
fun testPassageOfTimeDoesNotRemoveIndicators() {
doReturn(listOf(
- AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0)
+ AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime)
)).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
privacyItemController.addCallback(callback)
@@ -437,86 +454,75 @@
}
@Test
- fun testHoldingAfterEmptyBeforeTimeExpires() {
+ fun testNotHeldAfterTimeIsOff() {
+ // Start with some element at time 0
doReturn(listOf(
- AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0)
+ AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime)
)).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
-
privacyItemController.addCallback(callback)
executor.runAllReady()
- verify(appOpsController).addCallback(any(), capture(argCaptorCallback))
+ // Then remove it at time HOLD + 1
+ doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+ fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS + 1)
- `when`(appOpsController.getActiveAppOpsForUser(anyInt())).thenReturn(emptyList())
+ verify(appOpsController).addCallback(any(), capture(argCaptorCallback))
argCaptorCallback.value.onActiveStateChanged(
AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, false)
executor.runAllReady()
- fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS / 5)
- executor.runAllReady()
-
- verify(callback, never()).onPrivacyItemsChanged(emptyList())
- assertTrue(privacyItemController.privacyList.isNotEmpty())
- }
-
- @Test
- fun testAfterHoldingIndicatorsAreEmpty() {
- doReturn(listOf(
- AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0)
- )).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
-
- privacyItemController.addCallback(callback)
- executor.runAllReady()
-
- verify(appOpsController).addCallback(any(), capture(argCaptorCallback))
-
- `when`(appOpsController.getActiveAppOpsForUser(anyInt())).thenReturn(emptyList())
- argCaptorCallback.value.onActiveStateChanged(
- AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, false)
- executor.runAllReady()
-
- executor.advanceClockToLast()
- executor.runAllReady()
-
+ // See it's not there
verify(callback).onPrivacyItemsChanged(emptyList())
assertTrue(privacyItemController.privacyList.isEmpty())
}
@Test
- fun testHoldingStopsIfNewIndicatorsAppear() {
+ fun testElementNotRemovedBeforeHoldTime() {
+ // Start with some element at time 0
doReturn(listOf(
- AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0)
+ AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime)
)).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
-
privacyItemController.addCallback(callback)
executor.runAllReady()
- verify(appOpsController).addCallback(any(), capture(argCaptorCallback))
+ // Then remove it at time HOLD - 1
+ doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+ fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS - 1)
- `when`(appOpsController.getActiveAppOpsForUser(anyInt())).thenReturn(emptyList())
+ verify(appOpsController).addCallback(any(), capture(argCaptorCallback))
argCaptorCallback.value.onActiveStateChanged(
AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, false)
executor.runAllReady()
- fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS / 2)
- executor.runAllReady()
-
- doReturn(listOf(
- AppOpItem(AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, 0)
- )).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
- argCaptorCallback.value.onActiveStateChanged(
- AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true)
- executor.runAllReady()
-
- executor.advanceClockToLast()
- executor.runAllReady()
-
+ // See it's still there
verify(callback, never()).onPrivacyItemsChanged(emptyList())
- verify(callback, atLeastOnce()).onPrivacyItemsChanged(capture(argCaptor))
+ assertTrue(privacyItemController.privacyList.isNotEmpty())
+ }
- val lastList = argCaptor.allValues.last()
- assertEquals(1, lastList.size)
- assertEquals(PrivacyType.TYPE_MICROPHONE, lastList.single().privacyType)
+ @Test
+ fun testElementAutoRemovedAfterHoldTime() {
+ // Start with some element at time 0
+ doReturn(listOf(
+ AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime)
+ )).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+ privacyItemController.addCallback(callback)
+ executor.runAllReady()
+
+ // Then remove it at time HOLD - 1
+ doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+ fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS - 1)
+
+ verify(appOpsController).addCallback(any(), capture(argCaptorCallback))
+ argCaptorCallback.value.onActiveStateChanged(
+ AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, false)
+ executor.runAllReady()
+
+ fakeClock.advanceTime(2L)
+ executor.runAllReady()
+
+ // See it was auto-removed
+ verify(callback).onPrivacyItemsChanged(emptyList())
+ assertTrue(privacyItemController.privacyList.isEmpty())
}
private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
index 3595095..3c1b36e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -21,9 +21,9 @@
import android.view.View
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
-import com.android.systemui.colorextraction.SysuiColorExtractor
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.colorextraction.SysuiColorExtractor
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.privacy.OngoingPrivacyChip
@@ -32,16 +32,12 @@
import com.android.systemui.privacy.logging.PrivacyLogger
import com.android.systemui.qs.carrier.QSCarrierGroup
import com.android.systemui.qs.carrier.QSCarrierGroupController
-import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.policy.Clock
-import com.android.systemui.statusbar.policy.NextAlarmController
-import com.android.systemui.util.RingerModeTracker
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
-import com.android.systemui.utils.leaks.FakeZenModeController
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
@@ -61,26 +57,16 @@
@Mock
private lateinit var view: QuickStatusBarHeader
@Mock
- private lateinit var zenModeController: FakeZenModeController
- @Mock
- private lateinit var nextAlarmController: NextAlarmController
- @Mock
private lateinit var privacyItemController: PrivacyItemController
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private lateinit var ringerModeTracker: RingerModeTracker
@Mock
private lateinit var activityStarter: ActivityStarter
@Mock
private lateinit var uiEventLogger: UiEventLogger
@Mock
- private lateinit var qsTileHost: QSTileHost
- @Mock
private lateinit var statusBarIconController: StatusBarIconController
@Mock
private lateinit var demoModeController: DemoModeController
@Mock
- private lateinit var userTracker: UserTracker
- @Mock
private lateinit var quickQSPanelController: QuickQSPanelController
@Mock(answer = Answers.RETURNS_SELF)
private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
@@ -105,6 +91,8 @@
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private lateinit var context: Context
+ private val qsExpansionPathInterpolator = QSExpansionPathInterpolator()
+
private lateinit var controller: QuickStatusBarHeaderController
@Before
@@ -119,21 +107,17 @@
controller = QuickStatusBarHeaderController(
view,
- zenModeController,
- nextAlarmController,
privacyItemController,
- ringerModeTracker,
activityStarter,
uiEventLogger,
- qsTileHost,
statusBarIconController,
demoModeController,
- userTracker,
quickQSPanelController,
qsCarrierGroupControllerBuilder,
privacyLogger,
colorExtractor,
- privacyDialogController
+ privacyDialogController,
+ qsExpansionPathInterpolator
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java
index 022dc84..104b625 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java
@@ -21,10 +21,13 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.util.FeatureFlagUtils;
import android.view.LayoutInflater;
import androidx.test.filters.SmallTest;
+import com.android.settingslib.graph.SignalDrawable;
+import com.android.settingslib.mobile.TelephonyIcons;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -39,6 +42,7 @@
private QSCarrier mQSCarrier;
private TestableLooper mTestableLooper;
+ private int mSignalIconId;
@Before
public void setUp() throws Exception {
@@ -46,18 +50,26 @@
LayoutInflater inflater = LayoutInflater.from(mContext);
mTestableLooper.runWithLooper(() ->
mQSCarrier = (QSCarrier) inflater.inflate(R.layout.qs_carrier, null));
+
+ if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL)) {
+ // In this case, the id is an actual drawable id
+ mSignalIconId = TelephonyIcons.MOBILE_CALL_STRENGTH_ICONS[0];
+ } else {
+ // In this case, the id is a level
+ mSignalIconId = SignalDrawable.getEmptyState(5);
+ }
}
@Test
public void testUpdateState_first() {
- CellSignalState c = new CellSignalState(true, 0, "", "", false);
+ CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false);
assertTrue(mQSCarrier.updateState(c));
}
@Test
public void testUpdateState_same() {
- CellSignalState c = new CellSignalState(true, 0, "", "", false);
+ CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false);
assertTrue(mQSCarrier.updateState(c));
assertFalse(mQSCarrier.updateState(c));
@@ -65,7 +77,7 @@
@Test
public void testUpdateState_changed() {
- CellSignalState c = new CellSignalState(true, 0, "", "", false);
+ CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false);
assertTrue(mQSCarrier.updateState(c));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
index 0cc2072..95e9d1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
@@ -25,6 +25,7 @@
import androidx.test.filters.SmallTest
import com.android.settingslib.RestrictedLockUtils
import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.statusbar.policy.BrightnessMirrorController
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
@@ -75,6 +76,7 @@
private lateinit var checkedChangeCaptor: ArgumentCaptor<CompoundButton.OnCheckedChangeListener>
@Mock
private lateinit var compoundButton: CompoundButton
+ private var mFalsingManager: FalsingManagerFake = FalsingManagerFake()
private lateinit var mController: BrightnessSlider
@@ -85,7 +87,7 @@
whenever(mirrorController.toggleSlider).thenReturn(mirror)
whenever(motionEvent.copy()).thenReturn(motionEvent)
- mController = BrightnessSlider(rootView, brightnessSliderView, true)
+ mController = BrightnessSlider(rootView, brightnessSliderView, true, mFalsingManager)
mController.init()
mController.setOnChangedListener(listener)
}
@@ -160,7 +162,8 @@
@Test
fun testSettingMirrorWhenNotUseMirrorIsNoOp() {
- val otherController = BrightnessSlider(rootView, brightnessSliderView, false)
+ val otherController = BrightnessSlider(
+ rootView, brightnessSliderView, false, mFalsingManager)
otherController.init()
otherController.setMirrorControllerAndMirror(mirrorController)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index 4e7e0a3..ddf0537 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -26,6 +26,8 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -49,8 +51,10 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
@@ -86,24 +90,29 @@
@Mock
private UserManager mUserManager;
@Mock
- private KeyguardStateController mKeyguardStateController;
+ private UserTracker mUserTracker;
@Mock
private DumpManager mDumpManager;
@Mock
+ private DeviceProvisionedController mDeviceProvisionedController;
+ @Mock
private FeatureFlags mFeatureFlags;
@Captor
private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiver;
@Captor
private ArgumentCaptor<WallpaperManager.OnColorsChangedListener> mColorsListener;
+ @Captor
+ private ArgumentCaptor<DeviceProvisionedListener> mDeviceProvisionedListener;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
when(mFeatureFlags.isMonetEnabled()).thenReturn(true);
+ when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
mThemeOverlayController = new ThemeOverlayController(null /* context */,
mBroadcastDispatcher, mBgHandler, mMainExecutor, mBgExecutor, mThemeOverlayApplier,
- mSecureSettings, mWallpaperManager, mUserManager, mKeyguardStateController,
- mDumpManager, mFeatureFlags) {
+ mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController,
+ mUserTracker, mDumpManager, mFeatureFlags) {
@Nullable
@Override
protected FabricatedOverlay getOverlay(int color, int type) {
@@ -120,6 +129,7 @@
verify(mBroadcastDispatcher).registerReceiver(mBroadcastReceiver.capture(), any(),
eq(mMainExecutor), any());
verify(mDumpManager).registerDumpable(any(), any());
+ verify(mDeviceProvisionedController).addCallback(mDeviceProvisionedListener.capture());
}
@Test
@@ -191,6 +201,22 @@
}
@Test
+ public void onWallpaperColorsChanged_defersUntilSetupIsCompleted() {
+ reset(mDeviceProvisionedController);
+ WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
+ Color.valueOf(Color.BLUE), null);
+ mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+
+ verify(mThemeOverlayApplier, never())
+ .applyCurrentUserOverlays(any(), any(), anyInt(), any());
+
+ when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
+ mDeviceProvisionedListener.getValue().onUserSetupChanged();
+
+ verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any());
+ }
+
+ @Test
public void onWallpaperColorsChanged_parsesColorsFromWallpaperPicker() {
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
index cdf47b8..a1adb2c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
@@ -55,5 +55,6 @@
statusBarService, windowManager, windowManagerShellWrapper, launcherApps,
bubbleLogger, shellTaskOrganizer, positioner, shellMainExecutor, shellMainHandler);
setInflateSynchronously(true);
+ initialize();
}
}
diff --git a/services/Android.bp b/services/Android.bp
index 311e8735..c160842 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -9,7 +9,10 @@
filegroup {
name: "services-main-sources",
- srcs: ["java/**/*.java"],
+ srcs: [
+ "java/**/*.java",
+ "java/**/package.html",
+ ],
path: "java",
visibility: ["//visibility:private"],
}
@@ -19,6 +22,7 @@
srcs: [
":services.core-sources",
":services.core-sources-am-wm",
+ "core/java/com/android/server/am/package.html",
":services.accessibility-sources",
":services.appprediction-sources",
":services.appwidget-sources",
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index 5b74cbd..1f66bfd 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -79,7 +79,7 @@
private final ScreenStateObserver mScreenStateObserver;
- private final MagnificationRequestObserver mMagnificationRequestObserver;
+ private final MagnificationInfoChangedCallback mMagnificationInfoChangedCallback;
private int mUserId;
@@ -284,6 +284,14 @@
mControllerCtx.getHandler().sendMessage(m);
}
+ @Override
+ public void onImeWindowVisibilityChanged(boolean shown) {
+ final Message m = PooledLambda.obtainMessage(
+ FullScreenMagnificationController::notifyImeWindowVisibilityChanged,
+ FullScreenMagnificationController.this, shown);
+ mControllerCtx.getHandler().sendMessage(m);
+ }
+
/**
* Update our copy of the current magnification region
*
@@ -329,7 +337,7 @@
final boolean lastMagnificationActivated = mMagnificationActivated;
mMagnificationActivated = spec.scale > 1.0f;
if (mMagnificationActivated != lastMagnificationActivated) {
- mMagnificationRequestObserver.onFullScreenMagnificationActivationState(
+ mMagnificationInfoChangedCallback.onFullScreenMagnificationActivationState(
mMagnificationActivated);
}
}
@@ -498,7 +506,7 @@
sendSpecToAnimation(mCurrentMagnificationSpec, animationCallback);
if (isMagnifying() && (id != INVALID_ID)) {
mIdOfLastServiceToMagnify = id;
- mMagnificationRequestObserver.onRequestMagnificationSpec(mDisplayId,
+ mMagnificationInfoChangedCallback.onRequestMagnificationSpec(mDisplayId,
mIdOfLastServiceToMagnify);
}
return changed;
@@ -631,12 +639,12 @@
*/
public FullScreenMagnificationController(@NonNull Context context,
@NonNull AccessibilityManagerService ams, @NonNull Object lock,
- @NonNull MagnificationRequestObserver magnificationRequestObserver) {
+ @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback) {
this(new ControllerContext(context, ams,
LocalServices.getService(WindowManagerInternal.class),
new Handler(context.getMainLooper()),
context.getResources().getInteger(R.integer.config_longAnimTime)), lock,
- magnificationRequestObserver);
+ magnificationInfoChangedCallback);
}
/**
@@ -645,12 +653,12 @@
@VisibleForTesting
public FullScreenMagnificationController(@NonNull ControllerContext ctx,
@NonNull Object lock,
- @NonNull MagnificationRequestObserver magnificationRequestObserver) {
+ @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback) {
mControllerCtx = ctx;
mLock = lock;
mMainThreadId = mControllerCtx.getContext().getMainLooper().getThread().getId();
mScreenStateObserver = new ScreenStateObserver(mControllerCtx.getContext(), this);
- mMagnificationRequestObserver = magnificationRequestObserver;
+ mMagnificationInfoChangedCallback = magnificationInfoChangedCallback;
}
/**
@@ -1168,6 +1176,16 @@
}
/**
+ * Notifies that the IME window visibility changed.
+ *
+ * @param shown {@code true} means the IME window shows on the screen. Otherwise it's
+ * hidden.
+ */
+ void notifyImeWindowVisibilityChanged(boolean shown) {
+ mMagnificationInfoChangedCallback.onImeWindowVisibilityChanged(shown);
+ }
+
+ /**
* Returns {@code true} if the magnifiable regions of the display is forced to be shown.
*
* @param displayId The logical display id.
@@ -1528,7 +1546,7 @@
return animate ? STUB_ANIMATION_CALLBACK : null;
}
- interface MagnificationRequestObserver {
+ interface MagnificationInfoChangedCallback {
/**
* Called when the {@link MagnificationSpec} is changed with non-default
@@ -1545,7 +1563,13 @@
*
* @param activated {@code true} if the magnification is activated, otherwise {@code false}.
*/
- @GuardedBy("mLock")
void onFullScreenMagnificationActivationState(boolean activated);
+
+ /**
+ * Called when the IME window visibility changed.
+ * @param shown {@code true} means the IME window shows on the screen. Otherwise it's
+ * hidden.
+ */
+ void onImeWindowVisibilityChanged(boolean shown);
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
index 2073c70..878ebc5 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -18,6 +18,7 @@
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
import android.annotation.NonNull;
@@ -33,6 +34,7 @@
import android.view.accessibility.MagnificationAnimationCallback;
import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.accessibility.AccessibilityManagerService;
@@ -58,7 +60,7 @@
*/
public class MagnificationController implements WindowMagnificationManager.Callback,
MagnificationGestureHandler.Callback,
- FullScreenMagnificationController.MagnificationRequestObserver {
+ FullScreenMagnificationController.MagnificationInfoChangedCallback {
private static final boolean DEBUG = false;
private static final String TAG = "MagnificationController";
@@ -73,6 +75,10 @@
private WindowMagnificationManager mWindowMagnificationMgr;
private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+ @GuardedBy("mLock")
+ private int mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
+ @GuardedBy("mLock")
+ private boolean mImeWindowVisible = false;
private long mWindowModeEnabledTime = 0;
private long mFullScreenModeEnabledTime = 0;
@@ -216,9 +222,18 @@
public void onWindowMagnificationActivationState(boolean activated) {
if (activated) {
mWindowModeEnabledTime = SystemClock.uptimeMillis();
+
+ synchronized (mLock) {
+ mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
+ }
+ logMagnificationModeWithImeOnIfNeeded();
} else {
logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
SystemClock.uptimeMillis() - mWindowModeEnabledTime);
+
+ synchronized (mLock) {
+ mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
+ }
}
}
@@ -226,12 +241,29 @@
public void onFullScreenMagnificationActivationState(boolean activated) {
if (activated) {
mFullScreenModeEnabledTime = SystemClock.uptimeMillis();
+
+ synchronized (mLock) {
+ mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+ }
+ logMagnificationModeWithImeOnIfNeeded();
} else {
logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
SystemClock.uptimeMillis() - mFullScreenModeEnabledTime);
+
+ synchronized (mLock) {
+ mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
+ }
}
}
+ @Override
+ public void onImeWindowVisibilityChanged(boolean shown) {
+ synchronized (mLock) {
+ mImeWindowVisible = shown;
+ }
+ logMagnificationModeWithImeOnIfNeeded();
+ }
+
/**
* Wrapper method of logging the magnification activated mode and its duration of the usage
* when the magnification is disabled.
@@ -245,6 +277,17 @@
}
/**
+ * Wrapper method of logging the activated mode of the magnification when the IME window
+ * is shown on the screen.
+ *
+ * @param mode The activated magnification mode.
+ */
+ @VisibleForTesting
+ public void logMagnificationModeWithIme(int mode) {
+ AccessibilityStatsLogUtils.logMagnificationModeWithImeOn(mode);
+ }
+
+ /**
* Updates the active user ID of {@link FullScreenMagnificationController} and {@link
* WindowMagnificationManager}.
*
@@ -295,6 +338,18 @@
}
}
+ private void logMagnificationModeWithImeOnIfNeeded() {
+ final int mode;
+
+ synchronized (mLock) {
+ if (!mImeWindowVisible || mActivatedMode == ACCESSIBILITY_MAGNIFICATION_MODE_NONE) {
+ return;
+ }
+ mode = mActivatedMode;
+ }
+ logMagnificationModeWithIme(mode);
+ }
+
/**
* Getter of {@link FullScreenMagnificationController}.
*
diff --git a/services/api/current.txt b/services/api/current.txt
index a3e6715..a0b1e33 100644
--- a/services/api/current.txt
+++ b/services/api/current.txt
@@ -105,6 +105,14 @@
}
+package com.android.server.stats {
+
+ public final class StatsHelper {
+ method public static void sendStatsdReadyBroadcast(@NonNull android.content.Context);
+ }
+
+}
+
package com.android.server.wifi {
public class SupplicantManager {
diff --git a/services/api/non-updatable-current.txt b/services/api/non-updatable-current.txt
index f01c182..475dcf5 100644
--- a/services/api/non-updatable-current.txt
+++ b/services/api/non-updatable-current.txt
@@ -52,6 +52,14 @@
}
+package com.android.server.stats {
+
+ public final class StatsHelper {
+ method public static void sendStatsdReadyBroadcast(@NonNull android.content.Context);
+ }
+
+}
+
package com.android.server.wifi {
public class SupplicantManager {
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 641b38d..1e3f12a 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -158,7 +158,7 @@
"android.hardware.power.stats-V1-java",
"android.hidl.manager-V1.2-java",
"capture_state_listener-aidl-java",
- "dnsresolver_aidl_interface-V7-java",
+ "dnsresolver_aidl_interface-V8-java",
"icu4j_calendar_astronomer",
"netd-client",
"overlayable_policy_aidl-java",
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index bbe59c9..f3e6428 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -320,6 +320,9 @@
// The maximum number of network request allowed per uid before an exception is thrown.
private static final int MAX_NETWORK_REQUESTS_PER_UID = 100;
+ // The maximum number of network request allowed for system UIDs before an exception is thrown.
+ private static final int MAX_NETWORK_REQUESTS_PER_SYSTEM_UID = 250;
+
@VisibleForTesting
protected int mLingerDelayMs; // Can't be final, or test subclass constructors can't change it.
@VisibleForTesting
@@ -335,6 +338,7 @@
protected final PermissionMonitor mPermissionMonitor;
private final PerUidCounter mNetworkRequestCounter;
+ private final PerUidCounter mSystemNetworkRequestCounter;
private volatile boolean mLockdownEnabled;
@@ -1215,6 +1219,7 @@
mContext = Objects.requireNonNull(context, "missing Context");
mResources = deps.getResources(mContext);
mNetworkRequestCounter = new PerUidCounter(MAX_NETWORK_REQUESTS_PER_UID);
+ mSystemNetworkRequestCounter = new PerUidCounter(MAX_NETWORK_REQUESTS_PER_SYSTEM_UID);
mMetricsLog = logger;
mNetworkRanker = new NetworkRanker();
@@ -1570,16 +1575,16 @@
mNetworkInfoBlockingLogs.log(action + " " + uid);
}
- private void maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net,
- boolean blocked) {
+ private void maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net, int blocked) {
if (nri == null || net == null || !LOGD_BLOCKED_NETWORKINFO) {
return;
}
- final String action = blocked ? "BLOCKED" : "UNBLOCKED";
+ final String action = (blocked != 0) ? "BLOCKED" : "UNBLOCKED";
final int requestId = nri.getActiveRequest() != null
? nri.getActiveRequest().requestId : nri.mRequests.get(0).requestId;
mNetworkInfoBlockingLogs.log(String.format(
- "%s %d(%d) on netId %d", action, nri.mAsUid, requestId, net.getNetId()));
+ "%s %d(%d) on netId %d: %s", action, nri.mAsUid, requestId, net.getNetId(),
+ blockedReasonsToString(blocked)));
}
/**
@@ -3137,6 +3142,13 @@
}
break;
}
+ case NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED: {
+ if (msg.arg1 >= 0 && msg.arg1 <= NetworkAgent.MAX_TEARDOWN_DELAY_MS) {
+ nai.teardownDelayMs = msg.arg1;
+ } else {
+ logwtf(nai.toShortString() + " set invalid teardown delay " + msg.arg1);
+ }
+ }
}
}
@@ -3708,6 +3720,23 @@
mLegacyTypeTracker.remove(nai, wasDefault);
rematchAllNetworksAndRequests();
mLingerMonitor.noteDisconnect(nai);
+
+ // Immediate teardown.
+ if (nai.teardownDelayMs == 0) {
+ destroyNetwork(nai);
+ return;
+ }
+
+ // Delayed teardown.
+ try {
+ mNetd.networkSetPermissionForNetwork(nai.network.netId, INetd.PERMISSION_SYSTEM);
+ } catch (RemoteException e) {
+ Log.d(TAG, "Error marking network restricted during teardown: " + e);
+ }
+ mHandler.postDelayed(() -> destroyNetwork(nai), nai.teardownDelayMs);
+ }
+
+ private void destroyNetwork(NetworkAgentInfo nai) {
if (nai.created) {
// Tell netd to clean up the configuration for this network
// (routing rules, DNS, etc).
@@ -3720,7 +3749,7 @@
mDnsManager.removeNetwork(nai.network);
}
mNetIdManager.releaseNetId(nai.network.getNetId());
- nai.onNetworkDisconnected();
+ nai.onNetworkDestroyed();
}
private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
@@ -4023,7 +4052,7 @@
}
}
}
- mNetworkRequestCounter.decrementCount(nri.mUid);
+ decrementRequestCount(nri);
mNetworkRequestInfoLogs.log("RELEASE " + nri);
if (null != nri.getActiveRequest()) {
@@ -4128,6 +4157,20 @@
}
}
+ private PerUidCounter getRequestCounter(NetworkRequestInfo nri) {
+ return checkAnyPermissionOf(
+ nri.mPid, nri.mUid, NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+ ? mSystemNetworkRequestCounter : mNetworkRequestCounter;
+ }
+
+ private void incrementRequestCountOrThrow(NetworkRequestInfo nri) {
+ getRequestCounter(nri).incrementCountOrThrow(nri.mUid);
+ }
+
+ private void decrementRequestCount(NetworkRequestInfo nri) {
+ getRequestCounter(nri).decrementCount(nri.mUid);
+ }
+
@Override
public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
enforceNetworkStackSettingsOrSetup();
@@ -5463,7 +5506,7 @@
mPid = getCallingPid();
mUid = mDeps.getCallingUid();
mAsUid = asUid;
- mNetworkRequestCounter.incrementCountOrThrow(mUid);
+ incrementRequestCountOrThrow(this);
/**
* Location sensitive data not included in pending intent. Only included in
* {@link NetworkCallback}.
@@ -5495,7 +5538,7 @@
mUid = mDeps.getCallingUid();
mAsUid = asUid;
mPendingIntent = null;
- mNetworkRequestCounter.incrementCountOrThrow(mUid);
+ incrementRequestCountOrThrow(this);
mCallbackFlags = callbackFlags;
mCallingAttributionTag = callingAttributionTag;
@@ -5538,7 +5581,7 @@
mUid = nri.mUid;
mAsUid = nri.mAsUid;
mPendingIntent = nri.mPendingIntent;
- mNetworkRequestCounter.incrementCountOrThrow(mUid);
+ incrementRequestCountOrThrow(this);
mCallbackFlags = nri.mCallbackFlags;
mCallingAttributionTag = nri.mCallingAttributionTag;
}
@@ -6283,8 +6326,8 @@
// Request used to optionally keep vehicle internal network always active
private final NetworkRequest mDefaultVehicleRequest;
- // TODO replace with INetd.DUMMY_NET_ID when available.
- private static final int NO_SERVICE_NET_ID = 51;
+ // TODO replace with INetd.UNREACHABLE_NET_ID when available.
+ private static final int NO_SERVICE_NET_ID = 52;
// Sentinel NAI used to direct apps with default networks that should have no connectivity to a
// network with no service. This NAI should never be matched against, nor should any public API
// ever return the associated network. For this reason, this NAI is not in the list of available
@@ -7354,7 +7397,7 @@
break;
}
case ConnectivityManager.CALLBACK_BLK_CHANGED: {
- maybeLogBlockedStatusChanged(nri, networkAgent.network, arg1 != 0);
+ maybeLogBlockedStatusChanged(nri, networkAgent.network, arg1);
msg.arg1 = arg1;
break;
}
@@ -8825,7 +8868,7 @@
// Decrement the reference count for this NetworkRequestInfo. The reference count is
// incremented when the NetworkRequestInfo is created as part of
// enforceRequestCountLimit().
- mNetworkRequestCounter.decrementCount(nri.mUid);
+ decrementRequestCount(nri);
return;
}
@@ -8891,7 +8934,7 @@
// Decrement the reference count for this NetworkRequestInfo. The reference count is
// incremented when the NetworkRequestInfo is created as part of
// enforceRequestCountLimit().
- mNetworkRequestCounter.decrementCount(nri.mUid);
+ decrementRequestCount(nri);
iCb.unlinkToDeath(cbInfo, 0);
}
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index ebd32e8..08bff81 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -265,18 +265,9 @@
* Handler for on start pinning message
*/
private void handlePinOnStart() {
- final String bootImage = SystemProperties.get("dalvik.vm.boot-image", "");
- String[] filesToPin = null;
- if (bootImage.endsWith("boot-image.prof")) {
- // Use the files listed for that specific boot image.
- // TODO: find a better way to know we're using the JIT zygote configuration.
- filesToPin = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_jitzygoteBootImagePinnerServiceFiles);
- } else {
- // Files to pin come from the overlay and can be specified per-device config
- filesToPin = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_defaultPinnerServiceFiles);
- }
+ // Files to pin come from the overlay and can be specified per-device config
+ String[] filesToPin = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_defaultPinnerServiceFiles);
// Continue trying to pin each file even if we fail to pin some of them
for (String fileToPin : filesToPin) {
PinnedFile pf = pinFile(fileToPin,
@@ -286,10 +277,32 @@
Slog.e(TAG, "Failed to pin file = " + fileToPin);
continue;
}
-
synchronized (this) {
mPinnedFiles.add(pf);
}
+ if (fileToPin.endsWith(".jar") | fileToPin.endsWith(".apk")) {
+ // Check whether the runtime has compilation artifacts to pin.
+ String arch = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
+ String[] files = null;
+ try {
+ files = DexFile.getDexFileOutputPaths(fileToPin, arch);
+ } catch (IOException ioe) { }
+ if (files == null) {
+ continue;
+ }
+ for (String file : files) {
+ PinnedFile df = pinFile(file,
+ Integer.MAX_VALUE,
+ /*attemptPinIntrospection=*/false);
+ if (df == null) {
+ Slog.i(TAG, "Failed to pin ART file = " + file);
+ continue;
+ }
+ synchronized (this) {
+ mPinnedFiles.add(df);
+ }
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 3ea4458..b485fe8 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -44,6 +44,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.DeviceConfig;
+import android.telecom.TelecomManager;
import android.telephony.Annotation;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SrvccState;
@@ -215,6 +216,18 @@
return Binder.withCleanCallingIdentity(() -> CompatChanges.isChangeEnabled(
TelephonyCallback.PHONE_STATE_LISTENER_LIMIT_CHANGE_ID, uid));
}
+
+ /**
+ * See {@link TelecomManager#ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION} for more
+ * information.
+ * @noinspection ConstantConditions
+ */
+ public boolean isCallStateReadPhoneStateEnforcedInPlatformCompat(String packageName,
+ UserHandle userHandle) {
+ return Binder.withCleanCallingIdentity(() -> CompatChanges.isChangeEnabled(
+ TelecomManager.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION, packageName,
+ userHandle));
+ }
}
private final Context mContext;
@@ -405,10 +418,15 @@
switch (msg.what) {
case MSG_USER_SWITCHED: {
if (VDBG) log("MSG_USER_SWITCHED userId=" + msg.arg1);
- int numPhones = getTelephonyManager().getPhoneCount();
- for (int sub = 0; sub < numPhones; sub++) {
- TelephonyRegistry.this.notifyCellLocationForSubscriber(sub,
- mCellIdentity[sub]);
+ int numPhones = getTelephonyManager().getActiveModemCount();
+ for (int phoneId = 0; phoneId < numPhones; phoneId++) {
+ int[] subIds = SubscriptionManager.getSubId(phoneId);
+ int subId =
+ (subIds != null) && (subIds.length > 0)
+ ? subIds[0]
+ : SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ TelephonyRegistry.this.notifyCellLocationForSubscriber(
+ subId, mCellIdentity[phoneId], true /* hasUserSwitched */);
}
break;
}
@@ -1933,20 +1951,20 @@
}
@Override
- public void notifyCellLocation(CellIdentity cellLocation) {
- notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
+ public void notifyCellLocationForSubscriber(int subId, CellIdentity cellIdentity) {
+ notifyCellLocationForSubscriber(subId, cellIdentity, false /* hasUserSwitched */);
}
- @Override
- public void notifyCellLocationForSubscriber(int subId, CellIdentity cellIdentity) {
- log("notifyCellLocationForSubscriber: subId=" + subId
- + " cellIdentity=" + cellIdentity);
+ private void notifyCellLocationForSubscriber(int subId, CellIdentity cellIdentity,
+ boolean hasUserSwitched) {
+ log("notifyCellLocationForSubscriber: subId=" + subId + " cellIdentity=" + cellIdentity);
if (!checkNotifyPermission("notifyCellLocation()")) {
return;
}
int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
- if (validatePhoneId(phoneId) && !Objects.equals(cellIdentity, mCellIdentity[phoneId])) {
+ if (validatePhoneId(phoneId)
+ && (hasUserSwitched || !Objects.equals(cellIdentity, mCellIdentity[phoneId]))) {
mCellIdentity[phoneId] = cellIdentity;
for (Record r : mRecords) {
if (validateEventAndUserLocked(
@@ -2607,7 +2625,7 @@
final int recordCount = mRecords.size();
pw.println("last known state:");
pw.increaseIndent();
- for (int i = 0; i < getTelephonyManager().getPhoneCount(); i++) {
+ for (int i = 0; i < getTelephonyManager().getActiveModemCount(); i++) {
pw.println("Phone Id=" + i);
pw.increaseIndent();
pw.println("mCallState=" + mCallState[i]);
@@ -2947,6 +2965,19 @@
}
}
+ // Only check READ_PHONE_STATE for CALL_STATE_CHANGED for API 31+.
+ if (mConfigurationProvider.isCallStateReadPhoneStateEnforcedInPlatformCompat(callingPackage,
+ Binder.getCallingUserHandle())) {
+ if (events.contains(TelephonyCallback.EVENT_LEGACY_CALL_STATE_CHANGED)
+ || events.contains(TelephonyCallback.EVENT_CALL_STATE_CHANGED)) {
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+ mContext, subId, callingPackage, callingFeatureId, message)) {
+ throw new SecurityException("CALL_STATE_CHANGED event requires "
+ + "READ_PHONE_STATE");
+ }
+ }
+ }
+
if (isPrecisePhoneStatePermissionRequired(events)) {
// check if calling app has either permission READ_PRECISE_PHONE_STATE
// or with carrier privileges
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7f8d944..4c7ea57 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -70,6 +70,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UptimeMillisLong;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityThread;
@@ -131,6 +132,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
+import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.webkit.WebViewZygote;
@@ -225,6 +227,11 @@
final ArrayList<ServiceRecord> mPendingFgsNotifications = new ArrayList<>();
/**
+ * Uptime at which a given uid becomes eliglible again for FGS notification deferral
+ */
+ final SparseLongArray mFgsDeferralEligible = new SparseLongArray();
+
+ /**
* Map of services that are asked to be brought up (start/binding) but not ready to.
*/
private ArrayMap<ServiceRecord, ArrayList<Runnable>> mPendingBringups = new ArrayMap<>();
@@ -237,6 +244,12 @@
private final SparseArray<AppOpCallback> mFgsAppOpCallbacks = new SparseArray<>();
/**
+ * The list of packages with the service restart backoff disabled.
+ */
+ @GuardedBy("mAm")
+ private final ArraySet<String> mRestartBackoffDisabledPackages = new ArraySet<>();
+
+ /**
* For keeping ActiveForegroundApps retaining state while the screen is off.
*/
boolean mScreenOn = true;
@@ -1965,11 +1978,30 @@
}
}
+ private boolean withinFgsDeferRateLimit(final int uid, final long now) {
+ final long eligible = mFgsDeferralEligible.get(uid, 0L);
+ if (DEBUG_FOREGROUND_SERVICE) {
+ if (now < eligible) {
+ Slog.d(TAG_SERVICE, "FGS transition for uid " + uid
+ + " within rate limit, showing immediately");
+ }
+ }
+ return now < eligible;
+ }
+
// TODO: remove as part of fixing b/173627642
@SuppressWarnings("AndroidFrameworkCompatChange")
private void postFgsNotificationLocked(ServiceRecord r) {
+ final int uid = r.appInfo.uid;
+ final long now = SystemClock.uptimeMillis();
final boolean isLegacyApp = (r.appInfo.targetSdkVersion < Build.VERSION_CODES.S);
- boolean showNow = !mAm.mConstants.mFlagFgsNotificationDeferralEnabled;
+
+ boolean showNow = withinFgsDeferRateLimit(uid, now);
+ if (!showNow) {
+ final boolean showLegacyNow = isLegacyApp
+ && mAm.mConstants.mFlagFgsNotificationDeferralApiGated;
+ showNow = !mAm.mConstants.mFlagFgsNotificationDeferralEnabled || showLegacyNow;
+ }
if (!showNow) {
// Legacy apps' FGS notifications are not deferred unless the relevant
// DeviceConfig element has been set
@@ -2014,8 +2046,6 @@
}
// schedule the actual notification post
- final int uid = r.appInfo.uid;
- final long now = SystemClock.uptimeMillis();
long when = now + mAm.mConstants.mFgsNotificationDeferralInterval;
// If there are already deferred FGS notifications for this app,
// inherit that deferred-show timestamp
@@ -2033,6 +2063,9 @@
when = Math.min(when, pending.fgDisplayTime);
}
}
+
+ final long nextEligible = when + mAm.mConstants.mFgsNotificationDeferralExclusionTime;
+ mFgsDeferralEligible.put(uid, nextEligible);
r.fgDisplayTime = when;
mPendingFgsNotifications.add(r);
if (DEBUG_FOREGROUND_SERVICE) {
@@ -3272,25 +3305,32 @@
}
}
- r.nextRestartTime = now + r.restartDelay;
+ if (isServiceRestartBackoffEnabledLocked(r.packageName)) {
+ r.nextRestartTime = now + r.restartDelay;
- // Make sure that we don't end up restarting a bunch of services
- // all at the same time.
- boolean repeat;
- do {
- repeat = false;
+ // Make sure that we don't end up restarting a bunch of services
+ // all at the same time.
+ boolean repeat;
final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN;
- for (int i=mRestartingServices.size()-1; i>=0; i--) {
- ServiceRecord r2 = mRestartingServices.get(i);
- if (r2 != r && r.nextRestartTime >= (r2.nextRestartTime-restartTimeBetween)
- && r.nextRestartTime < (r2.nextRestartTime+restartTimeBetween)) {
- r.nextRestartTime = r2.nextRestartTime + restartTimeBetween;
- r.restartDelay = r.nextRestartTime - now;
- repeat = true;
- break;
+ do {
+ repeat = false;
+ for (int i = mRestartingServices.size() - 1; i >= 0; i--) {
+ final ServiceRecord r2 = mRestartingServices.get(i);
+ if (r2 != r
+ && r.nextRestartTime >= (r2.nextRestartTime - restartTimeBetween)
+ && r.nextRestartTime < (r2.nextRestartTime + restartTimeBetween)) {
+ r.nextRestartTime = r2.nextRestartTime + restartTimeBetween;
+ r.restartDelay = r.nextRestartTime - now;
+ repeat = true;
+ break;
+ }
}
- }
- } while (repeat);
+ } while (repeat);
+ } else {
+ // It's been forced to ignore the restart backoff, fix the delay here.
+ r.restartDelay = mAm.mConstants.SERVICE_RESTART_DURATION;
+ r.nextRestartTime = now + r.restartDelay;
+ }
} else {
// Persistent processes are immediately restarted, so there is no
@@ -3310,15 +3350,22 @@
cancelForegroundNotificationLocked(r);
+ performScheduleRestartLocked(r, "Scheduling", reason, SystemClock.uptimeMillis());
+
+ return true;
+ }
+
+ @VisibleForTesting
+ @GuardedBy("mAm")
+ void performScheduleRestartLocked(ServiceRecord r, @NonNull String scheduling,
+ @NonNull String reason, @UptimeMillisLong long now) {
mAm.mHandler.removeCallbacks(r.restarter);
mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
- r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
- Slog.w(TAG, "Scheduling restart of crashed service "
+ r.nextRestartTime = now + r.restartDelay;
+ Slog.w(TAG, scheduling + " restart of crashed service "
+ r.shortInstanceName + " in " + r.restartDelay + "ms for " + reason);
EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
r.userId, r.shortInstanceName, r.restartDelay);
-
- return true;
}
final void performServiceRestartLocked(ServiceRecord r) {
@@ -3383,6 +3430,52 @@
}
}
+ /**
+ * Toggle service restart backoff policy, used by {@link ActivityManagerShellCommand}.
+ */
+ @GuardedBy("mAm")
+ void setServiceRestartBackoffEnabledLocked(@NonNull String packageName, boolean enable,
+ @NonNull String reason) {
+ if (!enable) {
+ if (mRestartBackoffDisabledPackages.contains(packageName)) {
+ // Already disabled, do nothing.
+ return;
+ }
+ mRestartBackoffDisabledPackages.add(packageName);
+
+ final long now = SystemClock.uptimeMillis();
+ for (int i = 0, size = mRestartingServices.size(); i < size; i++) {
+ final ServiceRecord r = mRestartingServices.get(i);
+ if (TextUtils.equals(r.packageName, packageName)) {
+ final long remaining = r.nextRestartTime - now;
+ if (remaining > mAm.mConstants.SERVICE_RESTART_DURATION) {
+ r.restartDelay = mAm.mConstants.SERVICE_RESTART_DURATION;
+ r.nextRestartTime = now + r.restartDelay;
+ performScheduleRestartLocked(r, "Rescheduling", reason, now);
+ }
+ }
+ }
+ } else {
+ removeServiceRestartBackoffEnabledLocked(packageName);
+ // For the simplicity, we are not going to reschedule its pending restarts
+ // when we turn the backoff policy back on.
+ }
+ }
+
+ @GuardedBy("mAm")
+ private void removeServiceRestartBackoffEnabledLocked(@NonNull String packageName) {
+ mRestartBackoffDisabledPackages.remove(packageName);
+ }
+
+ /**
+ * @return {@code false} if the given package has been disable from enforcing the service
+ * restart backoff policy, used by {@link ActivityManagerShellCommand}.
+ */
+ @GuardedBy("mAm")
+ boolean isServiceRestartBackoffEnabledLocked(@NonNull String packageName) {
+ return !mRestartBackoffDisabledPackages.contains(packageName);
+ }
+
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
boolean enqueueOomAdj)
@@ -4431,6 +4524,7 @@
mPendingBringups.removeAt(i);
}
}
+ removeServiceRestartBackoffEnabledLocked(packageName);
}
void cleanUpServices(int userId, ComponentName component, Intent baseIntent) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index e16f4c9..c8363dd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -199,6 +199,15 @@
private static final String KEY_DEFERRED_FGS_NOTIFICATION_INTERVAL =
"deferred_fgs_notification_interval";
+ /**
+ * Time in milliseconds; once an FGS notification for a given uid has been
+ * deferred, no subsequent FGS notification from that uid will be deferred
+ * until this amount of time has passed. Default is two minutes
+ * (2 * 60 * 1000) unless overridden.
+ */
+ private static final String KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME =
+ "deferred_fgs_notification_exclusion_time";
+
// Maximum number of cached processes we will allow.
public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -398,6 +407,10 @@
// the foreground state.
volatile long mFgsNotificationDeferralInterval = 10_000;
+ // Rate limit: minimum time after an app's FGS notification is deferred
+ // before another FGS notifiction from that app can be deferred.
+ volatile long mFgsNotificationDeferralExclusionTime = 2 * 60 * 1000L;
+
/*
* At boot time, broadcast receiver ACTION_BOOT_COMPLETED, ACTION_LOCKED_BOOT_COMPLETED and
* ACTION_PRE_BOOT_COMPLETED are temp allowlisted to start FGS for a duration of time in
@@ -580,6 +593,9 @@
case KEY_DEFERRED_FGS_NOTIFICATION_INTERVAL:
updateFgsNotificationDeferralInterval();
break;
+ case KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME:
+ updateFgsNotificationDeferralExclusionTime();
+ break;
case KEY_OOMADJ_UPDATE_POLICY:
updateOomAdjUpdatePolicy();
break;
@@ -874,6 +890,13 @@
/*default value*/ 10_000L);
}
+ private void updateFgsNotificationDeferralExclusionTime() {
+ mFgsNotificationDeferralExclusionTime = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME,
+ /*default value*/ 2 * 60 * 1000L);
+ }
+
private void updateOomAdjUpdatePolicy() {
OOMADJ_UPDATE_QUICK = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 036b88e..8e63efa 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -188,6 +188,7 @@
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
+import android.content.AttributionSource;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
@@ -254,11 +255,11 @@
import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
-import android.os.PowerWhitelistManager.ReasonCode;
-import android.os.PowerWhitelistManager.TempAllowListType;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -340,7 +341,11 @@
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.QuintFunction;
+import com.android.internal.util.function.TriFunction;
import com.android.server.AlarmManagerInternal;
import com.android.server.DeviceIdleInternal;
import com.android.server.DisplayThread;
@@ -367,6 +372,7 @@
import com.android.server.job.JobSchedulerInternal;
import com.android.server.os.NativeTombstoneManager;
import com.android.server.pm.Installer;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.uri.GrantUri;
import com.android.server.uri.NeededUriGrants;
@@ -1123,24 +1129,6 @@
CoreSettingsObserver mCoreSettingsObserver;
/**
- * Thread-local storage used to carry caller permissions over through
- * indirect content-provider access.
- */
- private class Identity {
- public final IBinder token;
- public final int pid;
- public final int uid;
-
- Identity(IBinder _token, int _pid, int _uid) {
- token = _token;
- pid = _pid;
- uid = _uid;
- }
- }
-
- private static final ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
-
- /**
* All information we have collected about the runtime performance of
* any user id that can impact battery performance.
*/
@@ -5344,26 +5332,6 @@
return checkComponentPermission(permission, pid, uid, -1, true);
}
- @Override
- public int checkPermissionWithToken(String permission, int pid, int uid, IBinder callerToken) {
- if (permission == null) {
- return PackageManager.PERMISSION_DENIED;
- }
-
- // We might be performing an operation on behalf of an indirect binder
- // invocation, e.g. via {@link #openContentUri}. Check and adjust the
- // client identity accordingly before proceeding.
- Identity tlsIdentity = sCallerIdentity.get();
- if (tlsIdentity != null && tlsIdentity.token == callerToken) {
- Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
- + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
- uid = tlsIdentity.uid;
- pid = tlsIdentity.pid;
- }
-
- return checkComponentPermission(permission, pid, uid, -1, true);
- }
-
/**
* Binder IPC calls go through the public entry point.
* This can be called with or without the global lock held.
@@ -5618,14 +5586,6 @@
final int modeFlags, int userId, IBinder callerToken) {
enforceNotIsolatedCaller("checkUriPermission");
- // Another redirected-binder-call permissions check as in
- // {@link checkPermissionWithToken}.
- Identity tlsIdentity = sCallerIdentity.get();
- if (tlsIdentity != null && tlsIdentity.token == callerToken) {
- uid = tlsIdentity.uid;
- pid = tlsIdentity.pid;
- }
-
// Our own process gets to do everything.
if (pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
@@ -6159,23 +6119,19 @@
Binder.getCallingUid(), "*opencontent*", userId);
ParcelFileDescriptor pfd = null;
if (cph != null) {
- // We record the binder invoker's uid in thread-local storage before
- // going to the content provider to open the file. Later, in the code
- // that handles all permissions checks, we look for this uid and use
- // that rather than the Activity Manager's own uid. The effect is that
- // we do the check against the caller's permissions even though it looks
- // to the content provider like the Activity Manager itself is making
- // the request.
- Binder token = new Binder();
- sCallerIdentity.set(new Identity(
- token, Binder.getCallingPid(), Binder.getCallingUid()));
try {
- pfd = cph.provider.openFile(null, null, uri, "r", null, token);
+ // This method is exposed to the VNDK and to avoid changing its
+ // signature we just use the first package in the UID. For shared
+ // UIDs we may blame the wrong app but that is Okay as they are
+ // in the same security/privacy sandbox.
+ final AndroidPackage androidPackage = mPackageManagerInt
+ .getPackage(Binder.getCallingUid());
+ final AttributionSource attributionSource = new AttributionSource(
+ Binder.getCallingUid(), androidPackage.getPackageName(), null);
+ pfd = cph.provider.openFile(attributionSource, uri, "r", null);
} catch (FileNotFoundException e) {
// do nothing; pfd will be returned null
} finally {
- // Ensure that whatever happens, we clean up the identity state
- sCallerIdentity.remove();
// Ensure we're done with the provider.
mCpHelper.removeContentProviderExternalUnchecked(name, null, userId);
}
@@ -8436,6 +8392,26 @@
}
}
+ /**
+ * Toggle service restart backoff policy, used by {@link ActivityManagerShellCommand}.
+ */
+ void setServiceRestartBackoffEnabled(@NonNull String packageName, boolean enable,
+ @NonNull String reason) {
+ synchronized (this) {
+ mServices.setServiceRestartBackoffEnabledLocked(packageName, enable, reason);
+ }
+ }
+
+ /**
+ * @return {@code false} if the given package has been disable from enforcing the service
+ * restart backoff policy, used by {@link ActivityManagerShellCommand}.
+ */
+ boolean isServiceRestartBackoffEnabled(@NonNull String packageName) {
+ synchronized (this) {
+ return mServices.isServiceRestartBackoffEnabledLocked(packageName);
+ }
+ }
+
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
@@ -16639,6 +16615,74 @@
message, shouldCollectMessage);
}
+ @Override
+ public int noteProxyOperation(int code, @NonNull AttributionSource attributionSource,
+ boolean shouldCollectAsyncNotedOp, @Nullable String message,
+ boolean shouldCollectMessage, boolean skiProxyOperation,
+ @NonNull HexFunction<Integer, AttributionSource, Boolean, String, Boolean,
+ Boolean, Integer> superImpl) {
+ if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) {
+ final int shellUid = UserHandle.getUid(UserHandle.getUserId(
+ attributionSource.getUid()), Process.SHELL_UID);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return superImpl.apply(code, new AttributionSource(shellUid,
+ "com.android.shell", attributionSource.getAttributionTag(),
+ attributionSource.getNext()),
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ skiProxyOperation);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ return superImpl.apply(code, attributionSource, shouldCollectAsyncNotedOp,
+ message, shouldCollectMessage, skiProxyOperation);
+ }
+
+ @Override
+ public int startProxyOperation(IBinder token, int code,
+ @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ boolean skipProsyOperation, @NonNull OctFunction<IBinder, Integer,
+ AttributionSource, Boolean, Boolean, String, Boolean, Boolean,
+ Integer> superImpl) {
+ if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) {
+ final int shellUid = UserHandle.getUid(UserHandle.getUserId(
+ attributionSource.getUid()), Process.SHELL_UID);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return superImpl.apply(token, code, new AttributionSource(shellUid,
+ "com.android.shell", attributionSource.getAttributionTag(),
+ attributionSource.getNext()), startIfModeDefault,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ skipProsyOperation);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ return superImpl.apply(token, code, attributionSource, startIfModeDefault,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProsyOperation);
+ }
+
+ @Override
+ public void finishProxyOperation(IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource,
+ @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl) {
+ if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) {
+ final int shellUid = UserHandle.getUid(UserHandle.getUserId(
+ attributionSource.getUid()), Process.SHELL_UID);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ superImpl.apply(clientId, code, new AttributionSource(shellUid,
+ "com.android.shell", attributionSource.getAttributionTag(),
+ attributionSource.getNext()));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ superImpl.apply(clientId, code, attributionSource);
+ }
+
private boolean isTargetOp(int code) {
// null permissions means all ops are targeted
if (mPermissions == null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index b8e06ee..42aac29 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -318,6 +318,8 @@
return runRefreshSettingsCache();
case "memory-factor":
return runMemoryFactor(pw);
+ case "service-restart-backoff":
+ return runServiceRestartBackoff(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -3095,6 +3097,28 @@
}
}
+ private int runServiceRestartBackoff(PrintWriter pw) throws RemoteException {
+ mInternal.enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
+ "runServiceRestartBackoff()");
+
+ final String opt = getNextArgRequired();
+ switch (opt) {
+ case "enable":
+ mInternal.setServiceRestartBackoffEnabled(getNextArgRequired(), true, "shell");
+ return 0;
+ case "disable":
+ mInternal.setServiceRestartBackoffEnabled(getNextArgRequired(), false, "shell");
+ return 0;
+ case "show":
+ pw.println(mInternal.isServiceRestartBackoffEnabled(getNextArgRequired())
+ ? "enabled" : "disabled");
+ return 0;
+ default:
+ getErrPrintWriter().println("Error: unknown command '" + opt + "'");
+ return -1;
+ }
+ }
+
private Resources getResources(PrintWriter pw) throws RemoteException {
// system resources does not contain all the device configuration, construct it manually.
Configuration config = mInterface.getConfiguration();
@@ -3418,6 +3442,11 @@
pw.println(" Shows the existing memory pressure factor");
pw.println(" reset");
pw.println(" Removes existing override for memory pressure factor");
+ pw.println(" service-restart-backoff <COMMAND> [...]: sub-commands to toggle service restart backoff policy.");
+ pw.println(" enable|disable <PACKAGE_NAME>");
+ pw.println(" Toggles the restart backoff policy on/off for <PACKAGE_NAME>.");
+ pw.println(" show <PACKAGE_NAME>");
+ pw.println(" Shows the restart backoff policy state for <PACKAGE_NAME>.");
pw.println();
Intent.printIntentArgsHelp(pw, "");
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 9ecae42..7f2eae8 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -45,8 +45,8 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
-import android.os.PowerWhitelistManager;
-import android.os.PowerWhitelistManager.TempAllowListType;
+import android.os.PowerExemptionManager.ReasonCode;
+import android.os.PowerExemptionManager.TempAllowListType;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -908,7 +908,7 @@
}
final void scheduleTempAllowlistLocked(int uid, long duration, BroadcastRecord r,
- @TempAllowListType int type, @PowerWhitelistManager.ReasonCode int reasonCode,
+ @TempAllowListType int type, @ReasonCode int reasonCode,
@Nullable String reason) {
if (duration > Integer.MAX_VALUE) {
duration = Integer.MAX_VALUE;
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index ee4526b..b44699b 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -33,6 +33,7 @@
import android.app.ContentProviderHolder;
import android.app.IApplicationThread;
import android.app.usage.UsageEvents.Event;
+import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -42,6 +43,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.database.ContentObserver;
@@ -67,7 +69,9 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
+import com.android.server.LocalServices;
import com.android.server.RescueParty;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -1037,7 +1041,19 @@
holder = getContentProviderExternalUnchecked(name, null, callingUid,
"*checkContentProviderUriPermission*", userId);
if (holder != null) {
- return holder.provider.checkUriPermission(null, null, uri, callingUid, modeFlags);
+
+ final PackageManagerInternal packageManagerInt = LocalServices.getService(
+ PackageManagerInternal.class);
+ final AndroidPackage androidPackage = packageManagerInt
+ .getPackage(Binder.getCallingUid());
+ if (androidPackage == null) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+
+ final AttributionSource attributionSource = new AttributionSource(
+ callingUid, androidPackage.getPackageName(), null);
+ return holder.provider.checkUriPermission(attributionSource, uri, callingUid,
+ modeFlags);
}
} catch (RemoteException e) {
Log.w(TAG, "Content provider dead retrieving " + uri, e);
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 51666ac..f7c777e 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -66,7 +66,7 @@
/**
* Map IBinder to duration specified as Pair<Long, Integer>, Long is allowlist duration in
* milliseconds, Integer is allowlist type defined at
- * {@link android.os.PowerWhitelistManager.TempAllowListType}
+ * {@link android.os.PowerExemptionManager.TempAllowListType}
*/
private ArrayMap<IBinder, TempAllowListDuration> mAllowlistDuration;
private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 31183cac..143a1cf 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1641,13 +1641,6 @@
* PIN or pattern.
*/
private boolean maybeUnlockUser(final @UserIdInt int userId) {
- if (mInjector.isFileEncryptedNativeOnly() && mLockPatternUtils.isSecure(userId)) {
- // A token is needed, so don't bother trying to unlock without one.
- // This keeps misleading error messages from being logged.
- Slog.d(TAG, "Not unlocking user " + userId
- + "'s CE storage yet because a credential token is needed");
- return false;
- }
// Try unlocking storage using empty token
return unlockUserCleared(userId, null, null, null);
}
@@ -3108,11 +3101,5 @@
protected IStorageManager getStorageManager() {
return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
}
-
- // This is needed because isFileEncryptedNativeOnly is a static method,
- // but it needs to be mocked out in tests.
- protected boolean isFileEncryptedNativeOnly() {
- return StorageManager.isFileEncryptedNativeOnly();
- }
}
}
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index 5a99e0e..a12b213 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -106,6 +106,7 @@
private final HibernationStateDiskStore<GlobalLevelState> mGlobalLevelHibernationDiskStore;
private final Injector mInjector;
private final Executor mBackgroundExecutor;
+ private final boolean mOatArtifactDeletionEnabled;
@VisibleForTesting
boolean mIsServiceEnabled;
@@ -133,6 +134,7 @@
mUserManager = injector.getUserManager();
mGlobalLevelHibernationDiskStore = injector.getGlobalLevelDiskStore();
mBackgroundExecutor = injector.getBackgroundExecutor();
+ mOatArtifactDeletionEnabled = injector.isOatArtifactDeletionEnabled();
mInjector = injector;
final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
@@ -371,7 +373,9 @@
@GuardedBy("mLock")
private void hibernatePackageGlobally(@NonNull String packageName, GlobalLevelState state) {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackageGlobally");
- mPackageManagerInternal.deleteOatArtifactsOfPackage(packageName);
+ if (mOatArtifactDeletionEnabled) {
+ mPackageManagerInternal.deleteOatArtifactsOfPackage(packageName);
+ }
state.hibernated = true;
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
@@ -744,6 +748,8 @@
HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore();
HibernationStateDiskStore<UserLevelState> getUserLevelDiskStore(int userId);
+
+ boolean isOatArtifactDeletionEnabled();
}
private static final class InjectorImpl implements Injector {
@@ -801,5 +807,11 @@
return new HibernationStateDiskStore<>(
dir, mUserLevelHibernationProto, mScheduledExecutorService);
}
+
+ @Override
+ public boolean isOatArtifactDeletionEnabled() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_hibernationDeletesOatArtifactsEnabled);
+ }
}
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 7bc7105..10f7ef6 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -94,6 +94,7 @@
import android.app.RuntimeAppOpAccessMessage;
import android.app.SyncNotedAppOp;
import android.app.admin.DevicePolicyManagerInternal;
+import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -131,6 +132,7 @@
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.KeyValueListParser;
+import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pair;
import android.util.Pools;
@@ -159,6 +161,9 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
+import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.QuintFunction;
+import com.android.internal.util.function.TriFunction;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
@@ -1999,8 +2004,10 @@
@Override
public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
- mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
- Binder.getCallingPid(), Binder.getCallingUid(), null);
+ final int callingUid = Binder.getCallingUid();
+ final boolean hasAllPackageAccess = mContext.checkPermission(
+ Manifest.permission.GET_APP_OPS_STATS, Binder.getCallingPid(),
+ Binder.getCallingUid(), null) == PackageManager.PERMISSION_GRANTED;
ArrayList<AppOpsManager.PackageOps> res = null;
synchronized (this) {
final int uidStateCount = mUidStates.size();
@@ -2016,11 +2023,14 @@
ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
if (resOps != null) {
if (res == null) {
- res = new ArrayList<AppOpsManager.PackageOps>();
+ res = new ArrayList<>();
}
AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
pkgOps.packageName, pkgOps.uidState.uid, resOps);
- res.add(resPackage);
+ // Caller can always see their packages and with a permission all.
+ if (hasAllPackageAccess || callingUid == pkgOps.uidState.uid) {
+ res.add(resPackage);
+ }
}
}
}
@@ -2031,9 +2041,8 @@
@Override
public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName,
int[] ops) {
- mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
- Binder.getCallingPid(), Binder.getCallingUid(), null);
- String resolvedPackageName = resolvePackageName(uid, packageName);
+ enforceGetAppOpsStatsPermissionIfNeeded(uid,packageName);
+ String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
return Collections.emptyList();
}
@@ -2054,6 +2063,22 @@
}
}
+ private void enforceGetAppOpsStatsPermissionIfNeeded(int uid, String packageName) {
+ final int callingUid = Binder.getCallingUid();
+ // We get to access everything
+ if (callingUid == Process.myPid()) {
+ return;
+ }
+ // Apps can access their own data
+ if (uid == callingUid && packageName != null
+ && checkPackage(uid, packageName) == MODE_ALLOWED) {
+ return;
+ }
+ // Otherwise, you need a permission...
+ mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
+ Binder.getCallingPid(), callingUid, null);
+ }
+
/**
* Verify that historical appop request arguments are valid.
*/
@@ -2941,7 +2966,7 @@
verifyIncomingOp(code);
verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
- String resolvedPackageName = resolvePackageName(uid, packageName);
+ String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
@@ -3078,16 +3103,54 @@
}
@Override
- public int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
- String proxiedAttributionTag, int proxyUid, String proxyPackageName,
- String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message,
- boolean shouldCollectMessage) {
- verifyIncomingUid(proxyUid);
+ public int noteProxyOperation(int code, AttributionSource attributionSource,
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ boolean skipProxyOperation) {
+ final CheckOpsDelegate policy;
+ final CheckOpsDelegateDispatcher delegateDispatcher;
+ synchronized (AppOpsService.this) {
+ policy = mAppOpsPolicy;
+ delegateDispatcher = mCheckOpsDelegateDispatcher;
+ }
+ if (policy != null) {
+ if (delegateDispatcher != null) {
+ return policy.noteProxyOperation(code, attributionSource,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ skipProxyOperation, delegateDispatcher::noteProxyOperationImpl);
+ } else {
+ return policy.noteProxyOperation(code, attributionSource,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ skipProxyOperation, AppOpsService.this::noteProxyOperationImpl);
+ }
+ } else if (delegateDispatcher != null) {
+ delegateDispatcher.getCheckOpsDelegate().noteProxyOperation(code,
+ attributionSource, shouldCollectAsyncNotedOp, message,
+ shouldCollectMessage, skipProxyOperation,
+ AppOpsService.this::noteProxyOperationImpl);
+ }
+ return noteProxyOperationImpl(code, attributionSource, shouldCollectAsyncNotedOp,
+ message, shouldCollectMessage,skipProxyOperation);
+ }
+
+ private int noteProxyOperationImpl(int code, AttributionSource attributionSource,
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ boolean skipProxyOperation) {
+ final int proxyUid = attributionSource.getUid();
+ final String proxyPackageName = attributionSource.getPackageName();
+ final String proxyAttributionTag = attributionSource.getAttributionTag();
+ final int proxiedUid = attributionSource.getNextUid();
+ final String proxiedPackageName = attributionSource.getNextPackageName();
+ final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
+
+ verifyIncomingProxyUid(attributionSource);
verifyIncomingOp(code);
verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid));
verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid));
- String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
+ skipProxyOperation = resolveSkipProxyOperation(skipProxyOperation, attributionSource);
+
+ String resolveProxyPackageName = AppOpsManager.resolvePackageName(proxyUid,
+ proxyPackageName);
if (resolveProxyPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
@@ -3097,19 +3160,24 @@
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
== PackageManager.PERMISSION_GRANTED || isSelfBlame;
- final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
- : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
- final int proxyMode = noteOperationUnchecked(code, proxyUid, resolveProxyPackageName,
- proxyAttributionTag, Process.INVALID_UID, null, null, proxyFlags,
- !isProxyTrusted, "proxy " + message, shouldCollectMessage);
- if (proxyMode != AppOpsManager.MODE_ALLOWED) {
- return proxyMode;
+ if (!skipProxyOperation) {
+ final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
+ : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
+
+ final int proxyMode = noteOperationUnchecked(code, proxyUid, resolveProxyPackageName,
+ proxyAttributionTag, Process.INVALID_UID, null, null, proxyFlags,
+ !isProxyTrusted, "proxy " + message, shouldCollectMessage);
+ if (proxyMode != AppOpsManager.MODE_ALLOWED) {
+ return proxyMode;
+ }
}
- String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
+ String resolveProxiedPackageName = AppOpsManager.resolvePackageName(proxiedUid,
+ proxiedPackageName);
if (resolveProxiedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
+
final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
@@ -3152,7 +3220,7 @@
verifyIncomingOp(code);
verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
- String resolvedPackageName = resolvePackageName(uid, packageName);
+ String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
@@ -3535,7 +3603,7 @@
verifyIncomingOp(code);
verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
- String resolvedPackageName = resolvePackageName(uid, packageName);
+ String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
@@ -3558,17 +3626,58 @@
}
@Override
- public int startProxyOperation(IBinder clientId, int code, int proxiedUid,
- String proxiedPackageName, @Nullable String proxiedAttributionTag, int proxyUid,
- String proxyPackageName, @Nullable String proxyAttributionTag,
+ public int startProxyOperation(IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ boolean skipProxyOperation) {
+ final CheckOpsDelegate policy;
+ final CheckOpsDelegateDispatcher delegateDispatcher;
+ synchronized (AppOpsService.this) {
+ policy = mAppOpsPolicy;
+ delegateDispatcher = mCheckOpsDelegateDispatcher;
+ }
+ if (policy != null) {
+ if (delegateDispatcher != null) {
+ return policy.startProxyOperation(clientId, code, attributionSource,
+ startIfModeDefault, shouldCollectAsyncNotedOp, message,
+ shouldCollectMessage, skipProxyOperation,
+ delegateDispatcher::startProxyOperationImpl);
+ } else {
+ return policy.startProxyOperation(clientId, code, attributionSource,
+ startIfModeDefault, shouldCollectAsyncNotedOp, message,
+ shouldCollectMessage, skipProxyOperation,
+ AppOpsService.this::startProxyOperationImpl);
+ }
+ } else if (delegateDispatcher != null) {
+ delegateDispatcher.getCheckOpsDelegate().startProxyOperation(clientId, code,
+ attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message,
+ shouldCollectMessage, skipProxyOperation,
+ AppOpsService.this::startProxyOperationImpl);
+ }
+ return startProxyOperationImpl(clientId, code, attributionSource, startIfModeDefault,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation);
+ }
+
+ private int startProxyOperationImpl(IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
- boolean shouldCollectMessage) {
- verifyIncomingUid(proxyUid);
+ boolean shouldCollectMessage, boolean skipProxyOperation) {
+ final int proxyUid = attributionSource.getUid();
+ final String proxyPackageName = attributionSource.getPackageName();
+ final String proxyAttributionTag = attributionSource.getAttributionTag();
+ final int proxiedUid = attributionSource.getNextUid();
+ final String proxiedPackageName = attributionSource.getNextPackageName();
+ final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
+
+ verifyIncomingProxyUid(attributionSource);
verifyIncomingOp(code);
verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid));
verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid));
- String resolvedProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
+ skipProxyOperation = resolveSkipProxyOperation(skipProxyOperation, attributionSource);
+
+ String resolvedProxyPackageName = AppOpsManager.resolvePackageName(proxyUid,
+ proxyPackageName);
if (resolvedProxyPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
@@ -3578,31 +3687,35 @@
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
== PackageManager.PERMISSION_GRANTED || isSelfBlame;
- final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
- : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
-
- String resolvedProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
+ String resolvedProxiedPackageName = AppOpsManager.resolvePackageName(proxiedUid,
+ proxiedPackageName);
if (resolvedProxiedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
+
final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
- // Test if the proxied operation will succeed before starting the proxy operation
- final int testProxiedMode = startOperationUnchecked(clientId, code, proxiedUid,
- resolvedProxiedPackageName, proxiedAttributionTag, proxyUid,
- resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault,
- shouldCollectAsyncNotedOp, message, shouldCollectMessage, true);
- if (!shouldStartForMode(testProxiedMode, startIfModeDefault)) {
- return testProxiedMode;
- }
+ if (!skipProxyOperation) {
+ // Test if the proxied operation will succeed before starting the proxy operation
+ final int testProxiedMode = startOperationUnchecked(clientId, code, proxiedUid,
+ resolvedProxiedPackageName, proxiedAttributionTag, proxyUid,
+ resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage, true);
+ if (!shouldStartForMode(testProxiedMode, startIfModeDefault)) {
+ return testProxiedMode;
+ }
- final int proxyMode = startOperationUnchecked(clientId, code, proxyUid,
- resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null,
- proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message,
- shouldCollectMessage, false);
- if (!shouldStartForMode(proxyMode, startIfModeDefault)) {
- return proxyMode;
+ final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
+ : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
+
+ final int proxyMode = startOperationUnchecked(clientId, code, proxyUid,
+ resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null,
+ proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message,
+ shouldCollectMessage, false);
+ if (!shouldStartForMode(proxyMode, startIfModeDefault)) {
+ return proxyMode;
+ }
}
return startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
@@ -3714,7 +3827,7 @@
verifyIncomingOp(code);
verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
- String resolvedPackageName = resolvePackageName(uid, packageName);
+ String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
return;
}
@@ -3723,29 +3836,62 @@
}
@Override
- public void finishProxyOperation(IBinder clientId, int code, int proxiedUid,
- String proxiedPackageName, @Nullable String proxiedAttributionTag, int proxyUid,
- @Nullable String proxyPackageName, @Nullable String proxyAttributionTag) {
+ public void finishProxyOperation(IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource) {
+ final CheckOpsDelegate policy;
+ final CheckOpsDelegateDispatcher delegateDispatcher;
+ synchronized (AppOpsService.this) {
+ policy = mAppOpsPolicy;
+ delegateDispatcher = mCheckOpsDelegateDispatcher;
+ }
+ if (policy != null) {
+ if (delegateDispatcher != null) {
+ policy.finishProxyOperation(clientId, code, attributionSource,
+ delegateDispatcher::finishProxyOperationImpl);
+ } else {
+ policy.finishProxyOperation(clientId, code, attributionSource,
+ AppOpsService.this::finishProxyOperationImpl);
+ }
+ } else if (delegateDispatcher != null) {
+ delegateDispatcher.getCheckOpsDelegate().finishProxyOperation(clientId, code,
+ attributionSource, AppOpsService.this::finishProxyOperationImpl);
+ }
+ finishProxyOperationImpl(clientId, code, attributionSource);
+ }
+
+ private Void finishProxyOperationImpl(IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource) {
+ final int proxyUid = attributionSource.getUid();
+ final String proxyPackageName = attributionSource.getPackageName();
+ final String proxyAttributionTag = attributionSource.getAttributionTag();
+ final int proxiedUid = attributionSource.getNextUid();
+ final String proxiedPackageName = attributionSource.getNextPackageName();
+ final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
+
verifyIncomingUid(proxyUid);
verifyIncomingOp(code);
verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid));
verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid));
- String resolvedProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
+ String resolvedProxyPackageName = AppOpsManager.resolvePackageName(proxyUid,
+ proxyPackageName);
if (resolvedProxyPackageName == null) {
- return;
+ return null;
}
finishOperationUnchecked(clientId, code, proxyUid, resolvedProxyPackageName,
proxyAttributionTag);
- String resolvedProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
+ String resolvedProxiedPackageName = AppOpsManager.resolvePackageName(proxiedUid,
+ proxiedPackageName);
if (resolvedProxiedPackageName == null) {
- return;
+ return null;
}
finishOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
proxiedAttributionTag);
+
+ return null;
}
private void finishOperationUnchecked(IBinder clientId, int code, int uid, String packageName,
@@ -3953,6 +4099,20 @@
|| (permInfo.getProtectionFlags() & PROTECTION_FLAG_APPOP) != 0;
}
+ private void verifyIncomingProxyUid(@NonNull AttributionSource attributionSource) {
+ if (attributionSource.getUid() == Binder.getCallingUid()) {
+ return;
+ }
+ if (Binder.getCallingPid() == Process.myPid()) {
+ return;
+ }
+ if (attributionSource.isTrusted(mContext)) {
+ return;
+ }
+ mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid(), null);
+ }
+
private void verifyIncomingUid(int uid) {
if (uid == Binder.getCallingUid()) {
return;
@@ -3979,6 +4139,20 @@
}
}
+ private boolean resolveSkipProxyOperation(boolean requestsSkipProxyOperation,
+ @NonNull AttributionSource attributionSource) {
+ if (!requestsSkipProxyOperation) {
+ return false;
+ }
+ if (attributionSource.getUid() != Binder.getCallingUid()
+ && attributionSource.isTrusted(mContext)) {
+ return true;
+ }
+ return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid(), null)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
private @Nullable UidState getUidStateLocked(int uid, boolean edit) {
UidState uidState = mUidStates.get(uid);
if (uidState == null) {
@@ -4098,7 +4272,6 @@
/**
* Create a restriction description matching the properties of the package.
*
- * @param context A context to use
* @param pkg The package to create the restriction description for
*
* @return The restriction matching the package
@@ -4141,15 +4314,25 @@
int callingUid = Binder.getCallingUid();
int userId = UserHandle.getUserId(uid);
-
RestrictionBypass bypass = null;
+
+ // Allow any attribution tag for resolvable uids
+ int pkgUid = resolveUid(packageName);
+ if (pkgUid != Process.INVALID_UID) {
+ // Special case for the shell which is a package but should be able
+ // to bypass app attribution tag restrictions.
+ if (pkgUid != UserHandle.getAppId(uid)) {
+ throw new SecurityException("Specified package " + packageName + " under uid "
+ + UserHandle.getAppId(uid) + " but it is really " + pkgUid);
+ }
+ return RestrictionBypass.UNRESTRICTED;
+ }
+
final long ident = Binder.clearCallingIdentity();
try {
- int pkgUid;
- AndroidPackage pkg = LocalServices.getService(PackageManagerInternal.class).getPackage(
- packageName);
boolean isAttributionTagValid = false;
-
+ AndroidPackage pkg = LocalServices.getService(PackageManagerInternal.class)
+ .getPackage(packageName);
if (pkg != null) {
if (attributionTag == null) {
isAttributionTagValid = true;
@@ -4166,20 +4349,7 @@
pkgUid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
bypass = getBypassforPackage(pkg);
- } else {
- // Allow any attribution tag for resolvable uids
- isAttributionTagValid = true;
-
- pkgUid = resolveUid(packageName);
- if (pkgUid >= 0) {
- bypass = RestrictionBypass.UNRESTRICTED;
- }
}
- if (pkgUid != uid) {
- throw new SecurityException("Specified package " + packageName + " under uid " + uid
- + " but it is really " + pkgUid);
- }
-
if (!isAttributionTagValid) {
String msg = "attributionTag " + attributionTag + " not declared in"
+ " manifest of " + packageName;
@@ -4187,7 +4357,8 @@
if (mPlatformCompat.isChangeEnabledByPackageName(
SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, packageName,
userId) && mPlatformCompat.isChangeEnabledByUid(
- SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, callingUid)) {
+ SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE,
+ callingUid)) {
throw new SecurityException(msg);
} else {
Slog.e(TAG, msg);
@@ -4199,6 +4370,11 @@
Binder.restoreCallingIdentity(ident);
}
+ if (pkgUid != uid) {
+ throw new SecurityException("Specified package " + packageName + " under uid " + uid
+ + " but it is really " + pkgUid);
+ }
+
return bypass;
}
@@ -6082,7 +6258,7 @@
verifyIncomingOp(code);
verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
- final String resolvedPackageName = resolvePackageName(uid, packageName);
+ final String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
return false;
}
@@ -6103,6 +6279,57 @@
}
@Override
+ public boolean isProxying(int op, @NonNull String proxyPackageName,
+ @NonNull String proxyAttributionTag, int proxiedUid,
+ @NonNull String proxiedPackageName) {
+ Objects.requireNonNull(proxyPackageName);
+ Objects.requireNonNull(proxiedPackageName);
+ Binder.withCleanCallingIdentity(() -> {
+ final List<AppOpsManager.PackageOps> packageOps = getOpsForPackage(proxiedUid,
+ proxiedPackageName, new int[] {op});
+ if (packageOps == null || packageOps.isEmpty()) {
+ return false;
+ }
+ final List<OpEntry> opEntries = packageOps.get(0).getOps();
+ if (opEntries.isEmpty()) {
+ return false;
+ }
+ final OpEntry opEntry = opEntries.get(0);
+ if (!opEntry.isRunning()) {
+ return false;
+ }
+ final OpEventProxyInfo proxyInfo = opEntry.getLastProxyInfo(
+ AppOpsManager.OP_FLAG_TRUSTED_PROXY
+ | AppOpsManager.OP_FLAG_UNTRUSTED_PROXY);
+ return proxyInfo != null && Binder.getCallingUid() == proxyInfo.getUid()
+ && proxyPackageName.equals(proxyInfo.getPackageName())
+ && Objects.equals(proxyAttributionTag, proxyInfo.getAttributionTag());
+ });
+ return false;
+ }
+
+ @Override
+ public void resetPackageOpsNoHistory(@NonNull String packageName) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
+ "resetPackageOpsNoHistory");
+ synchronized (AppOpsService.this) {
+ final int uid = mPackageManagerInternal.getPackageUid(packageName, 0,
+ UserHandle.getCallingUserId());
+ if (uid == Process.INVALID_UID) {
+ return;
+ }
+ UidState uidState = mUidStates.get(uid);
+ if (uidState == null || uidState.pkgOps == null) {
+ return;
+ }
+ Ops removedOps = uidState.pkgOps.remove(packageName);
+ if (removedOps != null) {
+ scheduleFastWriteLocked();
+ }
+ }
+ }
+
+ @Override
public void setHistoryParameters(@AppOpsManager.HistoricalMode int mode,
long baseSnapshotInterval, int compressionStep) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
@@ -6429,23 +6656,6 @@
}
}
- private static String resolvePackageName(int uid, String packageName) {
- if (uid == Process.ROOT_UID) {
- return "root";
- } else if (uid == Process.SHELL_UID) {
- return "com.android.shell";
- } else if (uid == Process.MEDIA_UID) {
- return "media";
- } else if (uid == Process.AUDIOSERVER_UID) {
- return "audioserver";
- } else if (uid == Process.CAMERASERVER_UID) {
- return "cameraserver";
- } else if (uid == Process.SYSTEM_UID && packageName == null) {
- return "android";
- }
- return packageName;
- }
-
private static int resolveUid(String packageName) {
if (packageName == null) {
return -1;
@@ -6455,6 +6665,7 @@
return Process.ROOT_UID;
case "shell":
case "dumpstate":
+ case "com.android.shell":
return Process.SHELL_UID;
case "media":
return Process.MEDIA_UID;
@@ -6831,5 +7042,29 @@
shouldCollectAsyncNotedOp, message, shouldCollectMessage,
AppOpsService.this::noteOperationImpl);
}
+
+ public int noteProxyOperationImpl(int code, @NonNull AttributionSource attributionSource,
+ boolean shouldCollectAsyncNotedOp, @Nullable String message,
+ boolean shouldCollectMessage, boolean skipProxyOperation) {
+ return mCheckOpsDelegate.noteProxyOperation(code, attributionSource,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation,
+ AppOpsService.this::noteProxyOperationImpl);
+ }
+
+ public int startProxyOperationImpl(IBinder token, int code,
+ @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ boolean skipProxyOperation) {
+ return mCheckOpsDelegate.startProxyOperation(token, code, attributionSource,
+ startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ skipProxyOperation, AppOpsService.this::startProxyOperationImpl);
+ }
+
+ public Void finishProxyOperationImpl(IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource) {
+ mCheckOpsDelegate.finishProxyOperation(clientId, code, attributionSource,
+ AppOpsService.this::finishProxyOperationImpl);
+ return null;
+ }
}
}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 68cfc23..f566080 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -38,6 +38,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.hardware.SensorPrivacyManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -115,6 +116,7 @@
private static String sTestAttentionServicePackage;
private final Context mContext;
private final PowerManager mPowerManager;
+ private final SensorPrivacyManager mPrivacyManager;
private final Object mLock;
@GuardedBy("mLock")
@VisibleForTesting
@@ -146,6 +148,7 @@
mPowerManager = powerManager;
mLock = lock;
mAttentionHandler = handler;
+ mPrivacyManager = SensorPrivacyManager.getInstance(context);
}
@Override
@@ -249,6 +252,11 @@
return false;
}
+ if (mPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA)) {
+ Slog.w(LOG_TAG, "Camera is locked by a toggle.");
+ return false;
+ }
+
// don't allow attention check in screen off state
if (!mPowerManager.isInteractive()) {
return false;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 88dca0c..282a12d 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -80,9 +80,12 @@
private final @NonNull AudioService mAudioService;
private final @NonNull Context mContext;
- /** Forced device usage for communications sent to AudioSystem */
- private AudioDeviceAttributes mPreferredCommunicationDevice;
+ /** ID for Communication strategy retrieved form audio policy manager */
private int mCommunicationStrategyId = -1;
+ /** Active communication device reported by audio policy manager */
+ private AudioDeviceInfo mActiveCommunicationDevice;
+ /** Last preferred device set for communication strategy */
+ private AudioDeviceAttributes mPreferredCommunicationDevice;
// Manages all connected devices, only ever accessed on the message loop
private final AudioDeviceInventory mDeviceInventory;
@@ -153,8 +156,9 @@
private void init() {
setupMessaging(mContext);
- mPreferredCommunicationDevice = null;
initCommunicationStrategyId();
+ mPreferredCommunicationDevice = null;
+ updateActiveCommunicationDevice();
mSystemServer.registerUserStartedReceiver(mContext);
}
@@ -300,7 +304,6 @@
+ " from API: " + eventSource)).printLog(TAG));
final boolean wasBtScoRequested = isBluetoothScoRequested();
- final boolean wasSpeakerphoneRequested = isSpeakerphoneRequested();
CommunicationRouteClient client;
@@ -341,16 +344,6 @@
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);
- }
- }
-
sendLMsgNoDelay(MSG_L_UPDATE_COMMUNICATION_ROUTE, SENDMSG_QUEUE, eventSource);
}
@@ -386,66 +379,119 @@
* Returns the device currently requested for communication use case.
* @return AudioDeviceInfo the requested device for communication.
*/
- AudioDeviceInfo getCommunicationDevice() {
+ /* package */ AudioDeviceInfo getCommunicationDevice() {
synchronized (mDeviceStateLock) {
- AudioDeviceAttributes device = requestedCommunicationDevice();
- if (device == null) {
- AudioAttributes attr =
- AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(
- AudioSystem.STREAM_VOICE_CALL);
- List<AudioDeviceAttributes> devices = AudioSystem.getDevicesForAttributes(attr);
- if (devices.isEmpty()) {
- if (mAudioService.isPlatformVoice()) {
- Log.w(TAG, "getCommunicationDevice(): no device for phone strategy");
- }
- return null;
- }
- device = devices.get(0);
- }
- return AudioManager.getDeviceInfoFromTypeAndAddress(
- device.getType(), device.getAddress());
+ updateActiveCommunicationDevice();
+ return mActiveCommunicationDevice;
}
}
/**
- * Helper method on top of requestedCommunicationDevice() indicating if
+ * Updates currently active communication device (mActiveCommunicationDevice).
+ */
+ @GuardedBy("mDeviceStateLock")
+ void updateActiveCommunicationDevice() {
+ AudioDeviceAttributes device = preferredCommunicationDevice();
+ if (device == null) {
+ AudioAttributes attr =
+ AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(
+ AudioSystem.STREAM_VOICE_CALL);
+ List<AudioDeviceAttributes> devices = AudioSystem.getDevicesForAttributes(attr);
+ if (devices.isEmpty()) {
+ if (mAudioService.isPlatformVoice()) {
+ Log.w(TAG,
+ "updateActiveCommunicationDevice(): no device for phone strategy");
+ }
+ mActiveCommunicationDevice = null;
+ return;
+ }
+ device = devices.get(0);
+ }
+ mActiveCommunicationDevice = AudioManager.getDeviceInfoFromTypeAndAddress(
+ device.getType(), device.getAddress());
+ }
+
+ /**
+ * Indicates if the device which type is passed as argument is currently resquested to be used
+ * for communication.
+ * @param deviceType the device type the query applies to.
+ * @return true if this device type is requested for communication.
+ */
+ private boolean isDeviceRequestedForCommunication(int deviceType) {
+ synchronized (mDeviceStateLock) {
+ AudioDeviceAttributes device = requestedCommunicationDevice();
+ return device != null && device.getType() == deviceType;
+ }
+ }
+
+ /**
+ * Indicates if the device which type is passed as argument is currently either resquested
+ * to be used for communication or selected for an other reason (e.g bluetooth SCO audio
+ * is active for SCO device).
+ * @param deviceType the device type the query applies to.
+ * @return true if this device type is requested for communication.
+ */
+ private boolean isDeviceOnForCommunication(int deviceType) {
+ synchronized (mDeviceStateLock) {
+ AudioDeviceAttributes device = preferredCommunicationDevice();
+ return device != null && device.getType() == deviceType;
+ }
+ }
+
+ /**
+ * Indicates if the device which type is passed as argument is active for communication.
+ * Active means not only currently used by audio policy manager for communication strategy
+ * but also explicitly requested for use by communication strategy.
+ * @param deviceType the device type the query applies to.
+ * @return true if this device type is requested for communication.
+ */
+ private boolean isDeviceActiveForCommunication(int deviceType) {
+ return mActiveCommunicationDevice != null
+ && mActiveCommunicationDevice.getType() == deviceType
+ && mPreferredCommunicationDevice != null
+ && mPreferredCommunicationDevice.getType() == deviceType;
+ }
+
+ /**
+ * Helper method on top of isDeviceRequestedForCommunication() indicating if
* speakerphone ON is currently requested or not.
* @return true if speakerphone ON requested, false otherwise.
*/
-
private boolean isSpeakerphoneRequested() {
- synchronized (mDeviceStateLock) {
- AudioDeviceAttributes device = requestedCommunicationDevice();
- return device != null
- && device.getType()
- == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER;
- }
+ return isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
}
/**
- * Indicates if active route selection for communication is speakerphone.
+ * Indicates if preferred route selection for communication is speakerphone.
* @return true if speakerphone is active, false otherwise.
*/
/*package*/ boolean isSpeakerphoneOn() {
- AudioDeviceAttributes device = getPreferredCommunicationDevice();
- if (device == null) {
- return false;
- }
- return device.getInternalType() == AudioSystem.DEVICE_OUT_SPEAKER;
+ return isDeviceOnForCommunication(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
+ }
+
+ private boolean isSpeakerphoneActive() {
+ return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
}
/**
- * Helper method on top of requestedCommunicationDevice() indicating if
+ * Helper method on top of isDeviceRequestedForCommunication() 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;
- }
+ return isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
+ }
+
+ /**
+ * Indicates if preferred route selection for communication is Bluetooth SCO.
+ * @return true if Bluetooth SCO is preferred , false otherwise.
+ */
+ /*package*/ boolean isBluetoothScoOn() {
+ return isDeviceOnForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
+ }
+
+ /*package*/ boolean isBluetoothScoActive() {
+ return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
}
/*package*/ void setWiredDeviceConnectionState(int type,
@@ -593,18 +639,6 @@
}
}
- /**
- * Indicates if active route selection for communication is Bluetooth SCO.
- * @return true if Bluetooth SCO is active , false otherwise.
- */
- /*package*/ boolean isBluetoothScoOn() {
- AudioDeviceAttributes device = getPreferredCommunicationDevice();
- if (device == null) {
- return false;
- }
- return AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(device.getInternalType());
- }
-
/*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
synchronized (mDeviceStateLock) {
return mDeviceInventory.startWatchingRoutes(observer);
@@ -748,8 +782,8 @@
@GuardedBy("mDeviceStateLock")
private void dispatchCommunicationDevice() {
- AudioDeviceInfo device = getCommunicationDevice();
- int portId = (device == null) ? 0 : device.getId();
+ int portId = (mActiveCommunicationDevice == null) ? 0
+ : mActiveCommunicationDevice.getId();
if (portId == mCurCommunicationPortId) {
return;
}
@@ -1022,12 +1056,13 @@
pw.println(" " + prefix + "pid: " + cl.getPid() + " device: "
+ cl.getDevice() + " cb: " + cl.getBinder()); });
- pw.println("\n" + prefix + "mPreferredCommunicationDevice: "
+ pw.println("\n" + prefix + "Computed Preferred communication device: "
+ + preferredCommunicationDevice());
+ pw.println("\n" + prefix + "Applied Preferred communication device: "
+ mPreferredCommunicationDevice);
-
- AudioDeviceInfo device = getCommunicationDevice();
- pw.println(prefix + "Selected Communication Device: "
- + ((device == null) ? "None" : new AudioDeviceAttributes(device)));
+ pw.println(prefix + "Active communication device: "
+ + ((mActiveCommunicationDevice == null) ? "None"
+ : new AudioDeviceAttributes(mActiveCommunicationDevice)));
pw.println(prefix + "mCommunicationStrategyId: "
+ mCommunicationStrategyId);
@@ -1128,6 +1163,7 @@
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
initCommunicationStrategyId();
+ updateActiveCommunicationDevice();
mDeviceInventory.onRestoreDevices();
mBtHelper.onAudioServerDiedRestoreA2dp();
onUpdateCommunicationRoute("MSG_RESTORE_DEVICES");
@@ -1340,11 +1376,16 @@
final List<AudioDeviceAttributes> devices =
(List<AudioDeviceAttributes>) msg.obj;
setPreferredDevicesForStrategySync(strategy, devices);
-
+ if (strategy == mCommunicationStrategyId) {
+ onUpdatePhoneStrategyDevice(devices.isEmpty() ? null : devices.get(0));
+ }
} break;
case MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY: {
final int strategy = msg.arg1;
removePreferredDevicesForStrategySync(strategy);
+ if (strategy == mCommunicationStrategyId) {
+ onUpdatePhoneStrategyDevice(null);
+ }
} break;
case MSG_CHECK_MUTE_MUSIC:
checkMessagesMuteMusic(0);
@@ -1672,14 +1713,14 @@
}
/**
- * Determines which forced usage for communication should be sent to audio policy manager
+ * Determines which preferred device for phone strategy 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")
- @Nullable private AudioDeviceAttributes getPreferredCommunicationDevice() {
+ @Nullable private AudioDeviceAttributes preferredCommunicationDevice() {
boolean btSCoOn = mBluetoothScoOn && mBtHelper.isBluetoothScoOn();
if (btSCoOn) {
// Use the SCO device known to BtHelper so that it matches exactly
@@ -1692,8 +1733,7 @@
}
}
AudioDeviceAttributes device = requestedCommunicationDevice();
- if (device == null
- || AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(device.getInternalType())) {
+ if (device == null || device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
// Do not indicate BT SCO selection if SCO is requested but SCO is not ON
return null;
}
@@ -1707,30 +1747,49 @@
// @GuardedBy("mSetModeLock")
@GuardedBy("mDeviceStateLock")
private void onUpdateCommunicationRoute(String eventSource) {
- mPreferredCommunicationDevice = getPreferredCommunicationDevice();
+ AudioDeviceAttributes preferredCommunicationDevice = preferredCommunicationDevice();
if (AudioService.DEBUG_COMM_RTE) {
- Log.v(TAG, "onUpdateCommunicationRoute, mPreferredCommunicationDevice: "
- + mPreferredCommunicationDevice + " eventSource: " + eventSource);
+ Log.v(TAG, "onUpdateCommunicationRoute, preferredCommunicationDevice: "
+ + preferredCommunicationDevice + " eventSource: " + eventSource);
}
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
- "onUpdateCommunicationRoute, mPreferredCommunicationDevice: "
- + mPreferredCommunicationDevice + " eventSource: " + eventSource)));
+ "onUpdateCommunicationRoute, preferredCommunicationDevice: "
+ + preferredCommunicationDevice + " eventSource: " + eventSource)));
- if (mPreferredCommunicationDevice == null
- || !AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(
- mPreferredCommunicationDevice.getInternalType())) {
+ if (preferredCommunicationDevice == null
+ || preferredCommunicationDevice.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
AudioSystem.setParameters("BT_SCO=off");
} else {
AudioSystem.setParameters("BT_SCO=on");
}
- if (mPreferredCommunicationDevice == null) {
+ if (preferredCommunicationDevice == null) {
postRemovePreferredDevicesForStrategy(mCommunicationStrategyId);
} else {
postSetPreferredDevicesForStrategy(
- mCommunicationStrategyId, Arrays.asList(mPreferredCommunicationDevice));
+ mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice));
}
- mAudioService.postUpdateRingerModeServiceInt();
- dispatchCommunicationDevice();
+ }
+
+ private void onUpdatePhoneStrategyDevice(AudioDeviceAttributes device) {
+ synchronized (mSetModeLock) {
+ synchronized (mDeviceStateLock) {
+ boolean wasSpeakerphoneActive = isSpeakerphoneActive();
+ mPreferredCommunicationDevice = device;
+ updateActiveCommunicationDevice();
+ if (wasSpeakerphoneActive != isSpeakerphoneActive()) {
+ 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);
+ }
+ }
+ mAudioService.postUpdateRingerModeServiceInt();
+ dispatchCommunicationDevice();
+ }
+ }
}
private CommunicationRouteClient removeCommunicationRouteClient(
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 148c723..16a9626 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4192,7 +4192,7 @@
final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
|| ringerMode == AudioManager.RINGER_MODE_SILENT;
final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE
- && mDeviceBroker.isBluetoothScoOn();
+ && mDeviceBroker.isBluetoothScoActive();
// Ask audio policy engine to force use Bluetooth SCO channel if needed
final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()
+ "/" + Binder.getCallingPid();
@@ -5600,7 +5600,7 @@
switch (mPlatformType) {
case AudioSystem.PLATFORM_VOICE:
if (isInCommunication()) {
- if (mDeviceBroker.isBluetoothScoOn()) {
+ if (mDeviceBroker.isBluetoothScoActive()) {
// Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
return AudioSystem.STREAM_BLUETOOTH_SCO;
} else {
@@ -5636,7 +5636,7 @@
}
default:
if (isInCommunication()) {
- if (mDeviceBroker.isBluetoothScoOn()) {
+ if (mDeviceBroker.isBluetoothScoActive()) {
if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
return AudioSystem.STREAM_BLUETOOTH_SCO;
} else {
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 63e7b4b..70f26ac 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -766,15 +766,18 @@
public long[] getAuthenticatorIds(int callingUserId) {
checkInternalPermission();
- final List<Long> ids = new ArrayList<>();
+ final List<Long> authenticatorIds = new ArrayList<>();
for (BiometricSensor sensor : mSensors) {
try {
- final long id = sensor.impl.getAuthenticatorId(callingUserId);
- if (Utils.isAtLeastStrength(sensor.getCurrentStrength(),
- Authenticators.BIOMETRIC_STRONG) && id != 0) {
- ids.add(id);
+ final boolean hasEnrollments = sensor.impl.hasEnrolledTemplates(callingUserId,
+ getContext().getOpPackageName());
+ final long authenticatorId = sensor.impl.getAuthenticatorId(callingUserId);
+ if (hasEnrollments && Utils.isAtLeastStrength(sensor.getCurrentStrength(),
+ Authenticators.BIOMETRIC_STRONG)) {
+ authenticatorIds.add(authenticatorId);
} else {
- Slog.d(TAG, "Sensor " + sensor + ", sensorId " + id
+ Slog.d(TAG, "Sensor " + sensor + ", sensorId " + sensor.id
+ + ", hasEnrollments: " + hasEnrollments
+ " cannot participate in Keystore operations");
}
} catch (RemoteException e) {
@@ -782,9 +785,9 @@
}
}
- long[] result = new long[ids.size()];
- for (int i = 0; i < ids.size(); i++) {
- result[i] = ids.get(i);
+ long[] result = new long[authenticatorIds.size()];
+ for (int i = 0; i < authenticatorIds.size(); i++) {
+ result[i] = authenticatorIds.get(i);
}
return result;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
index 8197edc..383efce 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
@@ -65,12 +65,10 @@
}
@Override
- public void onRemoved(@Nullable BiometricAuthenticator.Identifier identifier, int remaining) {
+ public void onRemoved(@NonNull BiometricAuthenticator.Identifier identifier, int remaining) {
Slog.d(TAG, "onRemoved: " + identifier.getBiometricId() + " remaining: " + remaining);
- if (identifier != null) {
- mBiometricUtils.removeBiometricForUser(getContext(), getTargetUserId(),
- identifier.getBiometricId());
- }
+ mBiometricUtils.removeBiometricForUser(getContext(), getTargetUserId(),
+ identifier.getBiometricId());
try {
if (getListener() != null) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index d10fd4f..34a86d3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -36,6 +36,7 @@
import android.hardware.biometrics.face.SensorProps;
import android.hardware.face.Face;
import android.hardware.face.FaceSensorPropertiesInternal;
+import android.hardware.face.FaceServiceReceiver;
import android.hardware.face.IFaceService;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
@@ -166,12 +167,7 @@
String opPackageName) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
- final List<FaceSensorPropertiesInternal> properties =
- FaceService.this.getSensorProperties();
-
- Slog.d(TAG, "Retrieved sensor properties for: " + opPackageName
- + ", sensors: " + properties.size());
- return properties;
+ return FaceService.this.getSensorProperties();
}
@Override // Binder call
@@ -394,10 +390,29 @@
final IFaceServiceReceiver receiver, final String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
+ final FaceServiceReceiver internalReceiver = new FaceServiceReceiver() {
+ int sensorsFinishedRemoving = 0;
+ final int numSensors = getSensorPropertiesInternal(
+ getContext().getOpPackageName()).size();
+ @Override
+ public void onRemoved(Face face, int remaining) throws RemoteException {
+ if (remaining == 0) {
+ sensorsFinishedRemoving++;
+ Slog.d(TAG, "sensorsFinishedRemoving: " + sensorsFinishedRemoving
+ + ", numSensors: " + numSensors);
+ if (sensorsFinishedRemoving == numSensors) {
+ receiver.onRemoved(null, 0 /* remaining */);
+ }
+ }
+ }
+ };
+
+ // This effectively iterates through all sensors, but has to do so by finding all
+ // sensors under each provider.
for (ServiceProvider provider : mServiceProviders) {
List<FaceSensorPropertiesInternal> props = provider.getSensorProperties();
for (FaceSensorPropertiesInternal prop : props) {
- provider.scheduleRemoveAll(prop.sensorId, token, userId, receiver,
+ provider.scheduleRemoveAll(prop.sensorId, token, userId, internalReceiver,
opPackageName);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 79e361f..4ffbe06 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -398,7 +398,7 @@
private synchronized IBiometricsFace getDaemon() {
if (mTestHalEnabled) {
- final TestHal testHal = new TestHal();
+ final TestHal testHal = new TestHal(mContext, mSensorId);
testHal.setCallback(mHalResultController);
return testHal;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java
index 84aa6d9..d9408599 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java
@@ -16,23 +16,40 @@
package com.android.server.biometrics.sensors.face.hidl;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
import android.hardware.biometrics.face.V1_0.FaceError;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
import android.hardware.biometrics.face.V1_0.OptionalBool;
import android.hardware.biometrics.face.V1_0.OptionalUint64;
import android.hardware.biometrics.face.V1_0.Status;
+import android.hardware.face.Face;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.sensors.face.FaceUtils;
+
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
public class TestHal extends IBiometricsFace.Stub {
private static final String TAG = "face.hidl.TestHal";
+
+ @NonNull
+ private final Context mContext;
+ private final int mSensorId;
+
@Nullable
private IBiometricsFaceClientCallback mCallback;
+ private int mUserId;
+
+ TestHal(@NonNull Context context, int sensorId) {
+ mContext = context;
+ mSensorId = sensorId;
+ }
@Override
public OptionalUint64 setCallback(IBiometricsFaceClientCallback clientCallback) {
@@ -44,6 +61,7 @@
@Override
public int setActiveUser(int userId, String storePath) {
+ mUserId = userId;
return 0;
}
@@ -110,8 +128,20 @@
public int remove(int faceId) throws RemoteException {
Slog.w(TAG, "remove");
if (mCallback != null) {
- mCallback.onRemoved(0 /* deviceId */, new ArrayList<Integer>(Arrays.asList(faceId)),
- 0 /* userId */);
+ if (faceId == 0) {
+ // For this HAL interface, remove(0) means to remove all enrollments.
+ final List<Face> faces = FaceUtils.getInstance(mSensorId)
+ .getBiometricsForUser(mContext, mUserId);
+ final ArrayList<Integer> faceIds = new ArrayList<>();
+ for (Face face : faces) {
+ faceIds.add(face.getBiometricId());
+ }
+ mCallback.onRemoved(0 /* deviceId */, faceIds, mUserId);
+ } else {
+ mCallback.onRemoved(0 /* deviceId */,
+ new ArrayList<>(Collections.singletonList(faceId)),
+ mUserId);
+ }
}
return 0;
}
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 e4397fd..cbef6609 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
@@ -49,6 +49,7 @@
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.FingerprintServiceReceiver;
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
import android.hardware.fingerprint.IFingerprintService;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
@@ -145,12 +146,7 @@
Utils.checkPermission(getContext(), TEST_BIOMETRIC);
}
- final List<FingerprintSensorPropertiesInternal> properties =
- FingerprintService.this.getSensorProperties();
-
- Slog.d(TAG, "Retrieved sensor properties for: " + opPackageName
- + ", sensors: " + properties.size());
- return properties;
+ return FingerprintService.this.getSensorProperties();
}
@Override
@@ -505,12 +501,31 @@
@Override // Binder call
public void removeAll(final IBinder token, final int userId,
final IFingerprintServiceReceiver receiver, final String opPackageName) {
- Utils.checkPermission(getContext(), MANAGE_FINGERPRINT);
+ Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
+ final FingerprintServiceReceiver internalReceiver = new FingerprintServiceReceiver() {
+ int sensorsFinishedRemoving = 0;
+ final int numSensors = getSensorPropertiesInternal(
+ getContext().getOpPackageName()).size();
+ @Override
+ public void onRemoved(Fingerprint fp, int remaining) throws RemoteException {
+ if (remaining == 0) {
+ sensorsFinishedRemoving++;
+ Slog.d(TAG, "sensorsFinishedRemoving: " + sensorsFinishedRemoving
+ + ", numSensors: " + numSensors);
+ if (sensorsFinishedRemoving == numSensors) {
+ receiver.onRemoved(null, 0 /* remaining */);
+ }
+ }
+ }
+ };
+
+ // This effectively iterates through all sensors, but has to do so by finding all
+ // sensors under each provider.
for (ServiceProvider provider : mServiceProviders) {
List<FingerprintSensorPropertiesInternal> props = provider.getSensorProperties();
for (FingerprintSensorPropertiesInternal prop : props) {
- provider.scheduleRemoveAll(prop.sensorId, token, receiver, userId,
+ provider.scheduleRemoveAll(prop.sensorId, token, internalReceiver, userId,
opPackageName);
}
}
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 f2992cc..e149ca9 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
@@ -402,7 +402,7 @@
@VisibleForTesting
synchronized IBiometricsFingerprint getDaemon() {
if (mTestHalEnabled) {
- final TestHal testHal = new TestHal();
+ final TestHal testHal = new TestHal(mContext, mSensorId);
testHal.setNotify(mHalResultController);
return testHal;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java
index 129f6a6..986e92e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java
@@ -16,22 +16,38 @@
package com.android.server.biometrics.sensors.fingerprint.hidl;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
import android.hardware.biometrics.fingerprint.V2_1.FingerprintError;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback;
import android.hardware.biometrics.fingerprint.V2_3.IBiometricsFingerprint;
+import android.hardware.fingerprint.Fingerprint;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
+
+import java.util.List;
+
/**
* Test HAL that provides only provides no-ops.
*/
public class TestHal extends IBiometricsFingerprint.Stub {
private static final String TAG = "fingerprint.hidl.TestHal";
+ @NonNull
+ private final Context mContext;
+ private final int mSensorId;
+
@Nullable
private IBiometricsFingerprintClientCallback mCallback;
+ TestHal(@NonNull Context context, int sensorId) {
+ mContext = context;
+ mSensorId = sensorId;
+ }
+
@Override
public boolean isUdfps(int sensorId) {
return false;
@@ -96,7 +112,18 @@
public int remove(int gid, int fid) throws RemoteException {
Slog.w(TAG, "Remove");
if (mCallback != null) {
- mCallback.onRemoved(0 /* deviceId */, fid, gid, 0 /* remaining */);
+ if (fid == 0) {
+ // For this HAL interface, remove(0) means to remove all enrollments.
+ final List<Fingerprint> fingerprints = FingerprintUtils.getInstance(mSensorId)
+ .getBiometricsForUser(mContext, gid);
+ for (int i = 0; i < fingerprints.size(); i++) {
+ final Fingerprint fp = fingerprints.get(i);
+ mCallback.onRemoved(0 /* deviceId */, fp.getBiometricId(), gid,
+ fingerprints.size() - i - 1);
+ }
+ } else {
+ mCallback.onRemoved(0 /* deviceId */, fid, gid, 0 /* remaining */);
+ }
}
return 0;
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index b31fa70..d16a2de 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -201,6 +201,9 @@
// Set to true when partial connectivity was detected.
public boolean partialConnectivity;
+ // Delay between when the network is disconnected and when the native network is destroyed.
+ public int teardownDelayMs;
+
// Captive portal info of the network from RFC8908, if any.
// Obtained by ConnectivityService and merged into NetworkAgent-provided information.
public CaptivePortalData capportApiData;
@@ -589,13 +592,13 @@
}
/**
- * Notify the NetworkAgent that the network is disconnected and destroyed.
+ * Notify the NetworkAgent that the native network has been destroyed.
*/
- public void onNetworkDisconnected() {
+ public void onNetworkDestroyed() {
try {
- networkAgent.onNetworkDisconnected();
+ networkAgent.onNetworkDestroyed();
} catch (RemoteException e) {
- Log.e(TAG, "Error sending network disconnected event", e);
+ Log.e(TAG, "Error sending network destroyed event", e);
}
}
@@ -675,6 +678,12 @@
@QosCallbackException.ExceptionType final int exceptionType) {
mQosCallbackTracker.sendEventQosCallbackError(qosCallbackId, exceptionType);
}
+
+ @Override
+ public void sendTeardownDelayMs(int teardownDelayMs) {
+ mHandler.obtainMessage(NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED,
+ teardownDelayMs, 0, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
+ }
}
/**
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a070f27..820198c 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -464,7 +464,7 @@
.addTransportType(NetworkCapabilities.TRANSPORT_VPN)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
- .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE))
+ .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE, null))
.build();
loadAlwaysOnPackage();
@@ -528,7 +528,7 @@
private void resetNetworkCapabilities() {
mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
.setUids(null)
- .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE))
+ .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE, null))
.build();
}
@@ -1259,7 +1259,7 @@
capsBuilder.setUids(createUserAndRestrictedProfilesRanges(mUserId,
mConfig.allowedApplications, mConfig.disallowedApplications));
- capsBuilder.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
+ capsBuilder.setTransportInfo(new VpnTransportInfo(getActiveVpnType(), mConfig.session));
// Only apps targeting Q and above can explicitly declare themselves as metered.
// These VPNs are assumed metered unless they state otherwise.
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 30cbf27..74a21a7 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -433,9 +433,8 @@
}
private float permissibleRatio(float currLux, float prevLux) {
- return MathUtils.exp(MAX_GRAD
- * (MathUtils.log(currLux + LUX_GRAD_SMOOTHING)
- - MathUtils.log(prevLux + LUX_GRAD_SMOOTHING)));
+ return MathUtils.pow((currLux + LUX_GRAD_SMOOTHING)
+ / (prevLux + LUX_GRAD_SMOOTHING), MAX_GRAD);
}
protected float inferAutoBrightnessAdjustment(float maxGamma, float desiredBrightness,
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 4b84ba0..393a4eb 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2478,6 +2478,11 @@
}
@Override // Binder call
+ public int[] getUserDisabledHdrTypes() {
+ return mUserDisabledHdrTypes;
+ }
+
+ @Override // Binder call
public void requestColorMode(int displayId, int colorMode) {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
@@ -2927,9 +2932,6 @@
@Override // Binder call
public int getRefreshRateSwitchingType() {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
- "Permission required read refresh rate switching type.");
final long token = Binder.clearCallingIdentity();
try {
return getRefreshRateSwitchingTypeInternal();
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 56ad01b..cb8541e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -874,6 +874,10 @@
private void cleanupHandlerThreadAfterStop() {
setProximitySensorEnabled(false);
mHandler.removeCallbacksAndMessages(null);
+ if (mUnfinishedBusiness) {
+ mCallbacks.releaseSuspendBlocker();
+ mUnfinishedBusiness = false;
+ }
if (mPowerState != null) {
mPowerState.stop();
mPowerState = null;
@@ -1701,12 +1705,7 @@
}
}
- private final Runnable mCleanListener = new Runnable() {
- @Override
- public void run() {
- sendUpdatePowerState();
- }
- };
+ private final Runnable mCleanListener = this::sendUpdatePowerState;
private void setProximitySensorEnabled(boolean enable) {
if (enable) {
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 88b2668..7fa0b21 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -630,8 +630,12 @@
if (mCurrentUser == UserHandle.USER_NULL) {
return;
}
- final int strength = Secure.getIntForUser(getContext().getContentResolver(),
- Secure.REDUCE_BRIGHT_COLORS_LEVEL, 0, mCurrentUser);
+ int strength = Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.REDUCE_BRIGHT_COLORS_LEVEL, NOT_SET, mCurrentUser);
+ if (strength == NOT_SET) {
+ strength = getContext().getResources().getInteger(
+ R.integer.config_reduceBrightColorsStrengthDefault);
+ }
mReduceBrightColorsTintController.setMatrix(strength);
if (mReduceBrightColorsListener != null) {
mReduceBrightColorsListener.onReduceBrightColorsStrengthChanged(strength);
diff --git a/services/core/java/com/android/server/graphics/fonts/PersistentSystemFontConfig.java b/services/core/java/com/android/server/graphics/fonts/PersistentSystemFontConfig.java
index 62337c7..15abbd5 100644
--- a/services/core/java/com/android/server/graphics/fonts/PersistentSystemFontConfig.java
+++ b/services/core/java/com/android/server/graphics/fonts/PersistentSystemFontConfig.java
@@ -17,8 +17,7 @@
package com.android.server.graphics.fonts;
import android.annotation.NonNull;
-import android.graphics.FontListParser;
-import android.text.FontConfig;
+import android.graphics.fonts.FontUpdateRequest;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Slog;
@@ -48,7 +47,7 @@
/* package */ static class Config {
public long lastModifiedMillis;
public final Set<String> updatedFontDirs = new ArraySet<>();
- public final List<FontConfig.FontFamily> fontFamilies = new ArrayList<>();
+ public final List<FontUpdateRequest.Family> fontFamilies = new ArrayList<>();
}
/**
@@ -81,8 +80,8 @@
case TAG_FAMILY:
// updatableFontMap is not ready here. We get the base file names by passing
// empty fontDir, and resolve font paths later.
- out.fontFamilies.add(FontListParser.readFamily(
- parser, "" /* fontDir */, null /* updatableFontMap */));
+ out.fontFamilies.add(FontUpdateRequest.Family.readFromXml(parser));
+ break;
default:
Slog.w(TAG, "Skipping unknown tag: " + tag);
}
@@ -108,11 +107,11 @@
out.attribute(null, ATTR_VALUE, dir);
out.endTag(null, TAG_UPDATED_FONT_DIR);
}
- List<FontConfig.FontFamily> fontFamilies = config.fontFamilies;
+ List<FontUpdateRequest.Family> fontFamilies = config.fontFamilies;
for (int i = 0; i < fontFamilies.size(); i++) {
- FontConfig.FontFamily fontFamily = fontFamilies.get(i);
+ FontUpdateRequest.Family fontFamily = fontFamilies.get(i);
out.startTag(null, TAG_FAMILY);
- FontListParser.writeFamily(out, fontFamily);
+ FontUpdateRequest.Family.writeFamilyToXml(out, fontFamily);
out.endTag(null, TAG_FAMILY);
}
out.endTag(null, TAG_ROOT);
diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
index 7518130..3e6ddc3 100644
--- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
+++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
@@ -31,8 +31,6 @@
import android.util.Base64;
import android.util.Slog;
-import com.android.internal.annotations.VisibleForTesting;
-
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
@@ -42,9 +40,9 @@
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.function.Supplier;
/**
@@ -97,6 +95,11 @@
public long getRevision() {
return mRevision;
}
+
+ @Override
+ public String toString() {
+ return "FontFileInfo{mFile=" + mFile + ", mRevision=" + mRevision + '}';
+ }
}
/**
@@ -121,12 +124,6 @@
*/
private final ArrayMap<String, FontFileInfo> mFontFileInfoMap = new ArrayMap<>();
- /**
- * A mutable map containing mapping from font family name to {@link FontConfig.FontFamily}.
- * The FontFamily entries only reference font files in {@link #mFontFileInfoMap}.
- */
- private final ArrayMap<String, FontConfig.FontFamily> mFontFamilyMap = new ArrayMap<>();
-
UpdatableFontDir(File filesDir, List<File> preinstalledFontDirs, FontFileParser parser,
FsverityUtil fsverityUtil) {
this(filesDir, preinstalledFontDirs, parser, fsverityUtil, new File(CONFIG_XML_FILE),
@@ -147,7 +144,6 @@
/* package */ void loadFontFileMap() {
mFontFileInfoMap.clear();
- mFontFamilyMap.clear();
mLastModifiedMillis = 0;
boolean success = false;
try {
@@ -155,7 +151,7 @@
try (FileInputStream fis = new FileInputStream(mConfigFile)) {
PersistentSystemFontConfig.loadFromXml(fis, config);
} catch (IOException | XmlPullParserException e) {
- Slog.e(TAG, "Failed to load config xml file", e);
+ // The font config file is missing on the first boot. Just do nothing.
return;
}
mLastModifiedMillis = config.lastModifiedMillis;
@@ -180,17 +176,6 @@
FontFileInfo fontFileInfo = validateFontFile(files[0]);
addFileToMapIfNewer(fontFileInfo, true /* deleteOldFile */);
}
- // Resolve font file paths.
- List<FontConfig.FontFamily> fontFamilies = config.fontFamilies;
- for (int i = 0; i < fontFamilies.size(); i++) {
- FontConfig.FontFamily fontFamily = fontFamilies.get(i);
- try {
- addFontFamily(fontFamily);
- } catch (SystemFontException e) {
- // Ignore failures as updated fonts may be obsoleted by system OTA update.
- Slog.i(TAG, "Obsolete font family: " + fontFamily.getName());
- }
- }
success = true;
} catch (Throwable t) {
// If something happened during loading system fonts, clear all contents in finally
@@ -200,7 +185,6 @@
// Delete all files just in case if we find a problematic file.
if (!success) {
mFontFileInfoMap.clear();
- mFontFamilyMap.clear();
mLastModifiedMillis = 0;
FileUtils.deleteContents(mFilesDir);
}
@@ -210,11 +194,12 @@
/* package */ void clearUpdates() throws SystemFontException {
mFontFileInfoMap.clear();
FileUtils.deleteContents(mFilesDir);
- mFontFamilyMap.clear();
mLastModifiedMillis = mCurrentTimeSupplier.get();
try (FileOutputStream fos = new FileOutputStream(mConfigFile)) {
- PersistentSystemFontConfig.writeToXml(fos, createPersistentConfig());
+ PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
+ config.lastModifiedMillis = mLastModifiedMillis;
+ PersistentSystemFontConfig.writeToXml(fos, config);
} catch (Exception e) {
throw new SystemFontException(
FontManager.RESULT_ERROR_FAILED_UPDATE_CONFIG,
@@ -231,7 +216,13 @@
public void update(List<FontUpdateRequest> requests) throws SystemFontException {
// Backup the mapping for rollback.
ArrayMap<String, FontFileInfo> backupMap = new ArrayMap<>(mFontFileInfoMap);
- ArrayMap<String, FontConfig.FontFamily> backupFamilies = new ArrayMap<>(mFontFamilyMap);
+ PersistentSystemFontConfig.Config curConfig = readPersistentConfig();
+ Map<String, FontUpdateRequest.Family> familyMap = new HashMap<>();
+ for (int i = 0; i < curConfig.fontFamilies.size(); ++i) {
+ FontUpdateRequest.Family family = curConfig.fontFamilies.get(i);
+ familyMap.put(family.getName(), family);
+ }
+
long backupLastModifiedDate = mLastModifiedMillis;
boolean success = false;
try {
@@ -242,15 +233,33 @@
request.getFd().getFileDescriptor(), request.getSignature());
break;
case FontUpdateRequest.TYPE_UPDATE_FONT_FAMILY:
- addFontFamily(request.getFontFamily());
+ FontUpdateRequest.Family family = request.getFontFamily();
+ familyMap.put(family.getName(), family);
break;
}
}
+ // Before processing font family update, check all family points the available fonts.
+ for (FontUpdateRequest.Family family : familyMap.values()) {
+ if (resolveFontFiles(family) == null) {
+ throw new SystemFontException(
+ FontManager.RESULT_ERROR_FONT_NOT_FOUND,
+ "Required fonts are not available");
+ }
+ }
+
// Write config file.
mLastModifiedMillis = mCurrentTimeSupplier.get();
+
+ curConfig.lastModifiedMillis = mLastModifiedMillis;
+ for (FontFileInfo info : mFontFileInfoMap.values()) {
+ curConfig.updatedFontDirs.add(info.getRandomizedFontDir().getName());
+ }
+ curConfig.fontFamilies.clear();
+ curConfig.fontFamilies.addAll(familyMap.values());
+
try (FileOutputStream fos = new FileOutputStream(mTmpConfigFile)) {
- PersistentSystemFontConfig.writeToXml(fos, createPersistentConfig());
+ PersistentSystemFontConfig.writeToXml(fos, curConfig);
} catch (Exception e) {
throw new SystemFontException(
FontManager.RESULT_ERROR_FAILED_UPDATE_CONFIG,
@@ -268,8 +277,6 @@
if (!success) {
mFontFileInfoMap.clear();
mFontFileInfoMap.putAll(backupMap);
- mFontFamilyMap.clear();
- mFontFamilyMap.putAll(backupFamilies);
mLastModifiedMillis = backupLastModifiedDate;
}
}
@@ -511,50 +518,22 @@
}
}
- /**
- * Adds a font family to {@link #mFontFamilyMap} and returns true on success.
- *
- * <p>This method only accepts adding or updating a font family with a name.
- * This is to prevent bad font family update from removing glyphs from font fallback chains.
- * Unnamed font families are used as other named font family's fallback fonts to guarantee a
- * complete glyph coverage.
- */
- private void addFontFamily(FontConfig.FontFamily fontFamily) throws SystemFontException {
- Objects.requireNonNull(fontFamily.getName());
- FontConfig.FontFamily resolvedFontFamily = resolveFontFiles(fontFamily);
- if (resolvedFontFamily == null) {
- throw new SystemFontException(
- FontManager.RESULT_ERROR_FONT_NOT_FOUND,
- "Required fonts are not available");
- }
- mFontFamilyMap.put(resolvedFontFamily.getName(), resolvedFontFamily);
- }
-
@Nullable
- private FontConfig.FontFamily resolveFontFiles(FontConfig.FontFamily fontFamily) {
- List<FontConfig.Font> resolvedFonts = new ArrayList<>(fontFamily.getFontList().size());
- List<FontConfig.Font> fontList = fontFamily.getFontList();
+ private FontConfig.FontFamily resolveFontFiles(FontUpdateRequest.Family fontFamily) {
+ List<FontUpdateRequest.Font> fontList = fontFamily.getFonts();
+ List<FontConfig.Font> resolvedFonts = new ArrayList<>(fontList.size());
for (int i = 0; i < fontList.size(); i++) {
- FontConfig.Font font = fontList.get(i);
- FontFileInfo info = lookupFontFileInfo(font.getFile());
+ FontUpdateRequest.Font font = fontList.get(i);
+ FontFileInfo info = mFontFileInfoMap.get(font.getPostScriptName());
if (info == null) {
+ Slog.e(TAG, "Failed to lookup font file that has " + font.getPostScriptName());
return null;
}
- resolvedFonts.add(new FontConfig.Font(info.mFile, null, font.getStyle(),
- font.getTtcIndex(), font.getFontVariationSettings(), font.getFontFamilyName()));
+ resolvedFonts.add(new FontConfig.Font(info.mFile, null, font.getFontStyle(),
+ font.getIndex(), font.getFontVariationSettings(), null));
}
return new FontConfig.FontFamily(resolvedFonts, fontFamily.getName(),
- fontFamily.getLocaleList(), fontFamily.getVariant());
- }
-
- private PersistentSystemFontConfig.Config createPersistentConfig() {
- PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
- config.lastModifiedMillis = mLastModifiedMillis;
- for (FontFileInfo info : mFontFileInfoMap.values()) {
- config.updatedFontDirs.add(info.getRandomizedFontDir().getName());
- }
- config.fontFamilies.addAll(mFontFamilyMap.values());
- return config;
+ null, FontConfig.FontFamily.VARIANT_DEFAULT);
}
Map<String, File> getFontFileMap() {
@@ -566,27 +545,54 @@
return map;
}
- @VisibleForTesting
- Map<String, FontConfig.FontFamily> getFontFamilyMap() {
- return mFontFamilyMap;
- }
-
/* package */ FontConfig getSystemFontConfig() {
FontConfig config = SystemFonts.getSystemFontConfig(getFontFileMap(), 0, 0);
+ PersistentSystemFontConfig.Config persistentConfig = readPersistentConfig();
+ List<FontUpdateRequest.Family> families = persistentConfig.fontFamilies;
+
List<FontConfig.FontFamily> mergedFamilies =
- new ArrayList<>(config.getFontFamilies().size() + mFontFamilyMap.size());
+ new ArrayList<>(config.getFontFamilies().size() + families.size());
// We should keep the first font family (config.getFontFamilies().get(0)) because it's used
// as a fallback font. See SystemFonts.java.
mergedFamilies.addAll(config.getFontFamilies());
// When building Typeface, a latter font family definition will override the previous font
// family definition with the same name. An exception is config.getFontFamilies.get(0),
// which will be used as a fallback font without being overridden.
- mergedFamilies.addAll(mFontFamilyMap.values());
+ for (int i = 0; i < families.size(); ++i) {
+ FontConfig.FontFamily family = resolveFontFiles(families.get(i));
+ if (family != null) {
+ mergedFamilies.add(family);
+ }
+ }
+
return new FontConfig(
mergedFamilies, config.getAliases(), mLastModifiedMillis, mConfigVersion);
}
+ private PersistentSystemFontConfig.Config readPersistentConfig() {
+ PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
+ try (FileInputStream fis = new FileInputStream(mConfigFile)) {
+ PersistentSystemFontConfig.loadFromXml(fis, config);
+ } catch (IOException | XmlPullParserException e) {
+ // The font config file is missing on the first boot. Just do nothing.
+ }
+ return config;
+ }
+
/* package */ int getConfigVersion() {
return mConfigVersion;
}
+
+ public Map<String, FontConfig.FontFamily> getFontFamilyMap() {
+ PersistentSystemFontConfig.Config curConfig = readPersistentConfig();
+ Map<String, FontConfig.FontFamily> familyMap = new HashMap<>();
+ for (int i = 0; i < curConfig.fontFamilies.size(); ++i) {
+ FontUpdateRequest.Family family = curConfig.fontFamilies.get(i);
+ FontConfig.FontFamily resolvedFamily = resolveFontFiles(family);
+ if (resolvedFamily != null) {
+ familyMap.put(family.getName(), resolvedFamily);
+ }
+ }
+ return familyMap;
+ }
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 27f8fd3..3ac11da 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2623,8 +2623,9 @@
}
if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
// Dispatch display id for InputMethodService to update context display.
- executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
- MSG_INITIALIZE_IME, mCurTokenDisplayId, mCurMethod, mCurToken));
+ executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOOO(
+ MSG_INITIALIZE_IME, mCurTokenDisplayId, mCurMethod, mCurToken,
+ mMethodMap.get(mCurMethodId).getConfigChanges()));
scheduleNotifyImeUidToAudioService(mCurMethodUid);
if (mCurClient != null) {
clearClientSessionLocked(mCurClient);
@@ -4477,7 +4478,8 @@
}
final IBinder token = (IBinder) args.arg2;
((IInputMethod) args.arg1).initializeInternal(token, msg.arg1,
- new InputMethodPrivilegedOperationsImpl(this, token));
+ new InputMethodPrivilegedOperationsImpl(this, token),
+ (int) args.arg3);
} catch (RemoteException e) {
}
args.recycle();
@@ -5973,10 +5975,8 @@
@BinderThread
@Override
- public void setImeWindowStatus(int vis, int backDisposition,
- IVoidResultCallback resultCallback) {
- CallbackUtils.onResult(resultCallback,
- () -> mImms.setImeWindowStatus(mToken, vis, backDisposition));
+ public void setImeWindowStatusAsync(int vis, int backDisposition) {
+ mImms.setImeWindowStatus(mToken, vis, backDisposition);
}
@BinderThread
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index f646d5d..e25b03481 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -100,7 +100,8 @@
synchronized (mMethodMap) {
final List<ImeSubtypeListItem> imList = mSwitchingController
- .getSortedInputMethodAndSubtypeListLocked(showAuxSubtypes, isScreenLocked);
+ .getSortedInputMethodAndSubtypeListForImeMenuLocked(
+ showAuxSubtypes, isScreenLocked);
if (imList.isEmpty()) {
return;
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
index 8e84002..2969e53 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -181,7 +181,7 @@
}
public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList(
- boolean includeAuxiliarySubtypes, boolean isScreenLocked) {
+ boolean includeAuxiliarySubtypes, boolean isScreenLocked, boolean forImeMenu) {
final ArrayList<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
if (imis.isEmpty()) {
return Collections.emptyList();
@@ -196,6 +196,9 @@
final int numImes = imis.size();
for (int i = 0; i < numImes; ++i) {
final InputMethodInfo imi = imis.get(i);
+ if (forImeMenu && !imi.showInInputMethodPicker()) {
+ continue;
+ }
final List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypeList =
mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
final ArraySet<String> enabledSubtypeSet = new ArraySet<>();
@@ -513,7 +516,8 @@
mSubtypeList = new InputMethodAndSubtypeList(context, mSettings);
mController = ControllerImpl.createFrom(mController,
mSubtypeList.getSortedInputMethodAndSubtypeList(
- false /* includeAuxiliarySubtypes */, false /* isScreenLocked */));
+ false /* includeAuxiliarySubtypes */, false /* isScreenLocked */,
+ false /* forImeMenu */));
}
public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi,
@@ -527,10 +531,10 @@
return mController.getNextInputMethod(onlyCurrentIme, imi, subtype);
}
- public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeListLocked(
+ public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeListForImeMenuLocked(
boolean includingAuxiliarySubtypes, boolean isScreenLocked) {
return mSubtypeList.getSortedInputMethodAndSubtypeList(
- includingAuxiliarySubtypes, isScreenLocked);
+ includingAuxiliarySubtypes, isScreenLocked, true /* forImeMenu */);
}
public void dump(final Printer pw) {
diff --git a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
index 6201b94..5abc438 100644
--- a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
+++ b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
@@ -52,7 +52,8 @@
// Entries added by LockSettingsService once a user's synthetic password is known. At this point
// things are still keyed by userId.
- @NonNull private final ArrayList<UserAuthInfo> mPendingResetLockouts;
+ @NonNull private final ArrayList<UserAuthInfo> mPendingResetLockoutsForFingerprint;
+ @NonNull private final ArrayList<UserAuthInfo> mPendingResetLockoutsForFace;
/**
* Authentication info for a successful user unlock via Synthetic Password. This can be used to
@@ -151,7 +152,8 @@
mContext = context;
mSpManager = spManager;
mHandler = handler;
- mPendingResetLockouts = new ArrayList<>();
+ mPendingResetLockoutsForFingerprint = new ArrayList<>();
+ mPendingResetLockoutsForFace = new ArrayList<>();
}
public void systemReady(@Nullable FingerprintManager fingerprintManager,
@@ -173,17 +175,34 @@
*/
void addPendingLockoutResetForUser(int userId, @NonNull byte[] gatekeeperPassword) {
mHandler.post(() -> {
- Slog.d(TAG, "addPendingLockoutResetForUser: " + userId);
- mPendingResetLockouts.add(new UserAuthInfo(userId, gatekeeperPassword));
+ if (mFaceManager != null && mFaceManager.hasEnrolledTemplates(userId)) {
+ Slog.d(TAG, "Face addPendingLockoutResetForUser: " + userId);
+ mPendingResetLockoutsForFace.add(new UserAuthInfo(userId, gatekeeperPassword));
+ }
+
+ if (mFingerprintManager != null
+ && mFingerprintManager.hasEnrolledFingerprints(userId)) {
+ Slog.d(TAG, "Fingerprint addPendingLockoutResetForUser: " + userId);
+ mPendingResetLockoutsForFingerprint.add(new UserAuthInfo(userId,
+ gatekeeperPassword));
+ }
});
}
void processPendingLockoutResets() {
mHandler.post(() -> {
- Slog.d(TAG, "processPendingLockoutResets: " + mPendingResetLockouts.size());
- processPendingLockoutsForFingerprint(new ArrayList<>(mPendingResetLockouts));
- processPendingLockoutsForFace(new ArrayList<>(mPendingResetLockouts));
- mPendingResetLockouts.clear();
+ if (!mPendingResetLockoutsForFace.isEmpty()) {
+ Slog.d(TAG, "Processing pending resetLockout for face");
+ processPendingLockoutsForFace(new ArrayList<>(mPendingResetLockoutsForFace));
+ mPendingResetLockoutsForFace.clear();
+ }
+
+ if (!mPendingResetLockoutsForFingerprint.isEmpty()) {
+ Slog.d(TAG, "Processing pending resetLockout for fingerprint");
+ processPendingLockoutsForFingerprint(
+ new ArrayList<>(mPendingResetLockoutsForFingerprint));
+ mPendingResetLockoutsForFingerprint.clear();
+ }
});
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index b92a83f..f69a3bd 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -800,7 +800,7 @@
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
- setWriteAheadLoggingEnabled(true);
+ setWriteAheadLoggingEnabled(false);
// Memory optimization - close idle connections after 30s of inactivity
setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
}
diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
index cb0a6688..bb996a0 100644
--- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
+++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
@@ -64,13 +64,6 @@
private static final int PACKAGE_MANAGER_COMMON_FLAGS =
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
- /**
- * Denotes the duration during which a media button receiver will be exempted from
- * FGS-from-BG restriction and so will be allowed to start an FGS even if it is in the
- * background state while it receives a media key event.
- */
- private static final long FGS_STARTS_TEMP_ALLOWLIST_DURATION_MS = 10_000;
-
private final int mUserId;
private final PendingIntent mPendingIntent;
private final ComponentName mComponentName;
@@ -185,10 +178,13 @@
* Ignored if there's no valid pending intent.
* @param handler handler to be used to call onFinishedListener
* Ignored if there's no valid pending intent.
+ * @param fgsAllowlistDurationMs duration for which the media button receiver will be
+ * allowed to start FGS from BG.
* @see PendingIntent#send(Context, int, Intent, PendingIntent.OnFinished, Handler)
*/
public boolean send(Context context, KeyEvent keyEvent, String callingPackageName,
- int resultCode, PendingIntent.OnFinished onFinishedListener, Handler handler) {
+ int resultCode, PendingIntent.OnFinished onFinishedListener, Handler handler,
+ long fgsAllowlistDurationMs) {
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
@@ -196,7 +192,7 @@
mediaButtonIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callingPackageName);
final BroadcastOptions options = BroadcastOptions.makeBasic();
- options.setTemporaryAppAllowlist(FGS_STARTS_TEMP_ALLOWLIST_DURATION_MS,
+ options.setTemporaryAppAllowlist(fgsAllowlistDurationMs,
PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
PowerWhitelistManager.REASON_MEDIA_BUTTON, "");
if (mPendingIntent != null) {
diff --git a/services/core/java/com/android/server/media/MediaSessionDeviceConfig.java b/services/core/java/com/android/server/media/MediaSessionDeviceConfig.java
new file mode 100644
index 0000000..9bb8e2e
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaSessionDeviceConfig.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import android.content.Context;
+import android.provider.DeviceConfig;
+import android.text.TextUtils;
+
+import java.io.PrintWriter;
+import java.util.Set;
+
+class MediaSessionDeviceConfig {
+ /**
+ * Denotes the duration for which a media button receiver will be exempted from
+ * FGS-from-BG restriction and so will be allowed to start an FGS even if it is in the
+ * background state while it receives a media key event.
+ */
+ private static final String KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS =
+ "media_button_receiver_fgs_allowlist_duration_ms";
+ private static final long DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS = 10_000;
+ private static volatile long sMediaButtonReceiverFgsAllowlistDurationMs =
+ DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS;
+
+ /**
+ * Denotes the duration for which an app receiving a media session callback will be
+ * exempted from FGS-from-BG restriction and so will be allowed to start an FGS even if
+ * it is in the background state while it receives a media session callback.
+ */
+ private static final String KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS =
+ "media_session_calback_fgs_allowlist_duration_ms";
+ private static final long DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS = 10_000;
+ private static volatile long sMediaSessionCallbackFgsAllowlistDurationMs =
+ DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS;
+
+ private static void refresh(DeviceConfig.Properties properties) {
+ final Set<String> keys = properties.getKeyset();
+ properties.getKeyset().forEach(key -> {
+ switch (key) {
+ case KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS:
+ sMediaButtonReceiverFgsAllowlistDurationMs = properties.getLong(key,
+ DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS);
+ break;
+ case KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS:
+ sMediaSessionCallbackFgsAllowlistDurationMs = properties.getLong(key,
+ DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS);
+ break;
+ }
+ });
+ }
+
+ public static void initialize(Context context) {
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_MEDIA,
+ context.getMainExecutor(), properties -> refresh(properties));
+ refresh(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_MEDIA));
+ }
+
+ /**
+ * Returns the duration for which a media button receiver will be exempted from
+ * FGS-from-BG restriction and so will be allowed to start an FGS even if it is in the
+ * background state while it receives a media key event.
+ */
+ public static long getMediaButtonReceiverFgsAllowlistDurationMs() {
+ return sMediaButtonReceiverFgsAllowlistDurationMs;
+ }
+
+ /**
+ * Returns the duration for which an app receiving a media session callback will be
+ * exempted from FGS-from-BG restriction and so will be allowed to start an FGS even if
+ * it is in the background state while it receives a media session callback.
+ */
+ public static long getMediaSessionCallbackFgsAllowlistDurationMs() {
+ return sMediaSessionCallbackFgsAllowlistDurationMs;
+ }
+
+ public static void dump(PrintWriter pw, String prefix) {
+ pw.println("Media session config:");
+ final String dumpFormat = prefix + " %s: [cur: %s, def: %s]";
+ pw.println(TextUtils.formatSimple(dumpFormat,
+ KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS,
+ sMediaButtonReceiverFgsAllowlistDurationMs,
+ DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS));
+ pw.println(TextUtils.formatSimple(dumpFormat,
+ KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS,
+ sMediaSessionCallbackFgsAllowlistDurationMs,
+ DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS));
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index a30d993..50cfe1f 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -117,13 +117,6 @@
*/
private static final String MEDIA_BUTTON_RECEIVER = "media_button_receiver";
- /**
- * Denotes the duration during which an app receiving a media session callback will be
- * exempted from FGS-from-BG restriction and so will be allowed to start an FGS even if it is
- * in the background state while it receives a media session callback.
- */
- private static final long FGS_STARTS_TEMP_ALLOWLIST_DURATION_MS = 10_000;
-
private final Context mContext;
private final SessionManagerImpl mSessionManagerImpl;
private final MessageHandler mHandler = new MessageHandler();
@@ -244,6 +237,9 @@
mCommunicationManager.registerSessionCallback(new HandlerExecutor(mHandler),
mSession2TokenCallback);
break;
+ case PHASE_ACTIVITY_MANAGER_READY:
+ MediaSessionDeviceConfig.initialize(mContext);
+ break;
}
}
@@ -564,7 +560,7 @@
PowerExemptionManager.class);
powerExemptionManager.addToTemporaryAllowList(targetPackage,
PowerExemptionManager.REASON_MEDIA_SESSION_CALLBACK, reason,
- FGS_STARTS_TEMP_ALLOWLIST_DURATION_MS);
+ MediaSessionDeviceConfig.getMediaSessionCallbackFgsAllowlistDurationMs());
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -1979,6 +1975,7 @@
}
mAudioPlayerStateMonitor.dump(mContext, pw, "");
}
+ MediaSessionDeviceConfig.dump(pw, "");
}
/**
@@ -2262,7 +2259,8 @@
boolean sent = mediaButtonReceiverHolder.send(
mContext, keyEvent, callingPackageName,
needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1, mKeyEventReceiver,
- mHandler);
+ mHandler,
+ MediaSessionDeviceConfig.getMediaButtonReceiverFgsAllowlistDurationMs());
if (sent) {
String pkgName = mediaButtonReceiverHolder.getPackageName();
for (FullUserRecord.OnMediaKeyEventDispatchedListenerRecord cr
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index de5aae0..19f5e3c 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -24,6 +24,7 @@
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.EXTRA_UID;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkIdentity.SUBTYPE_COMBINED;
import static android.net.NetworkStack.checkNetworkStackPermission;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
@@ -65,6 +66,7 @@
import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -100,7 +102,9 @@
import android.net.NetworkStats;
import android.net.NetworkStats.NonMonotonicObserver;
import android.net.NetworkStatsHistory;
+import android.net.NetworkSpecifier;
import android.net.NetworkTemplate;
+import android.net.TelephonyNetworkSpecifier;
import android.net.TrafficStats;
import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
@@ -1320,8 +1324,9 @@
ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
ident.getRoaming(), true /* metered */,
true /* onDefaultNetwork */, ident.getOemManaged());
- findOrCreateNetworkIdentitySet(mActiveIfaces, IFACE_VT).add(vtIdent);
- findOrCreateNetworkIdentitySet(mActiveUidIfaces, IFACE_VT).add(vtIdent);
+ final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot);
+ findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent);
+ findOrCreateNetworkIdentitySet(mActiveUidIfaces, ifaceVt).add(vtIdent);
}
if (isMobile) {
@@ -1377,6 +1382,20 @@
mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
}
+ private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) {
+ if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ throw new IllegalArgumentException("Mobile state need capability TRANSPORT_CELLULAR");
+ }
+
+ final NetworkSpecifier spec = state.networkCapabilities.getNetworkSpecifier();
+ if (spec instanceof TelephonyNetworkSpecifier) {
+ return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
+ } else {
+ Slog.wtf(TAG, "getSubIdForState invalid NetworkSpecifier");
+ return INVALID_SUBSCRIPTION_ID;
+ }
+ }
+
/**
* For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through
* {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4fc97ef..68990ba 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3617,34 +3617,6 @@
}
@Override
- public void deleteConversationNotificationChannels(String pkg, int uid,
- String conversationId) {
- checkCallerIsSystem();
- List<NotificationChannel> channels =
- mPreferencesHelper.getNotificationChannelsByConversationId(
- pkg, uid, conversationId);
- if (!channels.isEmpty()) {
- // Preflight for fg service notifications in these channels: do nothing
- // unless they're all eligible
- final int appUserId = UserHandle.getUserId(uid);
- for (NotificationChannel nc : channels) {
- final String channelId = nc.getId();
- mAmi.stopForegroundServicesForChannel(pkg, appUserId, channelId);
- cancelAllNotificationsInt(MY_UID, MY_PID, pkg, nc.getId(), 0, 0, true,
- appUserId, REASON_CHANNEL_REMOVED, null);
- mPreferencesHelper.deleteNotificationChannel(pkg, uid, channelId);
- mListeners.notifyNotificationChannelChanged(pkg,
- UserHandle.getUserHandleForUid(uid),
- mPreferencesHelper.getNotificationChannel(
- pkg, uid, channelId, true),
- NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
- }
- handleSavePolicyFile();
- }
- }
-
-
- @Override
public NotificationChannelGroup getNotificationChannelGroup(String pkg, String groupId) {
checkCallerIsSystemOrSameApp(pkg);
return mPreferencesHelper.getNotificationChannelGroupWithChannels(
diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java
index cc6a824..ed1f5f5 100644
--- a/services/core/java/com/android/server/os/NativeTombstoneManager.java
+++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java
@@ -392,7 +392,7 @@
int pid = 0;
int uid = 0;
- String processName = "";
+ String processName = null;
String crashReason = "";
String selinuxLabel = "";
@@ -407,8 +407,10 @@
uid = stream.readInt(Tombstone.UID);
break;
- case (int) Tombstone.PROCESS_NAME:
- processName = stream.readString(Tombstone.PROCESS_NAME);
+ case (int) Tombstone.COMMAND_LINE:
+ if (processName == null) {
+ processName = stream.readString(Tombstone.COMMAND_LINE);
+ }
break;
case (int) Tombstone.CAUSES:
@@ -472,7 +474,7 @@
result.mAppId = appId;
result.mPid = pid;
result.mUid = uid;
- result.mProcessName = processName;
+ result.mProcessName = processName == null ? "" : processName;
result.mTimestampMs = timestampMs;
result.mCrashReason = crashReason;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 2e6c57c..671fccf 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -927,7 +927,7 @@
final boolean forcePermissionPrompt =
(params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0
- || params.requireUserAction == Boolean.TRUE;
+ || params.requireUserAction == SessionInfo.USER_ACTION_REQUIRED;
if (forcePermissionPrompt) {
return USER_ACTION_REQUIRED;
}
@@ -976,7 +976,7 @@
return USER_ACTION_REQUIRED;
}
- if (params.requireUserAction == Boolean.FALSE
+ if (params.requireUserAction == SessionInfo.USER_ACTION_NOT_REQUIRED
&& isUpdateWithoutUserActionPermissionGranted
&& (isInstallerOfRecord || isSelfUpdate)) {
return USER_ACTION_PENDING_APK_PARSING;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 550e9f8..dcb9906 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3173,8 +3173,8 @@
final int[] gids = (flags & PackageManager.GET_GIDS) == 0 ? EMPTY_INT_ARRAY
: mPermissionManager.getGidsForUid(UserHandle.getUid(userId, ps.appId));
// Compute granted permissions only if package has requested permissions
- final Set<String> permissions = ArrayUtils.isEmpty(p.getRequestedPermissions())
- ? Collections.emptySet()
+ final Set<String> permissions = ((flags & PackageManager.GET_PERMISSIONS) == 0
+ || ArrayUtils.isEmpty(p.getRequestedPermissions())) ? Collections.emptySet()
: mPermissionManager.getGrantedPermissions(ps.name, userId);
PackageInfo packageInfo = PackageInfoUtils.generate(p, gids, flags,
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index fd8ec7f..2dad8ce 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -2187,6 +2187,10 @@
private void saveShortcut(@NonNull final Collection<ShortcutInfo> shortcuts) {
Objects.requireNonNull(shortcuts);
+ if (shortcuts.isEmpty()) {
+ // No need to invoke AppSearch when there's nothing to save.
+ return;
+ }
ConcurrentUtils.waitForFutureNoInterrupt(
runInAppSearch(session -> {
final AndroidFuture<Boolean> future = new AndroidFuture<>();
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 780e5e5..d86438b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -171,7 +171,7 @@
static final int DEFAULT_MAX_UPDATES_PER_INTERVAL = 10;
@VisibleForTesting
- static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = Integer.MAX_VALUE;
+ static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
@VisibleForTesting
static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index ce49d88..5f0aa03 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -333,10 +333,7 @@
if (!shortcutPackage.rescanPackageIfNeeded(isNewApp, forceRescan)) {
if (isNewApp) {
- final ShortcutPackage sp = mPackages.remove(packageName);
- if (sp != null) {
- sp.removeShortcuts();
- }
+ mPackages.remove(packageName);
}
}
}
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index e16c67f..9bc9d9f 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -278,7 +278,7 @@
try {
return mContext.getPackageManager().getPermissionInfo(permissionName, 0);
} catch (NameNotFoundException e) {
- Slog.e(TAG, "Permission not found: " + permissionName);
+ Slog.w(TAG, "Permission not found: " + permissionName);
return null;
}
}
@@ -737,10 +737,9 @@
grantPermissionsToSystemPackage(pm, packageName, userId,
CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
- SENSORS_PERMISSIONS, STORAGE_PERMISSIONS);
+ SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, NEARBY_DEVICES_PERMISSIONS);
grantSystemFixedPermissionsToSystemPackage(pm, packageName, userId,
- ALWAYS_LOCATION_PERMISSIONS, NEARBY_DEVICES_PERMISSIONS,
- ACTIVITY_RECOGNITION_PERMISSIONS);
+ ALWAYS_LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
}
}
if (locationExtraPackageNames != null) {
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 920d044..142b36e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -85,11 +85,13 @@
import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.metrics.LogMaker;
import android.os.AsyncTask;
+import android.content.AttributionSource;
import android.os.Binder;
import android.os.Build;
import android.os.Debug;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
@@ -159,6 +161,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.WeakHashMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -254,6 +257,10 @@
@NonNull
private final PermissionRegistry mRegistry = new PermissionRegistry();
+ @NonNull
+ private final AttributionSourceRegistry mAttributionSourceRegistry =
+ new AttributionSourceRegistry();
+
@GuardedBy("mLock")
@Nullable
private ArraySet<String> mPrivappPermissionsViolations;
@@ -3231,6 +3238,16 @@
}
@Override
+ public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) {
+ return mAttributionSourceRegistry.registerAttributionSource(source);
+ }
+
+ @Override
+ public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) {
+ return mAttributionSourceRegistry.isRegisteredAttributionSource(source);
+ }
+
+ @Override
public List<String> getAutoRevokeExemptionRequestedPackages(int userId) {
return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISCOURAGED, userId);
}
@@ -5265,4 +5282,73 @@
|| mDelegatedPermissionNames.contains(permissionName);
}
}
+
+ private static final class AttributionSourceRegistry {
+ private final Object mLock = new Object();
+
+ private final WeakHashMap<IBinder, AttributionSource> mAttributions = new WeakHashMap<>();
+
+ public @NonNull AttributionSource registerAttributionSource(
+ @NonNull AttributionSource source) {
+ // Here we keep track of attribution sources that were created by an app
+ // from an attribution chain that called into the app and the apps's
+ // own attribution source. An app can register an attribution chain up
+ // to itself inclusive if and only if it is adding a node for itself which
+ // optionally points to an attribution chain that was created by each
+ // preceding app recursively up to the beginning of the chain.
+ // The only special case is when the first app in the attribution chain
+ // creates a source that points to another app (not a chain of apps). We
+ // allow this even if the source the app points to is not registered since
+ // in app ops we allow every app to blame every other app (untrusted if not
+ // holding a special permission).
+ // This technique ensures that a bad actor in the middle of the attribution
+ // chain can neither prepend nor append an invalid attribution sequence, i.e.
+ // a sequence that is not constructed by trusted sources up to the that bad
+ // actor's app.
+ // Note that passing your attribution source to another app means you allow
+ // it to blame private data access on your app. This can be mediated by the OS
+ // in, which case security is already enforced; by other app's code running in
+ // your process calling into the other app, in which case it can already access
+ // the private data in your process; or by you explicitly calling to another
+ // app passing the source, in which case you must trust the other side;
+
+ final int callingUid = Binder.getCallingUid();
+ if (source.getUid() != callingUid) {
+ throw new SecurityException("Cannot register attribution source for uid:"
+ + source.getUid() + " from uid:" + callingUid);
+ }
+
+ final PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ if (packageManagerInternal.getPackageUid(source.getPackageName(), 0,
+ UserHandle.getUserId(callingUid)) != source.getUid()) {
+ throw new SecurityException("Cannot register attribution source for package:"
+ + source.getPackageName() + " from uid:" + callingUid);
+ }
+
+ final AttributionSource next = source.getNext();
+ if (next != null && next.getNext() != null
+ && !isRegisteredAttributionSource(next)) {
+ throw new SecurityException("Cannot register forged attribution source:"
+ + source);
+ }
+
+ synchronized (mLock) {
+ final IBinder token = new Binder();
+ final AttributionSource result = source.withToken(token);
+ mAttributions.put(token, result);
+ return result;
+ }
+ }
+
+ public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) {
+ synchronized (mLock) {
+ final AttributionSource cachedSource = mAttributions.get(source.getToken());
+ if (cachedSource != null) {
+ return cachedSource.equals(source);
+ }
+ return false;
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index 1b2ff08..63515b9 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -24,7 +24,6 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.compat.annotation.ChangeId;
-import android.compat.annotation.Disabled;
import android.content.Context;
import android.content.Intent;
import android.content.pm.IntentFilterVerificationInfo;
@@ -92,7 +91,6 @@
* commands.
*/
@ChangeId
- @Disabled
private static final long SETTINGS_API_V2 = 178111421;
/**
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index c965390..5db63c6 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -20,13 +20,18 @@
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.AppOpsManagerInternal;
+import android.content.AttributionSource;
import android.location.LocationManagerInternal;
+import android.os.IBinder;
import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.TriFunction;
import com.android.server.LocalServices;
import java.util.Set;
@@ -52,7 +57,7 @@
@GuardedBy("mLock - writes only - see above")
@NonNull
private final ConcurrentHashMap<Integer, ArrayMap<String, ArraySet<String>>> mLocationTags =
- new ConcurrentHashMap();
+ new ConcurrentHashMap<>();
public AppOpsPolicy() {
final LocationManagerInternal locationManagerInternal = LocalServices.getService(
@@ -112,22 +117,59 @@
@Override
public int noteOperation(int code, int uid, @Nullable String packageName,
- @Nullable String featureId, boolean shouldCollectAsyncNotedOp, @Nullable String message,
- boolean shouldCollectMessage, @NonNull HeptFunction<Integer, Integer, String, String,
- Boolean, String, Boolean, Integer> superImpl) {
- if (isHandledOp(code)) {
+ @Nullable String attributionTag, boolean shouldCollectAsyncNotedOp, @Nullable
+ String message, boolean shouldCollectMessage, @NonNull HeptFunction<Integer, Integer,
+ String, String, Boolean, String, Boolean, Integer> superImpl) {
+ return superImpl.apply(resolveOpCode(code, uid, packageName, attributionTag), uid,
+ packageName, attributionTag, shouldCollectAsyncNotedOp,
+ message, shouldCollectMessage);
+ }
+
+ @Override
+ public int noteProxyOperation(int code, @NonNull AttributionSource attributionSource,
+ boolean shouldCollectAsyncNotedOp, @Nullable String message,
+ boolean shouldCollectMessage, boolean skipProxyOperation, @NonNull HexFunction<Integer,
+ AttributionSource, Boolean, String, Boolean, Boolean, Integer> superImpl) {
+ return superImpl.apply(resolveOpCode(code, attributionSource.getUid(),
+ attributionSource.getPackageName(), attributionSource.getAttributionTag()),
+ attributionSource, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ skipProxyOperation);
+ }
+
+ @Override
+ public int startProxyOperation(IBinder token, int code,
+ @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ boolean skipProxyOperation, @NonNull OctFunction<IBinder, Integer, AttributionSource,
+ Boolean, Boolean, String, Boolean, Boolean, Integer> superImpl) {
+ return superImpl.apply(token, resolveOpCode(code, attributionSource.getUid(),
+ attributionSource.getPackageName(), attributionSource.getAttributionTag()),
+ attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message,
+ shouldCollectMessage, skipProxyOperation);
+ }
+
+ @Override
+ public void finishProxyOperation(IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource,
+ @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl) {
+ superImpl.apply(clientId, resolveOpCode(code, attributionSource.getUid(),
+ attributionSource.getPackageName(), attributionSource.getAttributionTag()),
+ attributionSource);
+ }
+
+ private int resolveOpCode(int code, int uid, @NonNull String packageName,
+ @Nullable String attributionTag) {
+ if (isHandledOp(code) && attributionTag != null) {
// Only a single lookup from the underlying concurrent data structure
final ArrayMap<String, ArraySet<String>> uidTags = mLocationTags.get(uid);
if (uidTags != null) {
final ArraySet<String> packageTags = uidTags.get(packageName);
- if (packageTags != null && packageTags.contains(featureId)) {
- return superImpl.apply(resolveLocationOp(code), uid, packageName, featureId,
- shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+ if (packageTags != null && packageTags.contains(attributionTag)) {
+ return resolveHandledOp(code);
}
}
}
- return superImpl.apply(code, uid, packageName, featureId, shouldCollectAsyncNotedOp,
- message, shouldCollectMessage);
+ return code;
}
private static boolean isHandledOp(int code) {
@@ -139,7 +181,7 @@
return false;
}
- private static int resolveLocationOp(int code) {
+ private static int resolveHandledOp(int code) {
switch (code) {
case AppOpsManager.OP_FINE_LOCATION:
return AppOpsManager.OP_FINE_LOCATION_SOURCE;
diff --git a/services/core/java/com/android/server/policy/KeyCombinationManager.java b/services/core/java/com/android/server/policy/KeyCombinationManager.java
index 7f55723..268de3e 100644
--- a/services/core/java/com/android/server/policy/KeyCombinationManager.java
+++ b/services/core/java/com/android/server/policy/KeyCombinationManager.java
@@ -18,11 +18,13 @@
import static android.view.KeyEvent.KEYCODE_POWER;
import android.os.SystemClock;
+import android.util.Log;
import android.util.SparseLongArray;
import android.view.KeyEvent;
import com.android.internal.util.ToBooleanFunction;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.function.Consumer;
@@ -89,8 +91,8 @@
@Override
public String toString() {
- return "KeyCode1 = " + KeyEvent.keyCodeToString(mKeyCode1)
- + ", KeyCode2 = " + KeyEvent.keyCodeToString(mKeyCode2);
+ return KeyEvent.keyCodeToString(mKeyCode1) + " + "
+ + KeyEvent.keyCodeToString(mKeyCode2);
}
}
@@ -151,6 +153,7 @@
if (!rule.shouldInterceptKeys(mDownTimes)) {
return false;
}
+ Log.v(TAG, "Performing combination rule : " + rule);
rule.execute();
mTriggeredRule = rule;
return true;
@@ -230,4 +233,11 @@
}
return false;
}
+
+ void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "KeyCombination rules:");
+ forAllRules(mRules, (rule)-> {
+ pw.println(prefix + " " + rule);
+ });
+ }
}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 9077433..89d5415 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -578,7 +578,7 @@
private final @NonNull AppOpsManager mAppOpsManager;
private final @NonNull AppOpsManagerInternal mAppOpsManagerInternal;
- private final @NonNull ArrayMap<String, PermissionInfo> mRuntimePermissionInfos;
+ private final @NonNull ArrayMap<String, PermissionInfo> mRuntimeAndTheirBgPermissionInfos;
/**
* All ops that need to be flipped to allow.
@@ -618,7 +618,7 @@
mAppOpsManager = context.getSystemService(AppOpsManager.class);
mAppOpsManagerInternal = LocalServices.getService(AppOpsManagerInternal.class);
- mRuntimePermissionInfos = new ArrayMap<>();
+ mRuntimeAndTheirBgPermissionInfos = new ArrayMap<>();
PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
PermissionManagerServiceInternal.class);
List<PermissionInfo> permissionInfos =
@@ -627,7 +627,30 @@
int permissionInfosSize = permissionInfos.size();
for (int i = 0; i < permissionInfosSize; i++) {
PermissionInfo permissionInfo = permissionInfos.get(i);
- mRuntimePermissionInfos.put(permissionInfo.name, permissionInfo);
+ mRuntimeAndTheirBgPermissionInfos.put(permissionInfo.name, permissionInfo);
+ // Make sure we scoop up all background permissions as they may not be runtime
+ if (permissionInfo.backgroundPermission != null) {
+ String backgroundNonRuntimePermission = permissionInfo.backgroundPermission;
+ for (int j = 0; j < permissionInfosSize; j++) {
+ PermissionInfo bgPermissionCandidate = permissionInfos.get(j);
+ if (permissionInfo.backgroundPermission.equals(
+ bgPermissionCandidate.name)) {
+ backgroundNonRuntimePermission = null;
+ break;
+ }
+ }
+ if (backgroundNonRuntimePermission != null) {
+ try {
+ PermissionInfo backgroundPermissionInfo = mPackageManager
+ .getPermissionInfo(backgroundNonRuntimePermission, 0);
+ mRuntimeAndTheirBgPermissionInfos.put(backgroundPermissionInfo.name,
+ backgroundPermissionInfo);
+ } catch (NameNotFoundException e) {
+ Slog.w(LOG_TAG, "Unknown background permission: "
+ + backgroundNonRuntimePermission);
+ }
+ }
+ }
}
}
@@ -691,7 +714,7 @@
*/
private void addAppOps(@NonNull PackageInfo packageInfo, @NonNull AndroidPackage pkg,
@NonNull String permissionName) {
- PermissionInfo permissionInfo = mRuntimePermissionInfos.get(permissionName);
+ PermissionInfo permissionInfo = mRuntimeAndTheirBgPermissionInfos.get(permissionName);
if (permissionInfo == null) {
return;
}
@@ -726,7 +749,7 @@
boolean shouldGrantAppOp = shouldGrantAppOp(packageInfo, pkg, permissionInfo);
if (shouldGrantAppOp) {
if (permissionInfo.backgroundPermission != null) {
- PermissionInfo backgroundPermissionInfo = mRuntimePermissionInfos.get(
+ PermissionInfo backgroundPermissionInfo = mRuntimeAndTheirBgPermissionInfos.get(
permissionInfo.backgroundPermission);
boolean shouldGrantBackgroundAppOp = backgroundPermissionInfo != null
&& shouldGrantAppOp(packageInfo, pkg, backgroundPermissionInfo);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f185464..f931df8 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -434,7 +434,6 @@
// to hold wakelocks during dispatch and eliminating the critical path.
volatile boolean mPowerKeyHandled;
volatile boolean mBackKeyHandled;
- volatile boolean mBeganFromNonInteractive;
volatile boolean mEndCallKeyHandled;
volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
@@ -876,16 +875,6 @@
if (!mPowerKeyHandled) {
if (!interactive) {
wakeUpFromPowerKey(event.getDownTime());
- if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
- mBeganFromNonInteractive = true;
- } else {
- final int maxCount = getMaxMultiPressPowerCount();
- if (maxCount <= 1) {
- mPowerKeyHandled = true;
- } else {
- mBeganFromNonInteractive = true;
- }
- }
}
} else {
// handled by another power key policy.
@@ -895,7 +884,7 @@
}
}
- private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
+ private void interceptPowerKeyUp(KeyEvent event, boolean canceled) {
final boolean handled = canceled || mPowerKeyHandled;
if (!handled) {
@@ -906,33 +895,36 @@
} else {
// handled by single key or another power key policy.
mSingleKeyGestureDetector.reset();
- finishPowerKeyPress();
}
+
+ finishPowerKeyPress();
}
private void finishPowerKeyPress() {
- mBeganFromNonInteractive = false;
mPowerKeyHandled = false;
if (mPowerKeyWakeLock.isHeld()) {
mPowerKeyWakeLock.release();
}
}
- private void powerPress(long eventTime, boolean interactive, int count) {
+ private void powerPress(long eventTime, int count, boolean beganFromNonInteractive) {
if (mDefaultDisplayPolicy.isScreenOnEarly() && !mDefaultDisplayPolicy.isScreenOnFully()) {
Slog.i(TAG, "Suppressed redundant power key press while "
+ "already in the process of turning the screen on.");
return;
}
+
+ final boolean interactive = Display.isOnState(mDefaultDisplay.getState());
+
Slog.d(TAG, "powerPress: eventTime=" + eventTime + " interactive=" + interactive
- + " count=" + count + " beganFromNonInteractive=" + mBeganFromNonInteractive +
- " mShortPressOnPowerBehavior=" + mShortPressOnPowerBehavior);
+ + " count=" + count + " beganFromNonInteractive=" + beganFromNonInteractive
+ + " mShortPressOnPowerBehavior=" + mShortPressOnPowerBehavior);
if (count == 2) {
powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
} else if (count == 3) {
powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
- } else if (interactive && !mBeganFromNonInteractive) {
+ } else if (interactive && !beganFromNonInteractive) {
switch (mShortPressOnPowerBehavior) {
case SHORT_PRESS_POWER_NOTHING:
break;
@@ -1906,12 +1898,19 @@
@Override
void onPress(long downTime) {
- powerPress(downTime, true, 1 /*count*/);
+ powerPress(downTime, 1 /*count*/,
+ mSingleKeyGestureDetector.beganFromNonInteractive());
finishPowerKeyPress();
}
@Override
void onLongPress(long eventTime) {
+ if (mSingleKeyGestureDetector.beganFromNonInteractive()
+ && !mSupportLongPressPowerWhenNonInteractive) {
+ Slog.v(TAG, "Not support long press power when device is not interactive.");
+ return;
+ }
+
powerLongPress(eventTime);
}
@@ -1923,7 +1922,7 @@
@Override
void onMultiPress(long downTime, int count) {
- powerPress(downTime, true, count);
+ powerPress(downTime, count, mSingleKeyGestureDetector.beganFromNonInteractive());
finishPowerKeyPress();
}
}
@@ -3562,7 +3561,7 @@
if (down) {
interceptPowerKeyDown(event, interactiveAndOn);
} else {
- interceptPowerKeyUp(event, interactiveAndOn, canceled);
+ interceptPowerKeyUp(event, canceled);
}
break;
}
@@ -3752,7 +3751,7 @@
}
}
- mSingleKeyGestureDetector.interceptKey(event);
+ mSingleKeyGestureDetector.interceptKey(event, interactive);
}
// The camera gesture will be detected by GestureLauncherService.
@@ -5230,6 +5229,8 @@
pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
mGlobalKeyManager.dump(prefix, pw);
+ mKeyCombinationManager.dump(prefix, pw);
+ mSingleKeyGestureDetector.dump(prefix, pw);
if (mWakeGestureListener != null) {
mWakeGestureListener.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
index cae2093..3f4d920 100644
--- a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
+++ b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
@@ -25,6 +25,7 @@
import android.view.KeyEvent;
import android.view.ViewConfiguration;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -37,7 +38,7 @@
public final class SingleKeyGestureDetector {
private static final String TAG = "SingleKeyGesture";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = PhoneWindowManager.DEBUG_INPUT;
private static final int MSG_KEY_LONG_PRESS = 0;
private static final int MSG_KEY_VERY_LONG_PRESS = 1;
@@ -47,6 +48,7 @@
private final long mVeryLongPressTimeout;
private volatile int mKeyPressCounter;
+ private boolean mBeganFromNonInteractive = false;
private final ArrayList<SingleKeyRule> mRules = new ArrayList();
private SingleKeyRule mActiveRule = null;
@@ -57,7 +59,6 @@
private final Handler mHandler;
private static final long MULTI_PRESS_TIMEOUT = ViewConfiguration.getMultiPressTimeout();
-
/** Supported gesture flags */
public static final int KEY_LONGPRESS = 1 << 1;
public static final int KEY_VERYLONGPRESS = 1 << 2;
@@ -143,10 +144,10 @@
@Override
public String toString() {
- return "KeyCode = " + KeyEvent.keyCodeToString(mKeyCode)
- + ", long press : " + supportLongPress()
- + ", very Long press : " + supportVeryLongPress()
- + ", max multi press count : " + getMaxMultiPressCount();
+ return "KeyCode=" + KeyEvent.keyCodeToString(mKeyCode)
+ + ", LongPress=" + supportLongPress()
+ + ", VeryLongPress=" + supportVeryLongPress()
+ + ", MaxMultiPressCount=" + getMaxMultiPressCount();
}
}
@@ -161,8 +162,12 @@
mRules.add(rule);
}
- void interceptKey(KeyEvent event) {
+ void interceptKey(KeyEvent event, boolean interactive) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ // Store the non interactive state when first down.
+ if (mDownKeyCode == KeyEvent.KEYCODE_UNKNOWN || mDownKeyCode != event.getKeyCode()) {
+ mBeganFromNonInteractive = !interactive;
+ }
interceptKeyDown(event);
} else {
interceptKeyUp(event);
@@ -268,6 +273,7 @@
Log.i(TAG, "press key " + KeyEvent.keyCodeToString(event.getKeyCode()));
}
mActiveRule.onPress(downTime);
+ reset();
return true;
}
@@ -316,6 +322,17 @@
return false;
}
+ boolean beganFromNonInteractive() {
+ return mBeganFromNonInteractive;
+ }
+
+ void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "SingleKey rules:");
+ for (SingleKeyRule rule : mRules) {
+ pw.println(prefix + " " + rule);
+ }
+ }
+
private class KeyHandler extends Handler {
KeyHandler() {
super(Looper.getMainLooper());
@@ -354,7 +371,7 @@
} else {
mActiveRule.onMultiPress(eventTime, mKeyPressCounter);
}
- mKeyPressCounter = 0;
+ reset();
break;
}
}
diff --git a/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java b/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java
index 9732eba3..ea93324 100644
--- a/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java
+++ b/services/core/java/com/android/server/power/DisplayGroupPowerStateMapper.java
@@ -125,6 +125,10 @@
return mDisplayGroupIds;
}
+ int getDisplayGroupCountLocked() {
+ return mDisplayGroupIds.length;
+ }
+
int getWakefulnessLocked(int groupId) {
return mDisplayGroupInfos.get(groupId).wakefulness;
}
@@ -272,6 +276,14 @@
mDisplayGroupInfos.get(groupId).userActivitySummary = summary;
}
+ int getWakeLockSummaryLocked(int groupId) {
+ return mDisplayGroupInfos.get(groupId).wakeLockSummary;
+ }
+
+ void setWakeLockSummaryLocked(int groupId, int summary) {
+ mDisplayGroupInfos.get(groupId).wakeLockSummary = summary;
+ }
+
/**
* Interface through which an interested party may be informed of {@link DisplayGroup} events.
*/
@@ -292,6 +304,7 @@
public long lastUserActivityTime;
public long lastUserActivityTimeNoChangeLights;
public int userActivitySummary;
+ public int wakeLockSummary;
/** {@code true} if this DisplayGroup supports dreaming; otherwise {@code false}. */
public boolean supportsSandman;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 54d5b7a..8052522 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1348,9 +1348,20 @@
updatePowerStateLocked();
}
- private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
- WorkSource ws, String historyTag, int uid, int pid) {
+ private void acquireWakeLockInternal(IBinder lock, int displayId, int flags, String tag,
+ String packageName, WorkSource ws, String historyTag, int uid, int pid) {
synchronized (mLock) {
+ if (displayId != Display.INVALID_DISPLAY) {
+ final DisplayInfo displayInfo =
+ mSystemReady ? mDisplayManagerInternal.getDisplayInfo(displayId) : null;
+ if (displayInfo == null) {
+ Slog.wtf(TAG, "Tried to acquire wake lock for invalid display: " + displayId);
+ return;
+ } else if (!displayInfo.hasAccess(uid)) {
+ throw new SecurityException("Caller does not have access to display");
+ }
+ }
+
if (DEBUG_SPEW) {
Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)
+ ", flags=0x" + Integer.toHexString(flags)
@@ -1377,8 +1388,8 @@
mUidState.put(uid, state);
}
state.mNumWakeLocks++;
- wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid,
- state);
+ wakeLock = new WakeLock(lock, displayId, flags, tag, packageName, ws, historyTag,
+ uid, pid, state);
try {
lock.linkToDeath(wakeLock, 0);
} catch (RemoteException ex) {
@@ -2047,6 +2058,11 @@
return mWakefulnessRaw;
}
+ @VisibleForTesting
+ int getWakefulnessLocked(int groupId) {
+ return mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
+ }
+
/**
* Logs the time the device would have spent awake before user activity timeout,
* had the system not been told the user was inactive.
@@ -2293,7 +2309,9 @@
*/
@SuppressWarnings("deprecation")
private void updateWakeLockSummaryLocked(int dirty) {
- if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
+ if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS | DIRTY_DISPLAY_GROUP_WAKEFULNESS))
+ != 0) {
+
mWakeLockSummary = 0;
final int numProfiles = mProfilePowerState.size();
@@ -2301,11 +2319,28 @@
mProfilePowerState.valueAt(i).mWakeLockSummary = 0;
}
+ for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+ mDisplayGroupPowerStateMapper.setWakeLockSummaryLocked(groupId, 0);
+ }
+
+ int invalidGroupWakeLockSummary = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
final int wakeLockFlags = getWakeLockSummaryFlags(wakeLock);
mWakeLockSummary |= wakeLockFlags;
+
+ final int groupId = wakeLock.getDisplayGroupId();
+ if (groupId != Display.INVALID_DISPLAY_GROUP) {
+ int wakeLockSummary = mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(
+ groupId);
+ wakeLockSummary |= wakeLockFlags;
+ mDisplayGroupPowerStateMapper.setWakeLockSummaryLocked(groupId,
+ wakeLockSummary);
+ } else {
+ invalidGroupWakeLockSummary |= wakeLockFlags;
+ }
+
for (int j = 0; j < numProfiles; j++) {
final ProfilePowerState profile = mProfilePowerState.valueAt(j);
if (wakeLockAffectsUser(wakeLock, profile.mUserId)) {
@@ -2314,10 +2349,21 @@
}
}
- mWakeLockSummary = adjustWakeLockSummaryLocked(mWakeLockSummary);
+ for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+ final int wakeLockSummary = adjustWakeLockSummaryLocked(
+ mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId),
+ invalidGroupWakeLockSummary
+ | mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId));
+ mDisplayGroupPowerStateMapper.setWakeLockSummaryLocked(groupId, wakeLockSummary);
+ }
+
+ mWakeLockSummary = adjustWakeLockSummaryLocked(getWakefulnessLocked(),
+ mWakeLockSummary);
+
for (int i = 0; i < numProfiles; i++) {
final ProfilePowerState profile = mProfilePowerState.valueAt(i);
- profile.mWakeLockSummary = adjustWakeLockSummaryLocked(profile.mWakeLockSummary);
+ profile.mWakeLockSummary = adjustWakeLockSummaryLocked(getWakefulnessLocked(),
+ profile.mWakeLockSummary);
}
if (DEBUG_SPEW) {
@@ -2328,25 +2374,25 @@
}
}
- private int adjustWakeLockSummaryLocked(int wakeLockSummary) {
+ private static int adjustWakeLockSummaryLocked(int wakefulness, int wakeLockSummary) {
// Cancel wake locks that make no sense based on the current state.
- if (getWakefulnessLocked() != WAKEFULNESS_DOZING) {
+ if (wakefulness != WAKEFULNESS_DOZING) {
wakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
}
- if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP
+ if (wakefulness == WAKEFULNESS_ASLEEP
|| (wakeLockSummary & WAKE_LOCK_DOZE) != 0) {
wakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
| WAKE_LOCK_BUTTON_BRIGHT);
- if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
+ if (wakefulness == WAKEFULNESS_ASLEEP) {
wakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
}
}
// Infer implied wake locks where necessary based on the current state.
if ((wakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
- if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) {
+ if (wakefulness == WAKEFULNESS_AWAKE) {
wakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
- } else if (getWakefulnessLocked() == WAKEFULNESS_DREAMING) {
+ } else if (wakefulness == WAKEFULNESS_DREAMING) {
wakeLockSummary |= WAKE_LOCK_CPU;
}
}
@@ -2531,7 +2577,8 @@
}
if ((groupUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
- && (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) == 0) {
+ && (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
+ & WAKE_LOCK_STAY_AWAKE) == 0) {
groupNextTimeout = mAttentionDetector.updateUserActivity(groupNextTimeout,
screenDimDuration);
}
@@ -2831,7 +2878,8 @@
private boolean isBeingKeptAwakeLocked(int groupId) {
return mStayOn
|| mProximityPositive
- || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
+ || (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
+ & WAKE_LOCK_STAY_AWAKE) != 0
|| (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId) & (
USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0
|| mScreenBrightnessBoostInProgress;
@@ -3101,8 +3149,8 @@
if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
displayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
- if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0
- && !mDrawWakeLockOverrideFromSidekick) {
+ if ((mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
+ & WAKE_LOCK_DRAW) != 0 && !mDrawWakeLockOverrideFromSidekick) {
if (displayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
displayPowerRequest.dozeScreenState = Display.STATE_DOZE;
}
@@ -3128,7 +3176,8 @@
+ ", mWakefulness="
+ PowerManagerInternal.wakefulnessToString(
mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId))
- + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ + ", mWakeLockSummary=0x" + Integer.toHexString(
+ mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId))
+ ", mUserActivitySummary=0x" + Integer.toHexString(
mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId))
+ ", mBootCompleted=" + mBootCompleted
@@ -3193,10 +3242,11 @@
@VisibleForTesting
int getDesiredScreenPolicyLocked(int groupId) {
final int wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
+ final int wakeLockSummary = mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId);
if (wakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
return DisplayPowerRequest.POLICY_OFF;
} else if (wakefulness == WAKEFULNESS_DOZING) {
- if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
+ if ((wakeLockSummary & WAKE_LOCK_DOZE) != 0) {
return DisplayPowerRequest.POLICY_DOZE;
}
if (mDozeAfterScreenOff) {
@@ -3213,7 +3263,7 @@
return DisplayPowerRequest.POLICY_VR;
}
- if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
+ if ((wakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
|| !mBootCompleted
|| (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId)
& USER_ACTIVITY_SCREEN_BRIGHT) != 0
@@ -3292,7 +3342,9 @@
};
private boolean shouldUseProximitySensorLocked() {
- return !mIsVrModeEnabled && (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
+ // Use default display group for proximity sensor.
+ return !mIsVrModeEnabled && (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(
+ Display.DEFAULT_DISPLAY_GROUP) & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
}
/**
@@ -4248,6 +4300,8 @@
pw.println(" lastUserActivityTimeNoChangeLights=" + TimeUtils.formatUptime(
mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked(
id)));
+ pw.println(" mWakeLockSummary=0x" + Integer.toHexString(
+ mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(id)));
}
wcd = mWirelessChargerDetector;
@@ -4738,6 +4792,7 @@
*/
/* package */ final class WakeLock implements IBinder.DeathRecipient {
public final IBinder mLock;
+ public final int mDisplayId;
public int mFlags;
public String mTag;
public final String mPackageName;
@@ -4751,10 +4806,11 @@
public boolean mNotifiedLong;
public boolean mDisabled;
- public WakeLock(IBinder lock, int flags, String tag, String packageName,
+ public WakeLock(IBinder lock, int displayId, int flags, String tag, String packageName,
WorkSource workSource, String historyTag, int ownerUid, int ownerPid,
UidState uidState) {
mLock = lock;
+ mDisplayId = displayId;
mFlags = flags;
mTag = tag;
mPackageName = packageName;
@@ -4807,6 +4863,15 @@
mWorkSource = copyWorkSource(workSource);
}
+ public int getDisplayGroupId() {
+ if (!mSystemReady || mDisplayId == Display.INVALID_DISPLAY) {
+ return Display.INVALID_DISPLAY_GROUP;
+ }
+
+ final DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
+ return displayInfo == null ? Display.INVALID_DISPLAY_GROUP : displayInfo.displayGroupId;
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@@ -4996,11 +5061,11 @@
@Override // Binder call
public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
- String packageName, int uid) {
+ String packageName, int uid, int displayId) {
if (uid < 0) {
uid = Binder.getCallingUid();
}
- acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null);
+ acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null, displayId);
}
@Override // Binder call
@@ -5035,7 +5100,7 @@
@Override // Binder call
public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
- WorkSource ws, String historyTag) {
+ WorkSource ws, String historyTag, int displayId) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
@@ -5060,7 +5125,8 @@
final int pid = Binder.getCallingPid();
final long ident = Binder.clearCallingIdentity();
try {
- acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
+ acquireWakeLockInternal(lock, displayId, flags, tag, packageName, ws, historyTag,
+ uid, pid);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -5069,7 +5135,7 @@
@Override // Binder call
public void acquireWakeLockAsync(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag) {
- acquireWakeLock(lock, flags, tag, packageName, ws, historyTag);
+ acquireWakeLock(lock, flags, tag, packageName, ws, historyTag, Display.INVALID_DISPLAY);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index a4459d0..4adcfb6 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -615,7 +615,7 @@
if (session == null || session.isStagedSessionFailed()) {
iter.remove();
deleteRollback(rollback,
- "Session " + session.getSessionId() + " not existed or failed");
+ "Session " + rollback.getStagedSessionId() + " not existed or failed");
continue;
}
diff --git a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
index 3f20302..9c8ff68 100644
--- a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
+++ b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
@@ -18,12 +18,12 @@
import static com.android.internal.infra.AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS;
+import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.AppOpsManager;
+import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.speech.IRecognitionListener;
@@ -40,10 +40,6 @@
private static final String TAG = RemoteSpeechRecognitionService.class.getSimpleName();
private static final boolean DEBUG = false;
- private static final String APP_OP_MESSAGE = "Recording audio for speech recognition";
- private static final String RECORD_AUDIO_APP_OP =
- AppOpsManager.permissionToOp(android.Manifest.permission.RECORD_AUDIO);
-
private final Object mLock = new Object();
private boolean mConnected = false;
@@ -53,14 +49,6 @@
@Nullable
@GuardedBy("mLock")
- private String mPackageName;
-
- @Nullable
- @GuardedBy("mLock")
- private String mFeatureId;
-
- @Nullable
- @GuardedBy("mLock")
private DelegatingListener mDelegatingListener;
// Makes sure we can block startListening() if session is still in progress.
@@ -72,7 +60,6 @@
private boolean mRecordingInProgress = false;
private final int mCallingUid;
- private final AppOpsManager mAppOpsManager;
private final ComponentName mComponentName;
RemoteSpeechRecognitionService(
@@ -87,7 +74,6 @@
IRecognitionService.Stub::asInterface);
mCallingUid = callingUid;
- mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mComponentName = serviceName;
if (DEBUG) {
@@ -99,11 +85,12 @@
return mComponentName;
}
- void startListening(Intent recognizerIntent, IRecognitionListener listener, String packageName,
- String featureId) {
+ void startListening(Intent recognizerIntent, IRecognitionListener listener,
+ @NonNull AttributionSource attributionSource) {
if (DEBUG) {
Slog.i(TAG, String.format("#startListening for package: %s, feature=%s, callingUid=%d",
- packageName, featureId, mCallingUid));
+ attributionSource.getPackageName(), attributionSource.getAttributionTag(),
+ mCallingUid));
}
if (listener == null) {
@@ -123,10 +110,6 @@
return;
}
- if (startProxyOp(packageName, featureId) != AppOpsManager.MODE_ALLOWED) {
- tryRespondWithError(listener, SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
- return;
- }
mSessionInProgress = true;
mRecordingInProgress = true;
@@ -141,23 +124,18 @@
resetStateLocked();
}
});
- mPackageName = packageName;
- mFeatureId = featureId;
run(service ->
service.startListening(
recognizerIntent,
mDelegatingListener,
- packageName,
- featureId,
- mCallingUid));
+ attributionSource));
}
}
- void stopListening(
- IRecognitionListener listener, String packageName, String featureId) {
+ void stopListening(IRecognitionListener listener) {
if (DEBUG) {
- Slog.i(TAG, "#stopListening for package: " + packageName + ", feature=" + featureId);
+ Slog.i(TAG, "#stopListening");
}
if (!mConnected) {
@@ -184,19 +162,13 @@
}
mRecordingInProgress = false;
- finishProxyOp(packageName, featureId);
-
- run(service -> service.stopListening(mDelegatingListener, packageName, featureId));
+ run(service -> service.stopListening(mDelegatingListener));
}
}
- void cancel(
- IRecognitionListener listener,
- String packageName,
- String featureId,
- boolean isShutdown) {
+ void cancel(IRecognitionListener listener, boolean isShutdown) {
if (DEBUG) {
- Slog.i(TAG, "#cancel for package: " + packageName + ", feature=" + featureId);
+ Slog.i(TAG, "#cancel");
}
if (!mConnected) {
@@ -220,11 +192,8 @@
// Temporary reference to allow for resetting the hard link mDelegatingListener to null.
IRecognitionListener delegatingListener = mDelegatingListener;
- run(service -> service.cancel(delegatingListener, packageName, featureId, isShutdown));
+ run(service -> service.cancel(delegatingListener, isShutdown));
- if (mRecordingInProgress) {
- finishProxyOp(packageName, featureId);
- }
mRecordingInProgress = false;
mSessionInProgress = false;
@@ -249,7 +218,7 @@
}
}
- cancel(mListener, mPackageName, mFeatureId, true /* isShutdown */);
+ cancel(mListener, true /* isShutdown */);
}
@Override // from ServiceConnector.Impl
@@ -286,40 +255,12 @@
}
private void resetStateLocked() {
- if (mRecordingInProgress && mPackageName != null) {
- finishProxyOp(mPackageName, mFeatureId);
- }
-
mListener = null;
mDelegatingListener = null;
mSessionInProgress = false;
mRecordingInProgress = false;
}
- private int startProxyOp(String packageName, String featureId) {
- final long identity = Binder.clearCallingIdentity();
- try {
- return mAppOpsManager.startProxyOp(
- RECORD_AUDIO_APP_OP,
- mCallingUid,
- packageName,
- featureId,
- APP_OP_MESSAGE);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- private void finishProxyOp(String packageName, String featureId) {
- final long identity = Binder.clearCallingIdentity();
- try {
- mAppOpsManager.finishProxyOp(
- RECORD_AUDIO_APP_OP, mCallingUid, packageName, featureId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
private static void tryRespondWithError(IRecognitionListener listener, int errorCode) {
if (DEBUG) {
Slog.i(TAG, "Responding with error " + errorCode);
diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java
index 52c1467b..22eeb34 100644
--- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java
+++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerService.java
@@ -75,7 +75,7 @@
@Override
protected SpeechRecognitionManagerServiceImpl newServiceLocked(
@UserIdInt int resolvedUserId, boolean disabled) {
- return new SpeechRecognitionManagerServiceImpl(this, mLock, resolvedUserId, disabled);
+ return new SpeechRecognitionManagerServiceImpl(this, mLock, resolvedUserId);
}
final class SpeechRecognitionManagerServiceStub extends IRecognitionServiceManager.Stub {
diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
index 769e049..eee08c2 100644
--- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppGlobals;
+import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -36,8 +37,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.server.infra.AbstractPerUserSystemService;
-import com.google.android.collect.Sets;
-
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -60,7 +59,7 @@
SpeechRecognitionManagerServiceImpl(
@NonNull SpeechRecognitionManagerService master,
- @NonNull Object lock, @UserIdInt int userId, boolean disabled) {
+ @NonNull Object lock, @UserIdInt int userId) {
super(master, lock, userId);
}
@@ -108,10 +107,6 @@
}
final int creatorCallingUid = Binder.getCallingUid();
- Set<String> creatorPackageNames =
- Sets.newArraySet(
- getContext().getPackageManager().getPackagesForUid(creatorCallingUid));
-
RemoteSpeechRecognitionService service = createService(creatorCallingUid, serviceComponent);
if (service == null) {
@@ -127,6 +122,7 @@
} catch (RemoteException e) {
// RemoteException == binder already died, schedule disconnect anyway.
handleClientDeath(creatorCallingUid, service, true /* invoke #cancel */);
+ return;
}
service.connect().thenAccept(binderService -> {
@@ -137,41 +133,24 @@
public void startListening(
Intent recognizerIntent,
IRecognitionListener listener,
- String packageName,
- String featureId,
- int callingUid) throws RemoteException {
- verifyCallerIdentity(
- creatorCallingUid, packageName, creatorPackageNames, listener);
- if (callingUid != creatorCallingUid) {
- listener.onError(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
- return;
- }
-
- service.startListening(
- recognizerIntent, listener, packageName, featureId);
+ @NonNull AttributionSource attributionSource)
+ throws RemoteException {
+ attributionSource.enforceCallingUid();
+ service.startListening(recognizerIntent, listener, attributionSource);
}
@Override
public void stopListening(
- IRecognitionListener listener,
- String packageName,
- String featureId) throws RemoteException {
- verifyCallerIdentity(
- creatorCallingUid, packageName, creatorPackageNames, listener);
-
- service.stopListening(listener, packageName, featureId);
+ IRecognitionListener listener) throws RemoteException {
+ service.stopListening(listener);
}
@Override
public void cancel(
IRecognitionListener listener,
- String packageName,
- String featureId,
boolean isShutdown) throws RemoteException {
- verifyCallerIdentity(
- creatorCallingUid, packageName, creatorPackageNames, listener);
- service.cancel(listener, packageName, featureId, isShutdown);
+ service.cancel(listener, isShutdown);
if (isShutdown) {
handleClientDeath(
@@ -192,17 +171,6 @@
});
}
- private void verifyCallerIdentity(
- int creatorCallingUid,
- String packageName,
- Set<String> creatorPackageNames,
- IRecognitionListener listener) throws RemoteException {
- if (creatorCallingUid != Binder.getCallingUid()
- || !creatorPackageNames.contains(packageName)) {
- listener.onError(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
- }
- }
-
private void handleClientDeath(
int callingUid,
RemoteSpeechRecognitionService service, boolean invokeCancel) {
diff --git a/services/core/java/com/android/server/stats/StatsHelper.java b/services/core/java/com/android/server/stats/StatsHelper.java
new file mode 100644
index 0000000..9b9f6b50
--- /dev/null
+++ b/services/core/java/com/android/server/stats/StatsHelper.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.stats;
+
+import static android.app.StatsManager.ACTION_STATSD_STARTED;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+
+/**
+ * Provides helper methods for the Statsd APEX
+ *
+ * @hide
+ **/
+@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public final class StatsHelper {
+ private StatsHelper() {}
+
+ /**
+ * Send statsd ready broadcast
+ *
+ **/
+ public static void sendStatsdReadyBroadcast(@NonNull final Context context) {
+ context.sendBroadcastAsUser(
+ new Intent(ACTION_STATSD_STARTED).addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND),
+ UserHandle.SYSTEM, android.Manifest.permission.DUMP);
+ }
+}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index a7b9e95..91231c3 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -111,6 +111,7 @@
import android.os.OutcomeReceiver;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
@@ -148,6 +149,7 @@
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BinderCallsStats.ExportedCallStat;
+import com.android.internal.os.DmabufInfoReader;
import com.android.internal.os.KernelCpuBpfTracking;
import com.android.internal.os.KernelCpuThreadReader;
import com.android.internal.os.KernelCpuThreadReaderDiff;
@@ -198,6 +200,7 @@
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -528,6 +531,8 @@
synchronized (mProcessSystemIonHeapSizeLock) {
return pullProcessSystemIonHeapSizeLocked(atomTag, data);
}
+ case FrameworkStatsLog.PROCESS_DMABUF_MEMORY:
+ return pullProcessDmabufMemory(atomTag, data);
case FrameworkStatsLog.SYSTEM_MEMORY:
return pullSystemMemory(atomTag, data);
case FrameworkStatsLog.TEMPERATURE:
@@ -818,6 +823,7 @@
registerIonHeapSize();
registerProcessSystemIonHeapSize();
registerSystemMemory();
+ registerProcessDmabufMemory();
registerTemperature();
registerCoolingDevice();
registerBinderCallsStats();
@@ -2183,6 +2189,43 @@
return StatsManager.PULL_SUCCESS;
}
+ private void registerProcessDmabufMemory() {
+ int tagId = FrameworkStatsLog.PROCESS_DMABUF_MEMORY;
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl
+ );
+ }
+
+ int pullProcessDmabufMemory(int atomTag, List<StatsEvent> pulledData) {
+ List<ProcessMemoryState> managedProcessList =
+ LocalServices.getService(ActivityManagerInternal.class)
+ .getMemoryStateForProcesses();
+ managedProcessList.sort(Comparator.comparingInt(x -> x.oomScore));
+ for (ProcessMemoryState process : managedProcessList) {
+ if (process.uid == Process.SYSTEM_UID) {
+ continue;
+ }
+ DmabufInfoReader.ProcessDmabuf proc = DmabufInfoReader.getProcessStats(process.pid);
+ if (proc == null || (proc.retainedBuffersCount <= 0 && proc.mappedBuffersCount <= 0)) {
+ continue;
+ }
+ pulledData.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ process.uid,
+ process.processName,
+ process.oomScore,
+ proc.retainedSizeKb,
+ proc.retainedBuffersCount,
+ proc.mappedSizeKb,
+ proc.mappedBuffersCount));
+ }
+ return StatsManager.PULL_SUCCESS;
+ }
+
private void registerSystemMemory() {
int tagId = FrameworkStatsLog.SYSTEM_MEMORY;
mStatsManager.setPullAtomCallback(
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 75f06e5..9dc68f2 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -2389,13 +2389,15 @@
private IWallpaperEngine getEngine(int which, int userId, int displayId) {
WallpaperData wallpaperData = findWallpaperAtDisplay(userId, displayId);
if (wallpaperData == null) return null;
+ WallpaperConnection connection = wallpaperData.connection;
+ if (connection == null) return null;
IWallpaperEngine engine = null;
synchronized (mLock) {
- for (int i = 0; i < wallpaperData.connection.mDisplayConnector.size(); i++) {
- int id = wallpaperData.connection.mDisplayConnector.get(i).mDisplayId;
- int currentWhich = wallpaperData.connection.mDisplayConnector.get(i).mDisplayId;
+ for (int i = 0; i < connection.mDisplayConnector.size(); i++) {
+ int id = connection.mDisplayConnector.get(i).mDisplayId;
+ int currentWhich = connection.mDisplayConnector.get(i).mDisplayId;
if (id != displayId && currentWhich != which) continue;
- engine = wallpaperData.connection.mDisplayConnector.get(i).mEngine;
+ engine = connection.mDisplayConnector.get(i).mEngine;
break;
}
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index b947c88..16692e1 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -514,6 +514,18 @@
}
}
+ void onImeSurfaceShownChanged(WindowState windowState, boolean shown) {
+ if (mAccessibilityTracing.isEnabled()) {
+ mAccessibilityTracing.logState(TAG + ".onImeSurfaceShownChanged",
+ "windowState=" + windowState + "; shown=" + shown);
+ }
+ final int displayId = windowState.getDisplayId();
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.onImeSurfaceShownChanged(shown);
+ }
+ }
+
private static void populateTransformationMatrix(WindowState windowState,
Matrix outMatrix) {
windowState.getTransformationMatrix(sTempFloats, outMatrix);
@@ -766,6 +778,15 @@
}
}
+ void onImeSurfaceShownChanged(boolean shown) {
+ if (mAccessibilityTracing.isEnabled()) {
+ mAccessibilityTracing.logState(
+ LOG_TAG + ".onImeSurfaceShownChanged", "shown=" + shown);
+ }
+ mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED,
+ shown ? 1 : 0, 0).sendToTarget();
+ }
+
MagnificationSpec getMagnificationSpecForWindow(WindowState windowState) {
if (mAccessibilityTracing.isEnabled()) {
mAccessibilityTracing.logState(LOG_TAG + ".getMagnificationSpecForWindow",
@@ -1337,6 +1358,7 @@
public static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3;
public static final int MESSAGE_NOTIFY_ROTATION_CHANGED = 4;
public static final int MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED = 5;
+ public static final int MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED = 6;
MyHandler(Looper looper) {
super(looper);
@@ -1380,6 +1402,11 @@
}
}
} break;
+
+ case MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED: {
+ final boolean shown = message.arg1 == 1;
+ mCallbacks.onImeWindowVisibilityChanged(shown);
+ } break;
}
}
}
@@ -2123,5 +2150,4 @@
}
}
}
-
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index eadfbe2..f0c4a15 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2880,6 +2880,9 @@
mAtmService.deferWindowLayout();
try {
+ final Transition newTransition = (!mAtmService.getTransitionController().isCollecting()
+ && mAtmService.getTransitionController().getTransitionPlayer() != null)
+ ? mAtmService.getTransitionController().createTransition(TRANSIT_CLOSE) : null;
makeFinishingLocked();
// Make a local reference to its task since this.task could be set to null once this
// activity is destroyed and detached from task.
@@ -2911,6 +2914,10 @@
final boolean endTask = task.getTopNonFinishingActivity() == null
&& !task.isClearingToReuseTask();
final int transit = endTask ? TRANSIT_OLD_TASK_CLOSE : TRANSIT_OLD_ACTIVITY_CLOSE;
+ if (newTransition != null) {
+ mAtmService.getTransitionController().requestStartTransition(newTransition,
+ endTask ? task : null, null /* remote */);
+ }
if (isState(RESUMED)) {
if (endTask) {
mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 18e5552..0efadcf 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1816,7 +1816,8 @@
}
private Task computeTargetTask() {
- if (mInTask == null && !mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
+ if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
+ && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
// A new task should be created instead of using existing one.
return null;
} else if (mSourceRecord != null) {
@@ -2516,9 +2517,7 @@
// If bring to front is requested, and no result is requested and we have not been given
// an explicit task to launch in to, and we can find a task that was started with this
// same component, then instead of launching bring that one to the front.
- putIntoExistingTask &= !isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)
- ? (mInTask == null && mStartActivity.resultTo == null)
- : (mInTask == null);
+ putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
ActivityRecord intentActivity = null;
if (putIntoExistingTask) {
if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
diff --git a/services/core/java/com/android/server/wm/DisplayHashController.java b/services/core/java/com/android/server/wm/DisplayHashController.java
index 1262dee..5a8af45 100644
--- a/services/core/java/com/android/server/wm/DisplayHashController.java
+++ b/services/core/java/com/android/server/wm/DisplayHashController.java
@@ -17,7 +17,9 @@
package com.android.server.wm;
import static android.service.displayhash.DisplayHasherService.EXTRA_VERIFIED_DISPLAY_HASH;
+import static android.service.displayhash.DisplayHasherService.SERVICE_META_DATA;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM;
+import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_TOO_MANY_REQUESTS;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH_ERROR_CODE;
@@ -34,6 +36,9 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -49,15 +54,22 @@
import android.service.displayhash.DisplayHashParams;
import android.service.displayhash.DisplayHasherService;
import android.service.displayhash.IDisplayHasherService;
+import android.util.AttributeSet;
import android.util.Size;
import android.util.Slog;
+import android.util.Xml;
import android.view.MagnificationSpec;
import android.view.SurfaceControl;
import android.view.displayhash.DisplayHash;
import android.view.displayhash.VerifiedDisplayHash;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@@ -102,6 +114,41 @@
private final Matrix mTmpMatrix = new Matrix();
private final RectF mTmpRectF = new RectF();
+ /**
+ * Lock used when retrieving xml metadata. Lock when retrieving the xml data the first time
+ * since it will be cached after that. Check if {@link #mParsedXml} is set to determine if the
+ * metadata needs to retrieved.
+ */
+ private final Object mParseXmlLock = new Object();
+
+ /**
+ * Flag whether the xml metadata has been retrieved and parsed. Once this is set to true,
+ * there's no need to request metadata again.
+ */
+ @GuardedBy("mParseXmlLock")
+ private boolean mParsedXml;
+
+ /**
+ * Specified throttle time in milliseconds. Don't allow an app to generate a display hash more
+ * than once per throttleTime
+ */
+ private int mThrottleDurationMillis = 0;
+
+ /**
+ * The last time an app requested to generate a display hash in System time.
+ */
+ private long mLastRequestTimeMs;
+
+ /**
+ * The last uid that requested to generate a hash.
+ */
+ private int mLastRequestUid;
+
+ /**
+ * Only used for testing. Throttling should always be enabled unless running tests
+ */
+ private boolean mDisplayHashThrottlingEnabled = true;
+
private interface Command {
void run(IDisplayHasherService service) throws RemoteException;
}
@@ -131,6 +178,10 @@
return results.getParcelable(EXTRA_VERIFIED_DISPLAY_HASH);
}
+ void setDisplayHashThrottlingEnabled(boolean enable) {
+ mDisplayHashThrottlingEnabled = enable;
+ }
+
private void generateDisplayHash(HardwareBuffer buffer, Rect bounds,
String hashAlgorithm, RemoteCallback callback) {
connectAndRun(
@@ -138,8 +189,36 @@
callback));
}
+ private boolean allowedToGenerateHash(int uid) {
+ if (!mDisplayHashThrottlingEnabled) {
+ // Always allow to generate the hash. This is used to allow tests to run without
+ // waiting on the designated threshold.
+ return true;
+ }
+
+ long currentTime = System.currentTimeMillis();
+ if (mLastRequestUid != uid) {
+ mLastRequestUid = uid;
+ mLastRequestTimeMs = currentTime;
+ return true;
+ }
+
+ int throttleDurationMs = getThrottleDurationMillis();
+ if (currentTime - mLastRequestTimeMs < throttleDurationMs) {
+ return false;
+ }
+
+ mLastRequestTimeMs = currentTime;
+ return true;
+ }
+
void generateDisplayHash(SurfaceControl.LayerCaptureArgs.Builder args,
- Rect boundsInWindow, String hashAlgorithm, RemoteCallback callback) {
+ Rect boundsInWindow, String hashAlgorithm, int uid, RemoteCallback callback) {
+ if (!allowedToGenerateHash(uid)) {
+ sendDisplayHashError(callback, DISPLAY_HASH_ERROR_TOO_MANY_REQUESTS);
+ return;
+ }
+
final Map<String, DisplayHashParams> displayHashAlgorithmsMap = getDisplayHashAlgorithms();
DisplayHashParams displayHashParams = displayHashAlgorithmsMap.get(hashAlgorithm);
if (displayHashParams == null) {
@@ -277,6 +356,64 @@
}
}
+ private int getThrottleDurationMillis() {
+ if (!parseXmlProperties()) {
+ return 0;
+ }
+ return mThrottleDurationMillis;
+ }
+
+ private boolean parseXmlProperties() {
+ // We have a separate lock for the xml parsing since it doesn't need to make the
+ // request through the service connection. Instead, we have a lock to ensure we can
+ // properly cache the xml metadata so we don't need to call into the ExtServices
+ // process for each request.
+ synchronized (mParseXmlLock) {
+ if (mParsedXml) {
+ return true;
+ }
+
+ final ServiceInfo serviceInfo = getServiceInfo();
+ if (serviceInfo == null) return false;
+
+ final PackageManager pm = mContext.getPackageManager();
+
+ XmlResourceParser parser;
+ parser = serviceInfo.loadXmlMetaData(pm, SERVICE_META_DATA);
+ if (parser == null) {
+ return false;
+ }
+
+ Resources res;
+ try {
+ res = pm.getResourcesForApplication(serviceInfo.applicationInfo);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+
+ int type;
+ while (true) {
+ try {
+ if (!((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG)) {
+ break;
+ }
+ } catch (XmlPullParserException | IOException e) {
+ return false;
+ }
+ }
+
+ TypedArray sa = res.obtainAttributes(attrs, R.styleable.DisplayHasherService);
+ mThrottleDurationMillis = sa.getInt(
+ R.styleable.DisplayHasherService_throttleDurationMillis, 0);
+ sa.recycle();
+ mParsedXml = true;
+ return true;
+ }
+ }
+
/**
* Run a command, starting the service connection if necessary.
*/
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 6046cc6..9ff701c 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -1539,20 +1539,6 @@
}
}
- @Override
- public boolean canUseRotationResolver() {
- if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
-
- switch (mCurrentAppOrientation) {
- case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
- case ActivityInfo.SCREEN_ORIENTATION_USER:
- case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
- case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
- case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
- return true;
- }
- return false;
- }
@Override
public void onProposedRotationChanged(int rotation) {
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 28c5a6d9..6f2f698 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -404,8 +404,8 @@
}
if (!focus.mWinAnimator.hasSurface() || !focus.mInputWindowHandle.isFocusable()) {
- Slog.v(TAG_WM, "Focus not requested for window=%" + focus
- + " because it has no surface or is not focusable.");
+ ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Focus not requested for window=%s"
+ + " because it has no surface or is not focusable.", focus);
mInputFocus = null;
return;
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index bd84854..87854c2 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -20,10 +20,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-import static android.graphics.Matrix.MSCALE_X;
-import static android.graphics.Matrix.MSCALE_Y;
-import static android.graphics.Matrix.MSKEW_X;
-import static android.graphics.Matrix.MSKEW_Y;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
@@ -40,6 +36,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.WindowConfiguration;
+import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
@@ -59,6 +56,7 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.WindowInsets.Type;
+import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
import com.android.internal.annotations.VisibleForTesting;
@@ -233,8 +231,8 @@
}
@Override
- public void setFinishTaskBounds(int taskId, Rect destinationBounds, Rect windowCrop,
- float[] float9) {
+ public void setFinishTaskBounds(int taskId, Rect destinationBounds,
+ PictureInPictureSurfaceTransaction finishTransaction) {
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
"setFinishTaskBounds(%d): bounds=%s", taskId, destinationBounds);
final long token = Binder.clearCallingIdentity();
@@ -244,8 +242,7 @@
final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
if (taskAdapter.mTask.mTaskId == taskId) {
taskAdapter.mFinishBounds.set(destinationBounds);
- taskAdapter.mFinishWindowCrop.set(windowCrop);
- taskAdapter.mFinishTransform = float9;
+ taskAdapter.mFinishTransaction = finishTransaction;
break;
}
}
@@ -1098,8 +1095,7 @@
// The bounds of the target when animation is finished
private final Rect mFinishBounds = new Rect();
// Bounds and transform for the final transaction.
- private final Rect mFinishWindowCrop = new Rect();
- private float[] mFinishTransform;
+ private PictureInPictureSurfaceTransaction mFinishTransaction;
TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
mTask = task;
@@ -1138,29 +1134,25 @@
if (!mFinishBounds.isEmpty()) {
final SurfaceControl taskSurface = mTask.mSurfaceControl;
final Transaction pendingTransaction = mTask.getPendingTransaction();
- if (mFinishTransform != null) {
- pendingTransaction
- .setMatrix(taskSurface,
- mFinishTransform[MSCALE_X], mFinishTransform[MSKEW_Y],
- mFinishTransform[MSKEW_X], mFinishTransform[MSCALE_Y]);
- }
- float left = mFinishBounds.left;
- float top = mFinishBounds.top;
- if (!mFinishWindowCrop.isEmpty()) {
- pendingTransaction.setWindowCrop(taskSurface, mFinishWindowCrop);
- if (mFinishTransform != null) {
- // adjust the position for insets.
- left -= mFinishWindowCrop.left * mFinishTransform[MSCALE_X];
- top -= mFinishWindowCrop.top * mFinishTransform[MSCALE_Y];
+ if (mFinishTransaction != null) {
+ final Matrix matrix = new Matrix();
+ matrix.setScale(mFinishTransaction.mScaleX, mFinishTransaction.mScaleY);
+ if (mFinishTransaction.mRotation != 0) {
+ matrix.postRotate(mFinishTransaction.mRotation);
}
+ pendingTransaction.setMatrix(taskSurface, matrix, new float[9])
+ .setPosition(taskSurface,
+ mFinishTransaction.mPositionX, mFinishTransaction.mPositionY)
+ .setWindowCrop(taskSurface, mFinishTransaction.getWindowCrop())
+ .setCornerRadius(taskSurface, mFinishTransaction.mCornerRadius);
+ mTask.mLastRecentsAnimationBounds.set(mFinishBounds);
+ mFinishTransaction = null;
+ } else {
+ pendingTransaction
+ .setPosition(taskSurface, mFinishBounds.left, mFinishBounds.top)
+ .setWindowCrop(taskSurface, mFinishBounds);
}
- pendingTransaction
- .setPosition(taskSurface, left, top)
- .apply();
- mTask.mLastRecentsAnimationBounds.set(mFinishBounds);
- // reset the variables
- mFinishTransform = null;
- mFinishWindowCrop.setEmpty();
+ pendingTransaction.apply();
mFinishBounds.setEmpty();
} else if (!mTask.isAttached()) {
// Apply the task's pending transaction in case it is detached and its transaction
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 7261048..52551ec 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -3363,46 +3363,19 @@
}
/**
- * Find all visible tasks containing {@param userId} and intercept them with an activity
+ * Find all tasks containing {@param userId} and intercept them with an activity
* to block out the contents and possibly start a credential-confirming intent.
*
* @param userId user handle for the locked managed profile.
*/
void lockAllProfileTasks(@UserIdInt int userId) {
- mService.deferWindowLayout();
- try {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- RootWindowContainer::taskTopActivityIsUser, this, PooledLambda.__(Task.class),
- userId);
- forAllLeafTasks(c, true /* traverseTopToBottom */);
- c.recycle();
- } finally {
- mService.continueWindowLayout();
- }
- }
-
- /**
- * Detects whether we should show a lock screen in front of this task for a locked user.
- * <p>
- * We'll do this if either of the following holds:
- * <ul>
- * <li>The top activity explicitly belongs to {@param userId}.</li>
- * <li>The top activity returns a result to an activity belonging to {@param userId}.</li>
- * </ul>
- */
- private void taskTopActivityIsUser(Task task, @UserIdInt int userId) {
- // To handle the case that work app is in the task but just is not the top one.
- final ActivityRecord activityRecord = task.getTopNonFinishingActivity();
- final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
-
- // Check the task for a top activity belonging to userId, or returning a
- // result to an activity belonging to userId. Example case: a document
- // picker for personal files, opened by a work app, should still get locked.
- if ((activityRecord != null && activityRecord.mUserId == userId)
- || (resultTo != null && resultTo.mUserId == userId)) {
- mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
- task.mTaskId, userId);
- }
+ forAllLeafTasks(task -> {
+ if (task.getActivity(activity -> !activity.finishing && activity.mUserId == userId)
+ != null) {
+ mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
+ task.mTaskId, userId);
+ }
+ }, true /* traverseTopToBottom */);
}
void cancelInitializingActivities() {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index a4a0866..b36c25c 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -6060,12 +6060,10 @@
int idx = mChildren.size() - 1;
while (idx >= 0) {
final Task child = (Task) getChildAt(idx--);
- if (!child.isFocusableAndVisible()) {
- break;
+ if (!child.isTopActivityFocusable()) {
+ continue;
}
-
- // Only allow one activity to be resumed among sibling tasks in split-screen.
- if (inSplitScreenWindowingMode() && someActivityResumed) {
+ if (child.getVisibility(null /* starting */) != TASK_VISIBILITY_VISIBLE) {
break;
}
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 88e9ae9..3799067 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -346,6 +346,12 @@
position = findPositionForRootTask(position, task, true /* adding */);
super.addChild(task, position);
+ if (mPreferredTopFocusableRootTask != null
+ && task.isFocusable()
+ && mPreferredTopFocusableRootTask.compareTo(task) < 0) {
+ // Clear preferred top because the adding focusable task has a higher z-order.
+ mPreferredTopFocusableRootTask = null;
+ }
mAtmService.updateSleepIfNeededLocked();
onRootTaskOrderChanged(task);
}
@@ -439,6 +445,11 @@
// Update the top resumed activity because the preferred top focusable task may be changed.
mAtmService.mTaskSupervisor.updateTopResumedActivityIfNeeded();
+ final ActivityRecord r = child.getResumedActivity();
+ if (r != null && r == mRootWindowContainer.getTopResumedActivity()) {
+ mAtmService.setResumedActivityUncheckLocked(r, "positionChildAt");
+ }
+
if (mChildren.indexOf(child) != oldPosition) {
onRootTaskOrderChanged(child);
}
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 717775605..194f48f 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -19,7 +19,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -177,7 +177,7 @@
void commitVisibility(boolean visible) {
if (visible == isVisible()) return;
- ProtoLog.v(WM_DEBUG_WINDOW_TRANSITIONS,
+ ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
"commitVisibility: %s: visible=%b mVisibleRequested=%b", this,
isVisible(), mVisibleRequested);
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 8148f15..ab515d4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -113,7 +113,7 @@
*
* @param magnificationRegion the current magnification region
*/
- public void onMagnificationRegionChanged(Region magnificationRegion);
+ void onMagnificationRegionChanged(Region magnificationRegion);
/**
* Called when an application requests a rectangle on the screen to allow
@@ -124,20 +124,27 @@
* @param right The rectangle right.
* @param bottom The rectangle bottom.
*/
- public void onRectangleOnScreenRequested(int left, int top, int right, int bottom);
+ void onRectangleOnScreenRequested(int left, int top, int right, int bottom);
/**
* Notifies that the rotation changed.
*
* @param rotation The current rotation.
*/
- public void onRotationChanged(int rotation);
+ void onRotationChanged(int rotation);
/**
* Notifies that the context of the user changed. For example, an application
* was started.
*/
- public void onUserContextChanged();
+ void onUserContextChanged();
+
+ /**
+ * Notifies that the IME window visibility changed.
+ * @param shown {@code true} means the IME window shows on the screen. Otherwise it's
+ * hidden.
+ */
+ void onImeWindowVisibilityChanged(boolean shown);
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d494b75..a670b39 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8626,6 +8626,14 @@
return mDisplayHashController.verifyDisplayHash(displayHash);
}
+ @Override
+ public void setDisplayHashThrottlingEnabled(boolean enable) {
+ if (!checkCallingPermission(READ_FRAME_BUFFER, "setDisplayHashThrottle()")) {
+ throw new SecurityException("Requires READ_FRAME_BUFFER permission");
+ }
+ mDisplayHashController.setDisplayHashThrottlingEnabled(enable);
+ }
+
void generateDisplayHash(Session session, IWindow window, Rect boundsInWindow,
String hashAlgorithm, RemoteCallback callback) {
final SurfaceControl displaySurfaceControl;
@@ -8639,6 +8647,13 @@
return;
}
+ if (win.mActivityRecord == null || !win.mActivityRecord.isState(
+ Task.ActivityState.RESUMED)) {
+ mDisplayHashController.sendDisplayHashError(callback,
+ DISPLAY_HASH_ERROR_MISSING_WINDOW);
+ return;
+ }
+
DisplayContent displayContent = win.getDisplayContent();
if (displayContent == null) {
Slog.w(TAG, "Failed to generate DisplayHash. Window is not on a display");
@@ -8669,8 +8684,8 @@
.setUid(uid)
.setSourceCrop(boundsInDisplay);
- mDisplayHashController.generateDisplayHash(args, boundsInWindow,
- hashAlgorithm, callback);
+ mDisplayHashController.generateDisplayHash(args, boundsInWindow, hashAlgorithm, uid,
+ callback);
}
boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index e3d549b..2e37fee 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT;
+import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_LAUNCH_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS;
@@ -38,6 +39,7 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Binder;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
@@ -191,6 +193,15 @@
if (type < 0) {
throw new IllegalArgumentException("Can't create transition with no type");
}
+ if (mTransitionController.getTransitionPlayer() == null) {
+ Slog.w(TAG, "Using shell transitions API for legacy transitions.");
+ if (t == null) {
+ throw new IllegalArgumentException("Can't use legacy transitions in"
+ + " compatibility mode with no WCT.");
+ }
+ applyTransaction(t, -1 /* syncId */, null);
+ return null;
+ }
transition = mTransitionController.createTransition(type);
}
transition.start();
@@ -346,6 +357,15 @@
}
}
effects |= sanitizeAndApplyHierarchyOp(wc, hop);
+ break;
+ case HIERARCHY_OP_TYPE_LAUNCH_TASK:
+ Bundle launchOpts = hop.getLaunchOptions();
+ int taskId = launchOpts.getInt(
+ WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
+ launchOpts.remove(
+ WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
+ mService.startActivityFromRecents(taskId, launchOpts);
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowOrientationListener.java b/services/core/java/com/android/server/wm/WindowOrientationListener.java
index 49e704f..b971cab 100644
--- a/services/core/java/com/android/server/wm/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/wm/WindowOrientationListener.java
@@ -275,19 +275,6 @@
}
}
- /**
- * Returns true if the current status of the phone is suitable for using rotation resolver
- * service.
- *
- * To reduce the power consumption of rotation resolver service, rotation query should run less
- * frequently than other low power orientation sensors. This method is used to check whether
- * the current status of the phone is necessary to request a suggested screen rotation from the
- * rotation resolver service. Note that it always returns {@code false} in the base class. It
- * should be overridden in the derived classes.
- */
- public boolean canUseRotationResolver() {
- return false;
- }
/**
* Returns true if the rotation resolver feature is enabled by setting. It means {@link
@@ -1155,7 +1142,7 @@
}
}
- if (isRotationResolverEnabled() && canUseRotationResolver()) {
+ if (isRotationResolverEnabled()) {
if (mRotationResolverService == null) {
mRotationResolverService = LocalServices.getService(
RotationResolverInternal.class);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index eb83152..92c9522 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3462,6 +3462,9 @@
if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST) {
mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown);
}
+ if (mIsImWindow && mWmService.mAccessibilityController != null) {
+ mWmService.mAccessibilityController.onImeSurfaceShownChanged(this, shown);
+ }
}
private void logExclusionRestrictions(int side) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 56e2385..a419bf8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -16,6 +16,7 @@
package com.android.server.devicepolicy;
+import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_DISABLED;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
@@ -69,6 +70,10 @@
"disable-bt-contacts-sharing";
private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
+ private static final String TAG_NEARBY_NOTIFICATION_STREAMING_POLICY =
+ "nearby-notification-streaming-policy";
+ private static final String TAG_NEARBY_APP_STREAMING_POLICY =
+ "nearby-app-streaming-policy";
private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
private static final String TAG_FORCE_EPHEMERAL_USERS = "force_ephemeral_users";
private static final String TAG_IS_NETWORK_LOGGING_ENABLED = "is_network_logging_enabled";
@@ -159,6 +164,12 @@
@DevicePolicyManager.PasswordComplexity
int mPasswordComplexity = PASSWORD_COMPLEXITY_NONE;
+ @DevicePolicyManager.NearbyStreamingPolicy
+ int mNearbyNotificationStreamingPolicy = NEARBY_STREAMING_DISABLED;
+
+ @DevicePolicyManager.NearbyStreamingPolicy
+ int mNearbyAppStreamingPolicy = NEARBY_STREAMING_DISABLED;
+
@Nullable
FactoryResetProtectionPolicy mFactoryResetProtectionPolicy = null;
@@ -549,6 +560,14 @@
if (mPasswordComplexity != PASSWORD_COMPLEXITY_NONE) {
writeAttributeValueToXml(out, TAG_PASSWORD_COMPLEXITY, mPasswordComplexity);
}
+ if (mNearbyNotificationStreamingPolicy != NEARBY_STREAMING_DISABLED) {
+ writeAttributeValueToXml(out, TAG_NEARBY_NOTIFICATION_STREAMING_POLICY,
+ mNearbyNotificationStreamingPolicy);
+ }
+ if (mNearbyAppStreamingPolicy != NEARBY_STREAMING_DISABLED) {
+ writeAttributeValueToXml(out, TAG_NEARBY_APP_STREAMING_POLICY,
+ mNearbyAppStreamingPolicy);
+ }
if (!TextUtils.isEmpty(mOrganizationId)) {
writeTextToXml(out, TAG_ORGANIZATION_ID, mOrganizationId);
}
@@ -794,6 +813,10 @@
mCommonCriteriaMode = parser.getAttributeBoolean(null, ATTR_VALUE, false);
} else if (TAG_PASSWORD_COMPLEXITY.equals(tag)) {
mPasswordComplexity = parser.getAttributeInt(null, ATTR_VALUE);
+ } else if (TAG_NEARBY_NOTIFICATION_STREAMING_POLICY.equals(tag)) {
+ mNearbyNotificationStreamingPolicy = parser.getAttributeInt(null, ATTR_VALUE);
+ } else if (TAG_NEARBY_APP_STREAMING_POLICY.equals(tag)) {
+ mNearbyAppStreamingPolicy = parser.getAttributeInt(null, ATTR_VALUE);
} else if (TAG_ORGANIZATION_ID.equals(tag)) {
type = parser.next();
if (type == TypedXmlPullParser.TEXT) {
@@ -1154,6 +1177,12 @@
pw.print("mPasswordComplexity=");
pw.println(mPasswordComplexity);
+ pw.print("mNearbyNotificationStreamingPolicy=");
+ pw.println(mNearbyNotificationStreamingPolicy);
+
+ pw.print("mNearbyAppStreamingPolicy=");
+ pw.println(mNearbyAppStreamingPolicy);
+
if (!TextUtils.isEmpty(mOrganizationId)) {
pw.print("mOrganizationId=");
pw.println(mOrganizationId);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8739a01..1858712 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -63,6 +63,7 @@
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
+import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_DISABLED;
import static android.app.admin.DevicePolicyManager.NON_ORG_OWNED_PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
import static android.app.admin.DevicePolicyManager.OPERATION_SAFETY_REASON_NONE;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
@@ -7472,6 +7473,78 @@
});
}
+ @Override
+ public void setNearbyNotificationStreamingPolicy(int policy) {
+ if (!mHasFeature) {
+ return;
+ }
+
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
+ synchronized (getLockObject()) {
+ final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
+ if (admin.mNearbyNotificationStreamingPolicy != policy) {
+ admin.mNearbyNotificationStreamingPolicy = policy;
+ saveSettingsLocked(caller.getUserId());
+ }
+ }
+ }
+
+ @Override
+ public int getNearbyNotificationStreamingPolicy() {
+ if (!mHasFeature) {
+ return NEARBY_STREAMING_DISABLED;
+ }
+
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(
+ isDeviceOwner(caller)
+ || isProfileOwner(caller)
+ || hasCallingOrSelfPermission(permission.READ_NEARBY_STREAMING_POLICY));
+
+ synchronized (getLockObject()) {
+ final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
+ return admin.mNearbyNotificationStreamingPolicy;
+ }
+ }
+
+ @Override
+ public void setNearbyAppStreamingPolicy(int policy) {
+ if (!mHasFeature) {
+ return;
+ }
+
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
+ synchronized (getLockObject()) {
+ final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
+ if (admin.mNearbyAppStreamingPolicy != policy) {
+ admin.mNearbyAppStreamingPolicy = policy;
+ saveSettingsLocked(caller.getUserId());
+ }
+ }
+ }
+
+ @Override
+ public int getNearbyAppStreamingPolicy() {
+ if (!mHasFeature) {
+ return NEARBY_STREAMING_DISABLED;
+ }
+
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(
+ isDeviceOwner(caller)
+ || isProfileOwner(caller)
+ || hasCallingOrSelfPermission(permission.READ_NEARBY_STREAMING_POLICY));
+
+ synchronized (getLockObject()) {
+ final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
+ return admin.mNearbyAppStreamingPolicy;
+ }
+ }
+
/**
* Set whether auto time is required by the specified admin (must be device or profile owner).
*/
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 29aedce..1208ecc 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -30,6 +30,8 @@
import android.os.ServiceManager;
import android.os.UpdateEngine;
import android.os.UpdateEngineCallback;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.DeviceConfig;
import android.util.Log;
@@ -301,10 +303,18 @@
new Thread(() -> {
try {
- String reportPath = mIProfcollect.report();
+ String reportUuid = mIProfcollect.report();
+
if (!uploadReport) {
return;
}
+
+ final int profileId = getBBProfileId();
+ mIProfcollect.copy_report_to_bb(profileId, reportUuid);
+ String reportPath =
+ "/data/user/" + profileId
+ + "/com.google.android.apps.internal.betterbug/cache/"
+ + reportUuid + ".zip";
Intent uploadIntent =
new Intent("com.google.android.apps.betterbug.intent.action.UPLOAD_PROFILE")
.setPackage("com.google.android.apps.internal.betterbug")
@@ -316,9 +326,27 @@
if (context.getPackageManager().queryBroadcastReceivers(uploadIntent, 0) != null) {
context.sendBroadcast(uploadIntent);
}
+ mIProfcollect.delete_report(reportUuid);
} catch (RemoteException e) {
Log.e(LOG_TAG, e.getMessage());
}
}).start();
}
+
+ /**
+ * Get BetterBug's profile ID. It is the work profile ID, if it exists. Otherwise the system
+ * user ID.
+ *
+ * @return BetterBug's profile ID.
+ */
+ private int getBBProfileId() {
+ UserManager userManager = UserManager.get(getContext());
+ int[] profiles = userManager.getProfileIds(UserHandle.USER_SYSTEM, false);
+ for (int p : profiles) {
+ if (userManager.getUserInfo(p).isManagedProfile()) {
+ return p;
+ }
+ }
+ return UserHandle.USER_SYSTEM;
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 7a3a950..647ea13 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -16,8 +16,6 @@
package com.android.server.appop;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
-import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
-import static android.app.AppOpsManager.FILTER_BY_UID;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
@@ -44,7 +42,6 @@
import static org.mockito.ArgumentMatchers.nullable;
import android.app.ActivityManager;
-import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.PackageOps;
import android.content.ContentResolver;
@@ -53,7 +50,6 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
-import android.os.RemoteCallback;
import android.provider.Settings;
import androidx.test.InstrumentationRegistry;
@@ -66,6 +62,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.quality.Strictness;
@@ -73,9 +70,6 @@
import java.io.File;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
/**
* Unit tests for AppOpsService. Covers functionality that is difficult to test using CTS tests
@@ -229,6 +223,7 @@
// Tests that ops are persisted during shutdown.
@Test
+ @Ignore("b/183523911")
public void testShutdown() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
diff --git a/services/tests/mockingservicestests/src/com/android/server/usage/UserUsageStatsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/usage/UserUsageStatsServiceTest.java
index d786a5d..24c58f4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/usage/UserUsageStatsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/usage/UserUsageStatsServiceTest.java
@@ -106,7 +106,9 @@
@Test
public void testReportEvent_packageUsedEventNotTracked() {
- Event event = new Event(APP_COMPONENT_USED, SystemClock.elapsedRealtime());
+ // For APP_COMPONENT_USED event, the time stamp should have been converted to current time
+ // before reported here.
+ Event event = new Event(APP_COMPONENT_USED, System.currentTimeMillis());
event.mPackage = TEST_PACKAGE_NAME;
mService.reportEvent(event);
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 9513c6e..7c30b45 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -91,6 +91,7 @@
<uses-permission android:name="android.permission.VIBRATE_ALWAYS_ON"/>
<uses-permission android:name="android.permission.CONTROL_DEVICE_STATE"/>
<uses-permission android:name="android.permission.READ_PROJECTION_STATE"/>
+ <uses-permission android:name="android.permission.KILL_UID"/>
<!-- Uses API introduced in O (26) -->
<uses-sdk android:minSdkVersion="1"
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index d34f783..5a0f1ee 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -23,7 +23,9 @@
<option name="test-file-name" value="JobTestApp.apk" />
<option name="test-file-name" value="ConnTestApp.apk" />
<option name="test-file-name" value="SuspendTestApp.apk" />
- <option name="test-file-name" value="SimpleServiceTestApp.apk" />
+ <option name="test-file-name" value="SimpleServiceTestApp1.apk" />
+ <option name="test-file-name" value="SimpleServiceTestApp2.apk" />
+ <option name="test-file-name" value="SimpleServiceTestApp3.apk" />
</target_preparer>
<option name="test-tag" value="FrameworksServicesTests" />
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index 29691fb..502f64a 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -16,7 +16,7 @@
package com.android.server.accessibility.magnification;
-import static com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationRequestObserver;
+import static com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -96,8 +96,8 @@
final WindowManagerInternal mMockWindowManager = mock(WindowManagerInternal.class);
private final MagnificationAnimationCallback mAnimationCallback = mock(
MagnificationAnimationCallback.class);
- private final MagnificationRequestObserver mRequestObserver = mock(
- MagnificationRequestObserver.class);
+ private final MagnificationInfoChangedCallback mRequestObserver = mock(
+ MagnificationInfoChangedCallback.class);
final MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(null);
ValueAnimator mMockValueAnimator;
@@ -1145,6 +1145,15 @@
verify(mRequestObserver).onFullScreenMagnificationActivationState(eq(false));
}
+ @Test
+ public void testImeWindowIsShown_serviceNotified() {
+ register(DISPLAY_0);
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(DISPLAY_0);
+ callbacks.onImeWindowVisibilityChanged(true);
+ mMessageCapturingHandler.sendAllMessages();
+ verify(mRequestObserver).onImeWindowVisibilityChanged(eq(true));
+ }
+
private void setScaleToMagnifying() {
register(DISPLAY_0);
float scale = 2.0f;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index 28a6ff7..f881f04 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -53,7 +53,7 @@
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.accessibility.EventStreamTransformation;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationRequestObserver;
+import com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
import com.android.server.testutils.OffsettableClock;
import com.android.server.testutils.TestHandler;
import com.android.server.wm.WindowManagerInternal;
@@ -126,7 +126,7 @@
@Mock
MagnificationGestureHandler.Callback mMockCallback;
@Mock
- MagnificationRequestObserver mMagnificationRequestObserver;
+ MagnificationInfoChangedCallback mMagnificationInfoChangedCallback;
@Mock
WindowMagnificationPromptController mWindowMagnificationPromptController;
@@ -151,7 +151,7 @@
when(mockController.getAnimationDuration()).thenReturn(1000L);
when(mockWindowManager.setMagnificationCallbacks(eq(DISPLAY_0), any())).thenReturn(true);
mFullScreenMagnificationController = new FullScreenMagnificationController(mockController,
- new Object(), mMagnificationRequestObserver) {
+ new Object(), mMagnificationInfoChangedCallback) {
@Override
public boolean magnificationRegionContains(int displayId, float x, float y) {
return true;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index cf23197..3dff36e 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -486,6 +486,47 @@
eq(MODE_WINDOW));
}
+ @Test
+ public void imeWindowStateShown_windowMagnifying_logWindowMode() {
+ mMagnificationController.onWindowMagnificationActivationState(true);
+
+ mMagnificationController.onImeWindowVisibilityChanged(true);
+
+ verify(mMagnificationController).logMagnificationModeWithIme(
+ eq(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
+ }
+
+ @Test
+ public void imeWindowStateShown_fullScreenMagnifying_logFullScreenMode() {
+ mMagnificationController.onFullScreenMagnificationActivationState(true);
+
+ mMagnificationController.onImeWindowVisibilityChanged(true);
+
+ verify(mMagnificationController).logMagnificationModeWithIme(
+ eq(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
+ }
+
+ @Test
+ public void imeWindowStateShown_noMagnifying_noLogAnyMode() {
+ mMagnificationController.onImeWindowVisibilityChanged(true);
+
+ verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt());
+ }
+
+ @Test
+ public void imeWindowStateHidden_windowMagnifying_noLogAnyMode() {
+ mMagnificationController.onFullScreenMagnificationActivationState(true);
+
+ verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt());
+ }
+
+ @Test
+ public void imeWindowStateHidden_fullScreenMagnifying_noLogAnyMode() {
+ mMagnificationController.onWindowMagnificationActivationState(true);
+
+ verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt());
+ }
+
private void setMagnificationEnabled(int mode) throws RemoteException {
setMagnificationEnabled(mode, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
index e13597d..e04841b 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
@@ -73,8 +73,9 @@
public class ActivityManagerTest {
private static final String TAG = "ActivityManagerTest";
- private static final String TEST_APP = "com.android.servicestests.apps.simpleservicetestapp";
- private static final String TEST_CLASS = TEST_APP + ".SimpleService";
+ private static final String TEST_APP = "com.android.servicestests.apps.simpleservicetestapp1";
+ private static final String TEST_CLASS =
+ "com.android.servicestests.apps.simpleservicetestapp.SimpleService";
private static final int TEST_LOOPS = 100;
private static final long AWAIT_TIMEOUT = 2000;
private static final long CHECK_INTERVAL = 100;
diff --git a/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java b/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java
new file mode 100644
index 0000000..10f4c05
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.OnUidImportanceListener;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.os.SystemClock;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:ServiceRestarterTest
+ */
+@RunWith(AndroidJUnit4.class)
+public final class ServiceRestarterTest {
+ private static final String TAG = "ServiceRestarterTest";
+
+ private static final String TEST_PACKAGE1_NAME =
+ "com.android.servicestests.apps.simpleservicetestapp1";
+ private static final String TEST_PACKAGE2_NAME =
+ "com.android.servicestests.apps.simpleservicetestapp2";
+ private static final String TEST_PACKAGE3_NAME =
+ "com.android.servicestests.apps.simpleservicetestapp3";
+ private static final String TEST_SERVICE_NAME =
+ "com.android.servicestests.apps.simpleservicetestapp.SimpleService";
+
+ private static final long WAIT_MS = 5 * 1000;
+ private static final long WAIT_LONG_MS = 30 * 1000;
+
+ private static final int ACTION_START = 1;
+ private static final int ACTION_KILL = 2;
+ private static final int ACTION_WAIT = 4;
+ private static final int ACTION_STOPPKG = 8;
+ private static final int ACTION_ALL = ACTION_START | ACTION_KILL | ACTION_WAIT | ACTION_STOPPKG;
+
+ private Context mContext;
+ private Instrumentation mInstrumentation;
+ private int mTestPackage1Uid;
+ private int mTestPackage2Uid;
+ private int mTestPackage3Uid;
+
+ @Before
+ public void setUp() throws Exception {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mContext = InstrumentationRegistry.getContext();
+ ApplicationInfo ai = mContext.getPackageManager().getApplicationInfo(TEST_PACKAGE1_NAME, 0);
+ mTestPackage1Uid = ai.uid;
+ ai = mContext.getPackageManager().getApplicationInfo(TEST_PACKAGE2_NAME, 0);
+ mTestPackage2Uid = ai.uid;
+ ai = mContext.getPackageManager().getApplicationInfo(TEST_PACKAGE3_NAME, 0);
+ mTestPackage3Uid = ai.uid;
+ }
+
+ @LargeTest
+ @Test
+ public void testDisableServiceRestartBackoff() throws Exception {
+ final ActivityManager am = mContext.getSystemService(ActivityManager.class);
+ final MyUidImportanceListener uid1Listener1 = new MyUidImportanceListener(mTestPackage1Uid);
+ final MyUidImportanceListener uid1Listener2 = new MyUidImportanceListener(mTestPackage1Uid);
+ final MyUidImportanceListener uid2Listener1 = new MyUidImportanceListener(mTestPackage2Uid);
+ final MyUidImportanceListener uid2Listener2 = new MyUidImportanceListener(mTestPackage2Uid);
+ final MyUidImportanceListener uid3Listener1 = new MyUidImportanceListener(mTestPackage3Uid);
+ final MyUidImportanceListener uid3Listener2 = new MyUidImportanceListener(mTestPackage3Uid);
+ try {
+ am.addOnUidImportanceListener(uid1Listener1, RunningAppProcessInfo.IMPORTANCE_SERVICE);
+ am.addOnUidImportanceListener(uid1Listener2, RunningAppProcessInfo.IMPORTANCE_GONE);
+ am.addOnUidImportanceListener(uid2Listener1, RunningAppProcessInfo.IMPORTANCE_SERVICE);
+ am.addOnUidImportanceListener(uid2Listener2, RunningAppProcessInfo.IMPORTANCE_GONE);
+ am.addOnUidImportanceListener(uid3Listener1, RunningAppProcessInfo.IMPORTANCE_SERVICE);
+ am.addOnUidImportanceListener(uid3Listener2, RunningAppProcessInfo.IMPORTANCE_GONE);
+ executeShellCmd("cmd deviceidle whitelist +" + TEST_PACKAGE1_NAME);
+ executeShellCmd("cmd deviceidle whitelist +" + TEST_PACKAGE2_NAME);
+ executeShellCmd("cmd deviceidle whitelist +" + TEST_PACKAGE3_NAME);
+
+ // Issue the command to enable service backoff policy for app2.
+ executeShellCmd("am service-restart-backoff enable " + TEST_PACKAGE2_NAME);
+ // Test restarts in normal case
+ final long[] ts1 = startKillAndRestart(am, ACTION_START | ACTION_KILL | ACTION_WAIT,
+ uid1Listener1, uid1Listener2, uid2Listener1, uid2Listener2,
+ uid3Listener1, uid3Listener2, Long.MAX_VALUE);
+ assertTrue("app1 restart should be before app2", ts1[1] < ts1[2]);
+ assertTrue("app2 restart should be before app3", ts1[2] < ts1[3]);
+
+ // Issue the command to disable service backoff policy for app2.
+ executeShellCmd("am service-restart-backoff disable " + TEST_PACKAGE2_NAME);
+ // Test restarts again.
+ final long[] ts2 = startKillAndRestart(am, ACTION_KILL | ACTION_WAIT | ACTION_STOPPKG,
+ uid1Listener1, uid1Listener2, uid2Listener1,
+ uid2Listener2, uid3Listener1, uid3Listener2, Long.MAX_VALUE);
+ assertTrue("app2 restart should be before app1", ts2[2] < ts2[1]);
+ assertTrue("app1 restart should be before app3", ts2[1] < ts2[3]);
+ assertTrue("app2 should be restart in a very short moment", ts2[2] - ts2[0] < WAIT_MS);
+
+ // Issue the command to enable service backoff policy for app2.
+ executeShellCmd("am service-restart-backoff enable " + TEST_PACKAGE2_NAME);
+ // Test restarts again.
+ final long[] ts3 = startKillAndRestart(am, ACTION_ALL, uid1Listener1, uid1Listener2,
+ uid2Listener1, uid2Listener2, uid3Listener1, uid3Listener2, Long.MAX_VALUE);
+ assertTrue("app1 restart should be before app2", ts3[1] < ts3[2]);
+ assertTrue("app2 restart should be before app3", ts3[2] < ts3[3]);
+
+ } finally {
+ executeShellCmd("cmd deviceidle whitelist -" + TEST_PACKAGE1_NAME);
+ executeShellCmd("cmd deviceidle whitelist -" + TEST_PACKAGE2_NAME);
+ executeShellCmd("cmd deviceidle whitelist -" + TEST_PACKAGE3_NAME);
+ executeShellCmd("am service-restart-backoff enable " + TEST_PACKAGE2_NAME);
+ am.removeOnUidImportanceListener(uid1Listener1);
+ am.removeOnUidImportanceListener(uid1Listener2);
+ am.removeOnUidImportanceListener(uid2Listener1);
+ am.removeOnUidImportanceListener(uid2Listener2);
+ am.removeOnUidImportanceListener(uid3Listener1);
+ am.removeOnUidImportanceListener(uid3Listener2);
+ am.forceStopPackage(TEST_PACKAGE1_NAME);
+ am.forceStopPackage(TEST_PACKAGE2_NAME);
+ am.forceStopPackage(TEST_PACKAGE3_NAME);
+ }
+ }
+
+ private long[] startKillAndRestart(ActivityManager am, int action,
+ MyUidImportanceListener uid1Listener1, MyUidImportanceListener uid1Listener2,
+ MyUidImportanceListener uid2Listener1, MyUidImportanceListener uid2Listener2,
+ MyUidImportanceListener uid3Listener1, MyUidImportanceListener uid3Listener2,
+ long waitDuration) throws Exception {
+ final long[] res = new long[4];
+ // Test restarts in normal condition.
+ if ((action & ACTION_START) != 0) {
+ startServiceAndWait(TEST_PACKAGE1_NAME, uid1Listener1, WAIT_MS);
+ startServiceAndWait(TEST_PACKAGE2_NAME, uid2Listener1, WAIT_MS);
+ startServiceAndWait(TEST_PACKAGE3_NAME, uid3Listener1, WAIT_MS);
+ }
+
+ if ((action & ACTION_KILL) != 0) {
+ final long now = res[0] = SystemClock.uptimeMillis();
+ killUidAndWait(am, mTestPackage1Uid, uid1Listener2, WAIT_MS);
+ killUidAndWait(am, mTestPackage2Uid, uid2Listener2, WAIT_MS);
+ killUidAndWait(am, mTestPackage3Uid, uid3Listener2, WAIT_MS);
+ }
+
+ if ((action & ACTION_WAIT) != 0) {
+ assertTrue("Timed out to restart " + TEST_PACKAGE1_NAME, uid1Listener1.waitFor(
+ RunningAppProcessInfo.IMPORTANCE_SERVICE, waitDuration));
+ assertTrue("Timed out to restart " + TEST_PACKAGE2_NAME, uid2Listener1.waitFor(
+ RunningAppProcessInfo.IMPORTANCE_SERVICE, waitDuration));
+ assertTrue("Timed out to restart " + TEST_PACKAGE3_NAME, uid3Listener1.waitFor(
+ RunningAppProcessInfo.IMPORTANCE_SERVICE, waitDuration));
+ res[1] = uid1Listener1.mCurrentTimestamp;
+ res[2] = uid2Listener1.mCurrentTimestamp;
+ res[3] = uid3Listener1.mCurrentTimestamp;
+ }
+
+ if ((action & ACTION_STOPPKG) != 0) {
+ // Force stop these packages to reset the backoff delays.
+ am.forceStopPackage(TEST_PACKAGE1_NAME);
+ am.forceStopPackage(TEST_PACKAGE2_NAME);
+ am.forceStopPackage(TEST_PACKAGE3_NAME);
+ assertTrue("Timed out to force-stop " + mTestPackage1Uid,
+ uid1Listener2.waitFor(RunningAppProcessInfo.IMPORTANCE_GONE, WAIT_MS));
+ assertTrue("Timed out to force-stop " + mTestPackage2Uid,
+ uid2Listener2.waitFor(RunningAppProcessInfo.IMPORTANCE_GONE, WAIT_MS));
+ assertTrue("Timed out to force-stop " + mTestPackage3Uid,
+ uid3Listener2.waitFor(RunningAppProcessInfo.IMPORTANCE_GONE, WAIT_MS));
+ }
+ return res;
+ }
+
+ private void startServiceAndWait(String pkgName, MyUidImportanceListener uidListener,
+ long timeout) throws Exception {
+ final Intent intent = new Intent();
+ final ComponentName cn = ComponentName.unflattenFromString(
+ pkgName + "/" + TEST_SERVICE_NAME);
+ intent.setComponent(cn);
+ Log.i(TAG, "Starting service " + cn);
+ assertNotNull(mContext.startService(intent));
+ assertTrue("Timed out to start service " + cn,
+ uidListener.waitFor(RunningAppProcessInfo.IMPORTANCE_SERVICE, timeout));
+ }
+
+ private void killUidAndWait(ActivityManager am, int uid, MyUidImportanceListener uidListener,
+ long timeout) throws Exception {
+ am.killUid(uid, "test service restart");
+ assertTrue("Timed out to kill " + uid,
+ uidListener.waitFor(RunningAppProcessInfo.IMPORTANCE_GONE, timeout));
+ }
+
+ private String executeShellCmd(String cmd) throws Exception {
+ final String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
+ Log.d(TAG, String.format("Output for '%s': %s", cmd, result));
+ return result;
+ }
+
+ private static class MyUidImportanceListener implements OnUidImportanceListener {
+ final CountDownLatch[] mLatchHolder = new CountDownLatch[1];
+ private final int mExpectedUid;
+ private int mExpectedImportance;
+ private int mCurrentImportance = RunningAppProcessInfo.IMPORTANCE_GONE;
+ long mCurrentTimestamp;
+
+ MyUidImportanceListener(int uid) {
+ mExpectedUid = uid;
+ }
+
+ @Override
+ public void onUidImportance(int uid, int importance) {
+ if (uid == mExpectedUid) {
+ mCurrentTimestamp = SystemClock.uptimeMillis();
+ synchronized (this) {
+ if (importance == mExpectedImportance && mLatchHolder[0] != null) {
+ mLatchHolder[0].countDown();
+ }
+ mCurrentImportance = importance;
+ }
+ Log.i(TAG, "uid " + uid + " importance: " + importance);
+ }
+ }
+
+ boolean waitFor(int expectedImportance, long timeout) throws Exception {
+ synchronized (this) {
+ mExpectedImportance = expectedImportance;
+ if (mCurrentImportance == expectedImportance) {
+ return true;
+ }
+ mLatchHolder[0] = new CountDownLatch(1);
+ }
+ return mLatchHolder[0].await(timeout, TimeUnit.MILLISECONDS);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 5c8a7d2..9ffb5017 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -80,7 +80,6 @@
import androidx.test.filters.SmallTest;
-import com.android.internal.widget.LockPatternUtils;
import com.android.server.FgThread;
import com.android.server.am.UserState.KeyEvictedCallback;
import com.android.server.pm.UserManagerInternal;
@@ -124,7 +123,6 @@
private static final long HANDLER_WAIT_TIME_MS = 100;
private UserController mUserController;
- private LockPatternUtils mLockPatternUtils;
private TestInjector mInjector;
private final HashMap<Integer, UserState> mUserStates = new HashMap<>();
@@ -163,13 +161,6 @@
doNothing().when(mInjector).activityManagerOnUserStopped(anyInt());
doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt());
-
- // Make it appear that calling unlockUserKey() is needed.
- doReturn(true).when(mInjector).isFileEncryptedNativeOnly();
- mLockPatternUtils = mock(LockPatternUtils.class);
- when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
- doReturn(mLockPatternUtils).when(mInjector).getLockPatternUtils();
-
// All UserController params are set to default.
mUserController = new UserController(mInjector);
setUpUser(TEST_USER_ID, NO_USERINFO_FLAGS);
@@ -561,20 +552,6 @@
/* keyEvictedCallback= */ mKeyEvictedCallback, /* expectLocking= */ true);
}
- /**
- * Test that if a user has a lock screen credential set, then UserController
- * doesn't bother trying to unlock their storage key without a credential
- * token, as it will never work.
- */
- @Test
- public void testSecureUserUnlockNotAttempted() throws Exception {
- when(mLockPatternUtils.isSecure(eq(TEST_USER_ID1))).thenReturn(true);
- setUpUser(TEST_USER_ID1, 0);
- mUserController.startUser(TEST_USER_ID1, /* foreground= */ false);
- verify(mInjector.mStorageManagerMock, times(0))
- .unlockUserKey(eq(TEST_USER_ID1), anyInt(), any(), any());
- }
-
@Test
public void testStartProfile_fullUserFails() {
setUpUser(TEST_USER_ID1, 0);
diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
index 0dbf3fe..9a430e4 100644
--- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
@@ -282,5 +282,10 @@
public HibernationStateDiskStore<UserLevelState> getUserLevelDiskStore(int userId) {
return mock(HibernationStateDiskStore.class);
}
+
+ @Override
+ public boolean isOatArtifactDeletionEnabled() {
+ return true;
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/PersistentSystemFontConfigTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/PersistentSystemFontConfigTest.java
index 912da94..63a53e7 100644
--- a/services/tests/servicestests/src/com/android/server/graphics/fonts/PersistentSystemFontConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/PersistentSystemFontConfigTest.java
@@ -18,9 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
-import android.graphics.FontListParser;
+import android.graphics.fonts.FontUpdateRequest;
import android.platform.test.annotations.Presubmit;
-import android.text.FontConfig;
import android.util.Xml;
import androidx.test.filters.SmallTest;
@@ -49,9 +48,9 @@
config.updatedFontDirs.add("~~abc");
config.updatedFontDirs.add("~~def");
- FontConfig.FontFamily fontFamily = parseFontFamily(
+ FontUpdateRequest.Family fontFamily = parseFontFamily(
"<family name='test'>"
- + " <font>test.ttf</font>"
+ + " <font name=\"test\" />"
+ "</family>");
config.fontFamilies.add(fontFamily);
@@ -86,11 +85,11 @@
}
}
- private static FontConfig.FontFamily parseFontFamily(String xml) throws Exception {
+ private static FontUpdateRequest.Family parseFontFamily(String xml) throws Exception {
XmlPullParser parser = Xml.newPullParser();
ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
parser.setInput(is, "UTF-8");
parser.nextTag();
- return FontListParser.readFamily(parser, "", null);
+ return FontUpdateRequest.Family.readFromXml(parser);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
index e7ffea0..b941b23 100644
--- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
@@ -699,7 +699,7 @@
+ " <font>test.ttf</font>"
+ "</family>")));
fail("Expect NullPointerException");
- } catch (NullPointerException e) {
+ } catch (FontManagerService.SystemFontException e) {
// Expect
}
}
@@ -797,8 +797,18 @@
ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
parser.setInput(is, "UTF-8");
parser.nextTag();
+
FontConfig.FontFamily fontFamily = FontListParser.readFamily(parser, "", null);
- return new FontUpdateRequest(fontFamily);
+ List<FontUpdateRequest.Font> fonts = new ArrayList<>();
+ for (FontConfig.Font font : fontFamily.getFontList()) {
+ String name = font.getFile().getName();
+ String psName = name.substring(0, name.length() - 4); // drop suffix
+ FontUpdateRequest.Font updateFont = new FontUpdateRequest.Font(
+ psName, font.getStyle(), font.getTtcIndex(), font.getFontVariationSettings());
+ fonts.add(updateFont);
+ }
+ FontUpdateRequest.Family family = new FontUpdateRequest.Family(fontFamily.getName(), fonts);
+ return new FontUpdateRequest(family);
}
private void writeConfig(PersistentSystemFontConfig.Config config,
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index ef3e320..88b0651 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -850,6 +850,12 @@
}
@Override
+ public void getStorageInfo(String packageName, String databaseName, int userId,
+ IAppSearchResultCallback callback) throws RemoteException {
+ ignore(callback);
+ }
+
+ @Override
public void persistToDisk(int userId) throws RemoteException {
}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 2df6c5a..874f8dc 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -467,21 +467,21 @@
// First, ensure that a normal full wake lock does not cause a wakeup
int flags = PowerManager.FULL_WAKE_LOCK;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
- null /* workSource */, null /* historyTag */);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
// Ensure that the flag does *NOT* work with a partial wake lock.
flags = PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
- null /* workSource */, null /* historyTag */);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
// Verify that flag forces a wakeup when paired to a FULL_WAKE_LOCK
flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
- null /* workSource */, null /* historyTag */);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
}
@@ -669,7 +669,7 @@
// Create a wakelock
mService.getBinderServiceInstance().acquireWakeLock(new Binder(), flags, tag, pkg,
- null /* workSource */, null /* historyTag */);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
assertThat(wakelockMap.get(tag)).isEqualTo(flags); // Verify wakelock is active.
// Confirm that the wakelocks have been disabled when the forceSuspend is in flight.
@@ -727,7 +727,7 @@
// Take a nap and verify we no longer hold the blocker
int flags = PowerManager.DOZE_WAKE_LOCK;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
- null /* workSource */, null /* historyTag */);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
mService.getBinderServiceInstance().goToSleep(mClock.now(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
@@ -835,13 +835,94 @@
mService.getBinderServiceInstance().acquireWakeLock(token,
PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
- null /* workSource */, null /* historyTag */);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+ assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
advanceTime(60);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
}
@Test
+ public void testWakeLock_affectsProperDisplayGroup() throws Exception {
+ final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
+ final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
+ new AtomicReference<>();
+ doAnswer((Answer<Void>) invocation -> {
+ listener.set(invocation.getArgument(0));
+ return null;
+ }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any());
+ final DisplayInfo info = new DisplayInfo();
+ info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP;
+ when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info);
+
+ final String pkg = mContextSpy.getOpPackageName();
+ final Binder token = new Binder();
+ final String tag = "testWakeLock_affectsProperDisplayGroup";
+
+ setMinimumScreenOffTimeoutConfig(5);
+ createService();
+ startSystem();
+ listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
+
+ mService.getBinderServiceInstance().acquireWakeLock(token,
+ PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
+ null /* workSource */, null /* historyTag */, Display.DEFAULT_DISPLAY);
+
+ assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+ assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
+ WAKEFULNESS_AWAKE);
+ assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
+ WAKEFULNESS_AWAKE);
+
+ advanceTime(15000);
+ assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+ assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
+ WAKEFULNESS_AWAKE);
+ assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
+ WAKEFULNESS_DOZING);
+ }
+
+ @Test
+ public void testInvalidDisplayGroupWakeLock_affectsAllDisplayGroups() throws Exception {
+ final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
+ final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
+ new AtomicReference<>();
+ doAnswer((Answer<Void>) invocation -> {
+ listener.set(invocation.getArgument(0));
+ return null;
+ }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any());
+ final DisplayInfo info = new DisplayInfo();
+ info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP;
+ when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info);
+
+ final String pkg = mContextSpy.getOpPackageName();
+ final Binder token = new Binder();
+ final String tag = "testInvalidDisplayGroupWakeLock_affectsAllDisplayGroups";
+
+ setMinimumScreenOffTimeoutConfig(5);
+ createService();
+ startSystem();
+ listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
+
+ mService.getBinderServiceInstance().acquireWakeLock(token,
+ PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+
+ assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+ assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
+ WAKEFULNESS_AWAKE);
+ assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
+ WAKEFULNESS_AWAKE);
+
+ advanceTime(15000);
+ assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+ assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
+ WAKEFULNESS_AWAKE);
+ assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
+ WAKEFULNESS_AWAKE);
+ }
+
+ @Test
public void testBoot_ShouldBeAwake() throws Exception {
createService();
startSystem();
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java
index f5d0ca7..584bcf4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java
@@ -58,7 +58,6 @@
private com.android.server.wm.WindowOrientationListener mWindowOrientationListener;
private int mFinalizedRotation;
private boolean mRotationResolverEnabled;
- private boolean mCanUseRotationResolver;
private SensorEvent mFakeSensorEvent;
private Sensor mFakeSensor;
@@ -66,7 +65,6 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mRotationResolverEnabled = true;
- mCanUseRotationResolver = true;
mFakeRotationResolverInternal = new TestableRotationResolver();
doReturn(mMockSensorManager).when(mMockContext).getSystemService(Context.SENSOR_SERVICE);
@@ -89,16 +87,6 @@
}
@Test
- public void testOnSensorChanged_cannotUseRotationResolver_useSensorResult() {
- mCanUseRotationResolver = false;
-
- mWindowOrientationListener.mOrientationJudge.onSensorChanged(mFakeSensorEvent);
-
- assertThat(mFinalizedRotation).isEqualTo(Surface.ROTATION_90);
-
- }
-
- @Test
public void testOnSensorChanged_normalCase() {
mFakeRotationResolverInternal.mResult = Surface.ROTATION_180;
@@ -139,11 +127,6 @@
}
@Override
- public boolean canUseRotationResolver() {
- return mCanUseRotationResolver;
- }
-
- @Override
public boolean isRotationResolverEnabled() {
return mRotationResolverEnabled;
}
diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp b/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp
index 50b89d4..5550f7d 100644
--- a/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp
+++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp
@@ -22,7 +22,7 @@
}
android_test_helper_app {
- name: "SimpleServiceTestApp",
+ name: "SimpleServiceTestApp1",
test_suites: ["device-tests"],
@@ -36,4 +36,47 @@
optimize: {
enabled: false,
},
+ aaptflags: [
+ "--rename-manifest-package com.android.servicestests.apps.simpleservicetestapp1",
+ ],
+}
+
+android_test_helper_app {
+ name: "SimpleServiceTestApp2",
+
+ test_suites: ["device-tests"],
+
+ srcs: ["**/*.java"],
+
+ platform_apis: true,
+ certificate: "platform",
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ aaptflags: [
+ "--rename-manifest-package com.android.servicestests.apps.simpleservicetestapp2",
+ ],
+}
+
+android_test_helper_app {
+ name: "SimpleServiceTestApp3",
+
+ test_suites: ["device-tests"],
+
+ srcs: ["**/*.java"],
+
+ platform_apis: true,
+ certificate: "platform",
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ aaptflags: [
+ "--rename-manifest-package com.android.servicestests.apps.simpleservicetestapp3",
+ ],
}
diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java b/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
index 75f71d6..674ce8a 100644
--- a/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
+++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
@@ -21,8 +21,11 @@
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Process;
+import android.util.Log;
public class SimpleService extends Service {
+ private static final String TAG = "SimpleService";
+
private final IRemoteCallback.Stub mBinder = new IRemoteCallback.Stub() {
@Override
public void sendResult(Bundle bundle) {
@@ -31,6 +34,12 @@
};
@Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.i(TAG, "onStartCommand");
+ return START_STICKY;
+ }
+
+ @Override
public IBinder onBind(Intent intent) {
return mBinder;
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 55ebe11..bb70c79 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -6972,51 +6972,6 @@
}
@Test
- public void deleteConversationNotificationChannels() throws Exception {
- NotificationChannel messagesParent =
- new NotificationChannel("messages", "messages", IMPORTANCE_HIGH);
- Parcel msgParcel = Parcel.obtain();
- messagesParent.writeToParcel(msgParcel, 0);
- msgParcel.setDataPosition(0);
-
- NotificationChannel callsParent =
- new NotificationChannel("calls", "calls", IMPORTANCE_HIGH);
- Parcel callParcel = Parcel.obtain();
- callsParent.writeToParcel(callParcel, 0);
- callParcel.setDataPosition(0);
-
- mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
- messagesParent, callsParent)));
-
- String conversationId = "friend";
-
- mBinderService.createConversationNotificationChannelForPackage(
- PKG, mUid, NotificationChannel.CREATOR.createFromParcel(msgParcel),
- conversationId);
- mBinderService.createConversationNotificationChannelForPackage(
- PKG, mUid, NotificationChannel.CREATOR.createFromParcel(callParcel),
- conversationId);
-
- NotificationChannel messagesChild = mBinderService.getConversationNotificationChannel(
- PKG, 0, PKG, messagesParent.getId(), false, conversationId);
- NotificationChannel callsChild = mBinderService.getConversationNotificationChannel(
- PKG, 0, PKG, callsParent.getId(), false, conversationId);
-
- assertEquals(messagesParent.getId(), messagesChild.getParentChannelId());
- assertEquals(conversationId, messagesChild.getConversationId());
-
- assertEquals(callsParent.getId(), callsChild.getParentChannelId());
- assertEquals(conversationId, callsChild.getConversationId());
-
- mBinderService.deleteConversationNotificationChannels(PKG, mUid, conversationId);
-
- assertNull(mBinderService.getConversationNotificationChannel(
- PKG, 0, PKG, messagesParent.getId(), false, conversationId));
- assertNull(mBinderService.getConversationNotificationChannel(
- PKG, 0, PKG, callsParent.getId(), false, conversationId));
- }
-
- @Test
public void testCorrectCategory_systemOn_appCannotTurnOff() {
int requested = 0;
int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index acda4d5..04c144a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -71,6 +71,7 @@
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
+import android.content.AttributionSource;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -86,6 +87,7 @@
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -207,37 +209,35 @@
throw new UnsupportedOperationException("unimplemented mock method");
});
doAnswer(invocation -> {
- String callingPkg = invocation.getArgument(0);
- String featureId = invocation.getArgument(1);
- Uri uri = invocation.getArgument(2);
- RemoteCallback cb = invocation.getArgument(3);
+ AttributionSource attributionSource = invocation.getArgument(0);
+ Uri uri = invocation.getArgument(1);
+ RemoteCallback cb = invocation.getArgument(2);
IContentProvider mock = (IContentProvider) (invocation.getMock());
AsyncTask.SERIAL_EXECUTOR.execute(() -> {
final Bundle bundle = new Bundle();
try {
bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
- mock.canonicalize(callingPkg, featureId, uri));
+ mock.canonicalize(attributionSource, uri));
} catch (RemoteException e) { /* consume */ }
cb.sendResult(bundle);
});
return null;
- }).when(mTestIContentProvider).canonicalizeAsync(any(), any(), any(), any());
+ }).when(mTestIContentProvider).canonicalizeAsync(any(), any(), any());
doAnswer(invocation -> {
- String callingPkg = invocation.getArgument(0);
- String featureId = invocation.getArgument(1);
- Uri uri = invocation.getArgument(2);
- RemoteCallback cb = invocation.getArgument(3);
+ AttributionSource attributionSource = invocation.getArgument(0);
+ Uri uri = invocation.getArgument(1);
+ RemoteCallback cb = invocation.getArgument(2);
IContentProvider mock = (IContentProvider) (invocation.getMock());
AsyncTask.SERIAL_EXECUTOR.execute(() -> {
final Bundle bundle = new Bundle();
try {
bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
- mock.uncanonicalize(callingPkg, featureId, uri));
+ mock.uncanonicalize(attributionSource, uri));
} catch (RemoteException e) { /* consume */ }
cb.sendResult(bundle);
});
return null;
- }).when(mTestIContentProvider).uncanonicalizeAsync(any(), any(), any(), any());
+ }).when(mTestIContentProvider).uncanonicalizeAsync(any(), any(), any());
doAnswer(invocation -> {
Uri uri = invocation.getArgument(0);
RemoteCallback cb = invocation.getArgument(1);
@@ -256,11 +256,11 @@
contentResolver.addProvider(TEST_AUTHORITY, testContentProvider);
doReturn(CANONICAL_SOUND_URI)
- .when(mTestIContentProvider).canonicalize(any(), any(), eq(SOUND_URI));
+ .when(mTestIContentProvider).canonicalize(any(), eq(SOUND_URI));
doReturn(CANONICAL_SOUND_URI)
- .when(mTestIContentProvider).canonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+ .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI));
doReturn(SOUND_URI)
- .when(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+ .when(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0);
@@ -594,7 +594,7 @@
// Testing that in restore we are given the canonical version
loadStreamXml(baos, true, UserHandle.USER_SYSTEM);
- verify(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+ verify(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
}
@Test
@@ -605,12 +605,11 @@
.appendQueryParameter("canonical", "1")
.build();
doReturn(canonicalBasedOnLocal)
- .when(mTestIContentProvider).canonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+ .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI));
doReturn(localUri)
- .when(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+ .when(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
doReturn(localUri)
- .when(mTestIContentProvider).uncanonicalize(any(), any(),
- eq(canonicalBasedOnLocal));
+ .when(mTestIContentProvider).uncanonicalize(any(), eq(canonicalBasedOnLocal));
NotificationChannel channel =
new NotificationChannel("id", "name", IMPORTANCE_LOW);
@@ -630,9 +629,9 @@
public void testRestoreXml_withNonExistentCanonicalizedSoundUri() throws Exception {
Thread.sleep(3000);
doReturn(null)
- .when(mTestIContentProvider).canonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+ .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI));
doReturn(null)
- .when(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+ .when(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
NotificationChannel channel =
new NotificationChannel("id", "name", IMPORTANCE_LOW);
@@ -657,7 +656,7 @@
public void testRestoreXml_withUncanonicalizedNonLocalSoundUri() throws Exception {
// Not a local uncanonicalized uri, simulating that it fails to exist locally
doReturn(null)
- .when(mTestIContentProvider).canonicalize(any(), any(), eq(SOUND_URI));
+ .when(mTestIContentProvider).canonicalize(any(), eq(SOUND_URI));
String id = "id";
String backupWithUncanonicalizedSoundUri = "<ranking version=\"1\">\n"
+ "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 5018166..b83f9f2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -132,11 +132,11 @@
when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider);
contentResolver.addProvider(TEST_AUTHORITY, testContentProvider);
- when(mTestIContentProvider.canonicalize(any(), any(), eq(SOUND_URI)))
+ when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI)))
.thenReturn(CANONICAL_SOUND_URI);
- when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
+ when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
.thenReturn(CANONICAL_SOUND_URI);
- when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
+ when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
.thenReturn(SOUND_URI);
mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
index aceed86..baae25c 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
@@ -110,7 +110,7 @@
mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
TestableLooper.get(this).processAllMessages();
- verify(mIContentProvider).call(anyString(), nullable(String.class), anyString(),
+ verify(mIContentProvider).call(any(), anyString(),
eq(SliceProvider.METHOD_PIN), eq(null), argThat(b -> {
assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
return true;
@@ -168,8 +168,8 @@
// Throw exception when trying to pin
doAnswer(invocation -> {
throw new Exception("Pin failed");
- }).when(mIContentProvider).call(anyString(), nullable(String.class), anyString(),
- anyString(), eq(null), any());
+ }).when(mIContentProvider).call(any(), anyString(), anyString(),
+ nullable(String.class), any());
TestableLooper.get(this).processAllMessages();
@@ -177,7 +177,7 @@
mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
TestableLooper.get(this).processAllMessages();
- verify(mIContentProvider).call(anyString(), nullable(String.class), anyString(),
+ verify(mIContentProvider).call(any(), anyString(),
eq(SliceProvider.METHOD_PIN), eq(null), argThat(b -> {
assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
return true;
diff --git a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
index 3025a95..222c692 100644
--- a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
@@ -26,6 +26,7 @@
import static com.android.server.policy.SingleKeyGestureDetector.KEY_VERYLONGPRESS;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.app.Instrumentation;
@@ -62,6 +63,10 @@
private long mLongPressTime;
private long mVeryLongPressTime;
+ // Allow press from non interactive mode.
+ private boolean mAllowNonInteractiveForPress = true;
+ private boolean mAllowNonInteractiveForLongPress = true;
+
@Before
public void setUp() {
mDetector = new SingleKeyGestureDetector(mContext);
@@ -81,11 +86,17 @@
}
@Override
public void onPress(long downTime) {
+ if (mDetector.beganFromNonInteractive() && !mAllowNonInteractiveForPress) {
+ return;
+ }
mShortPressed.countDown();
}
@Override
void onLongPress(long downTime) {
+ if (mDetector.beganFromNonInteractive() && !mAllowNonInteractiveForLongPress) {
+ return;
+ }
mLongPressed.countDown();
}
@@ -96,6 +107,9 @@
@Override
void onMultiPress(long downTime, int count) {
+ if (mDetector.beganFromNonInteractive() && !mAllowNonInteractiveForPress) {
+ return;
+ }
mMultiPressed.countDown();
assertEquals(mMaxMultiPressPowerCount, count);
}
@@ -103,9 +117,13 @@
}
private void pressKey(long eventTime, int keyCode, long pressTime) {
+ pressKey(eventTime, keyCode, pressTime, true /* interactive */);
+ }
+
+ private void pressKey(long eventTime, int keyCode, long pressTime, boolean interactive) {
final KeyEvent keyDown = new KeyEvent(eventTime, eventTime, ACTION_DOWN,
keyCode, 0 /* repeat */, 0 /* metaState */);
- mDetector.interceptKey(keyDown);
+ mDetector.interceptKey(keyDown, interactive);
// keep press down.
try {
@@ -118,7 +136,7 @@
final KeyEvent keyUp = new KeyEvent(eventTime, eventTime, ACTION_UP,
keyCode, 0 /* repeat */, 0 /* metaState */);
- mDetector.interceptKey(keyUp);
+ mDetector.interceptKey(keyUp, interactive);
}
@Test
@@ -149,4 +167,18 @@
pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
assertTrue(mMultiPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
+
+ @Test
+ public void testNonInteractive() throws InterruptedException {
+ long eventTime = SystemClock.uptimeMillis();
+ // Disallow short press behavior from non interactive.
+ mAllowNonInteractiveForPress = false;
+ pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */, false /* interactive */);
+ assertFalse(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
+
+ // Allow long press behavior from non interactive.
+ eventTime = SystemClock.uptimeMillis();
+ pressKey(eventTime, KEYCODE_POWER, mLongPressTime, false /* interactive */);
+ assertTrue(mLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 96ebd24..ab9aa26 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1033,6 +1033,27 @@
}
/**
+ * Verify that finish request for the last activity in a task will request a shell transition
+ * with that task as a trigger.
+ */
+ @Test
+ public void testFinishActivityIfPossible_lastInTaskRequestsTransitionWithTrigger() {
+ // Set-up mock shell transitions
+ final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
+ mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
+ mAtm.getTransitionController().registerTransitionPlayer(testPlayer);
+
+ final ActivityRecord activity = createActivityWithTask();
+ activity.finishing = false;
+ activity.mVisibleRequested = true;
+ activity.setState(RESUMED, "test");
+ activity.finishIfPossible("test", false /* oomAdj */);
+
+ verify(activity).setVisibility(eq(false));
+ assertEquals(activity.getTask().mTaskId, testPlayer.mLastRequest.getTriggerTask().taskId);
+ }
+
+ /**
* Verify that complete finish request for non-finishing activity is invalid.
*/
@Test(expected = IllegalArgumentException.class)
@@ -2136,6 +2157,8 @@
attrs.setTitle("AppWindow");
final TestWindowState appWindow = createWindowState(attrs, activity);
activity.addWindow(appWindow);
+ spyOn(appWindow);
+ doNothing().when(appWindow).onStartFreezingScreen();
// Set initial orientation and update.
activity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
@@ -2172,6 +2195,8 @@
attrs.setTitle("RotationByPolicy");
final TestWindowState appWindow = createWindowState(attrs, activity);
activity.addWindow(appWindow);
+ spyOn(appWindow);
+ doNothing().when(appWindow).onStartFreezingScreen();
// Set initial orientation and update.
performRotation(displayRotation, Surface.ROTATION_90);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 20bced2..0bf237d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -70,6 +70,7 @@
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.util.MergedConfiguration;
import android.util.Pair;
@@ -1026,6 +1027,24 @@
assertEquals(taskDisplayArea.getTopRootTask(), taskDisplayArea.getRootHomeTask());
}
+ @Test
+ public void testLockAllProfileTasks() {
+ // Make an activity visible with the user id set to 0
+ final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
+ final int taskId = task.mTaskId;
+ final ActivityRecord activity = task.getTopMostActivity();
+
+ // Create another activity on top and the user id is 1
+ final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task)
+ .setUid(UserHandle.PER_USER_RANGE + 1).build();
+
+ // Make sure the listeners will be notified for putting the task to locked state
+ TaskChangeNotificationController controller = mAtm.getTaskChangeNotificationController();
+ spyOn(controller);
+ mWm.mRoot.lockAllProfileTasks(0);
+ verify(controller).notifyTaskProfileLocked(eq(taskId), eq(0));
+ }
+
/**
* Mock {@link RootWindowContainer#resolveHomeActivity} for returning consistent activity
* info for test cases.
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index e2b58bc..6d55220 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.START_CANCELED;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -55,6 +56,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
@@ -68,6 +70,7 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
@@ -1315,6 +1318,26 @@
assertFalse(info.topActivityInSizeCompat);
}
+ @Test
+ public void testStartTasksInTransaction() {
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ Bundle testOptions = new Bundle();
+ testOptions.putInt("test", 20);
+ wct.startTask(1, null /* options */);
+ wct.startTask(2, testOptions);
+ spyOn(mWm.mAtmService);
+ doReturn(START_CANCELED).when(mWm.mAtmService).startActivityFromRecents(anyInt(), any());
+ clearInvocations(mWm.mAtmService);
+ mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
+
+ final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mWm.mAtmService, times(1)).startActivityFromRecents(eq(1), bundleCaptor.capture());
+ assertTrue(bundleCaptor.getValue().isEmpty());
+
+ verify(mWm.mAtmService, times(1)).startActivityFromRecents(eq(2), bundleCaptor.capture());
+ assertEquals(20, bundleCaptor.getValue().getInt("test"));
+ }
+
/**
* Verifies that task vanished is called for a specific task.
*/
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 0510b9c..52f9fe5 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -75,6 +75,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Slog;
@@ -109,8 +110,10 @@
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.TimeUnit;
/**
* A service that collects, aggregates, and persists application usage data.
@@ -166,6 +169,11 @@
private final SparseIntArray mUidToKernelCounter = new SparseIntArray();
int mUsageSource;
+ private long mRealTimeSnapshot;
+ private long mSystemTimeSnapshot;
+ // A map storing last time global usage of packages, measured in milliseconds since the epoch.
+ private final Map<String, Long> mLastTimeComponentUsedGlobal = new ArrayMap<>();
+
/** Manages the standby state of apps. */
AppStandbyInternal mAppStandby;
@@ -279,6 +287,9 @@
getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
null, mHandler);
+ mRealTimeSnapshot = SystemClock.elapsedRealtime();
+ mSystemTimeSnapshot = System.currentTimeMillis();
+
publishLocalService(UsageStatsManagerInternal.class, new LocalService());
publishLocalService(AppStandbyInternal.class, mAppStandby);
publishBinderServices();
@@ -804,6 +815,28 @@
}
/**
+ * Assuming the event's timestamp is measured in milliseconds since boot,
+ * convert it to a system wall time. System and real time snapshots are updated before
+ * conversion.
+ */
+ private void convertToSystemTimeLocked(Event event) {
+ final long actualSystemTime = System.currentTimeMillis();
+ if (ENABLE_TIME_CHANGE_CORRECTION) {
+ final long actualRealtime = SystemClock.elapsedRealtime();
+ final long expectedSystemTime =
+ (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
+ final long diffSystemTime = actualSystemTime - expectedSystemTime;
+ if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
+ // The time has changed.
+ Slog.i(TAG, "Time changed in by " + (diffSystemTime / 1000) + " seconds");
+ mRealTimeSnapshot = actualRealtime;
+ mSystemTimeSnapshot = actualSystemTime;
+ }
+ }
+ event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
+ }
+
+ /**
* Called by the Binder stub.
*/
void reportEvent(Event event, int userId) {
@@ -940,6 +973,12 @@
Slog.w(TAG, "Failed to note usage stop", iae);
}
break;
+ case Event.USER_INTERACTION:
+ // Fall through
+ case Event.APP_COMPONENT_USED:
+ convertToSystemTimeLocked(event);
+ mLastTimeComponentUsedGlobal.put(event.mPackage, event.mTimeStamp);
+ break;
}
final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId);
@@ -2094,6 +2133,16 @@
public void forceUsageSourceSettingRead() {
readUsageSourceSetting();
}
+
+ @Override
+ public long getLastTimeAnyComponentUsed(String packageName) {
+ synchronized (mLock) {
+ // Truncate the returned milliseconds to the boundary of the last day before exact
+ // time for privacy reasons.
+ return mLastTimeComponentUsedGlobal.getOrDefault(packageName, 0L)
+ / TimeUnit.DAYS.toMillis(1) * TimeUnit.DAYS.toMillis(1);
+ }
+ }
}
void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 22b4f4e..36d8c85 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -277,8 +277,11 @@
+ eventToString(event.mEventType));
}
- checkAndGetTimeLocked();
- convertToSystemTimeLocked(event);
+ if (event.mEventType != Event.USER_INTERACTION
+ && event.mEventType != Event.APP_COMPONENT_USED) {
+ checkAndGetTimeLocked();
+ convertToSystemTimeLocked(event);
+ }
if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
// Need to rollover
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index bbfb0d6..5d541e9 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -93,7 +93,7 @@
HotwordDetectionConnection(Object lock, Context context, ComponentName serviceName,
int userId, boolean bindInstantServiceAllowed, @Nullable PersistableBundle options,
- @Nullable SharedMemory sharedMemory) {
+ @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
mLock = lock;
mContext = context;
mDetectionComponentName = serviceName;
@@ -111,7 +111,7 @@
mBound = connected;
if (connected) {
try {
- service.updateState(options, sharedMemory);
+ service.updateState(options, sharedMemory, callback);
} catch (RemoteException e) {
// TODO: (b/181842909) Report an error to voice interactor
Slog.w(TAG, "Failed to updateState for HotwordDetectionService", e);
@@ -146,7 +146,7 @@
void updateStateLocked(PersistableBundle options, SharedMemory sharedMemory) {
mRemoteHotwordDetectionService.run(
- service -> service.updateState(options, sharedMemory));
+ service -> service.updateState(options, sharedMemory, null /* callback */));
}
void startListeningFromMic(
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index d66f21f..ccaeaf9 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1026,7 +1026,7 @@
@Override
public void updateState(@Nullable PersistableBundle options,
- @Nullable SharedMemory sharedMemory) {
+ @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
enforceCallingPermission(Manifest.permission.MANAGE_HOTWORD_DETECTION);
synchronized (this) {
enforceIsCurrentVoiceInteractionService();
@@ -1037,7 +1037,7 @@
}
final long caller = Binder.clearCallingIdentity();
try {
- mImpl.updateStateLocked(options, sharedMemory);
+ mImpl.updateStateLocked(options, sharedMemory, callback);
} finally {
Binder.restoreCallingIdentity(caller);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index efa7f78..6922ccc 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -405,7 +405,7 @@
}
public void updateStateLocked(@Nullable PersistableBundle options,
- @Nullable SharedMemory sharedMemory) {
+ @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
if (DEBUG) {
Slog.d(TAG, "updateStateLocked");
}
@@ -427,7 +427,7 @@
if (mHotwordDetectionConnection == null) {
mHotwordDetectionConnection = new HotwordDetectionConnection(mServiceStub, mContext,
mHotwordDetectionComponentName, mUser, /* bindInstantServiceAllowed= */ false,
- options, sharedMemory);
+ options, sharedMemory, callback);
} else {
mHotwordDetectionConnection.updateStateLocked(options, sharedMemory);
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 1677c8c..4886789 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -25,6 +25,8 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -1004,6 +1006,17 @@
PRESENTATION_PAYPHONE})
public @interface Presentation {}
+
+ /**
+ * Enable READ_PHONE_STATE protection on APIs querying and notifying call state, such as
+ * {@code TelecomManager#getCallState}, {@link TelephonyManager#getCallStateForSubscription()},
+ * and {@link android.telephony.TelephonyCallback.CallStateListener}.
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
+ // this magic number is a bug ID
+ public static final long ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION = 157233955L;
+
private static final String TAG = "TelecomManager";
@@ -1758,21 +1771,23 @@
* {@link TelephonyManager#CALL_STATE_OFFHOOK}
* {@link TelephonyManager#CALL_STATE_IDLE}
*
- * Note that this API does not require the
- * {@link android.Manifest.permission#READ_PHONE_STATE} permission. This is intentional, to
- * preserve the behavior of {@link TelephonyManager#getCallState()}, which also did not require
- * the permission.
- *
* Takes into consideration both managed and self-managed calls.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+ * targeting API level 31+.
*
* @hide
*/
+ @RequiresPermission(anyOf = {READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PHONE_STATE}, conditional = true)
@SystemApi
public @CallState int getCallState() {
ITelecomService service = getTelecomService();
if (service != null) {
try {
- return service.getCallState();
+ return service.getCallStateUsingPackage(mContext.getPackageName(),
+ mContext.getAttributionTag());
} catch (RemoteException e) {
Log.d(TAG, "RemoteException calling getCallState().", e);
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 78283fa..18afde7 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -195,11 +195,18 @@
/**
* @see TelecomServiceImpl#getCallState
+ * Note: only kept around to not break app compat, however this will throw a SecurityException
+ * on API 31+.
*/
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
int getCallState();
/**
+ * @see TelecomServiceImpl#getCallState
+ */
+ int getCallStateUsingPackage(String callingPackage, String callingFeatureId);
+
+ /**
* @see TelecomServiceImpl#endCall
*/
boolean endCall(String callingPackage);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3db31ec..1cc9c6f 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -4902,6 +4902,15 @@
public static final String KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL =
"display_call_strength_indicator_bool";
+ /**
+ * Determine whether or not to display no data notification when data setup is permanently
+ * failed.
+ *
+ * @hide
+ */
+ public static final String KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL =
+ "display_no_data_notification_on_permanent_failure_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -5478,6 +5487,7 @@
sDefaults.putBoolean(KEY_HIDE_NO_CALLING_INDICATOR_ON_DATA_NETWORK_BOOL, false);
sDefaults.putBoolean(KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL, true);
sDefaults.putString(KEY_CARRIER_PROVISIONING_APP_STRING, "");
+ sDefaults.putBoolean(KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d2da51a..653aa9c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -105,6 +105,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.IBooleanConsumer;
import com.android.internal.telephony.ICallForwardingInfoCallback;
@@ -139,6 +140,7 @@
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -431,6 +433,27 @@
}
/**
+ * Post a runnable to the BackgroundThread.
+ *
+ * Used to invoke user callbacks without calling into the caller's executor from the caller's
+ * calling thread context, for example to provide asynchronous error information that is
+ * generated locally (not over a binder thread).
+ *
+ * <p>This is not necessary unless you are invoking caller's code asynchronously from within
+ * the caller's thread context.
+ *
+ * @param r a runnable.
+ */
+ private static void runOnBackgroundThread(@NonNull Runnable r) {
+ try {
+ BackgroundThread.getExecutor().execute(r);
+ } catch (RejectedExecutionException e) {
+ throw new IllegalStateException(
+ "Failed to post a callback from the caller's thread context.", e);
+ }
+ }
+
+ /**
* Returns the multi SIM variant
* Returns DSDS for Dual SIM Dual Standby
* Returns DSDA for Dual SIM Dual Active
@@ -5702,9 +5725,20 @@
* Note: The call state returned via this method may differ from what is reported by
* {@link PhoneStateListener#onCallStateChanged(int, String)}, as that callback only considers
* Telephony (mobile) calls.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+ * targeting API level 31+.
*
* @return the current call state.
+ * @deprecated Use {@link #getCallStateForSubscription} to retrieve the call state for a
+ * specific telephony subscription (which allows carrier privileged apps),
+ * {@link TelephonyCallback.CallStateListener} for real-time call state updates, or
+ * {@link TelecomManager#isInCall()}, which supplies an aggregate "in call" state for the entire
+ * device.
*/
+ @RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
+ @Deprecated
public @CallState int getCallState() {
if (mContext != null) {
TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
@@ -5716,19 +5750,48 @@
}
/**
+ * Retrieve the call state for a specific subscription that was specified when this
+ * TelephonyManager instance was created.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} or that the calling
+ * application has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * @see TelephonyManager#createForSubscriptionId(int)
+ * @see TelephonyManager#createForPhoneAccountHandle(PhoneAccountHandle)
+ * @return The call state of the subscription associated with this TelephonyManager instance.
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public @CallState int getCallStateForSubscription() {
+ return getCallState(getSubId());
+ }
+
+ /**
* Returns the Telephony call state for calls on a specific subscription.
* <p>
* Note: This method considers ONLY telephony/mobile calls, where {@link #getCallState()}
* considers the state of calls from other {@link android.telecom.ConnectionService}
* implementations.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+ * targeting API level 31+ or that the calling application has carrier privileges
+ * (see {@link #hasCarrierPrivileges()}).
*
* @param subId the subscription to check call state for.
* @hide
*/
@UnsupportedAppUsage
+ @RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
public @CallState int getCallState(int subId) {
- int phoneId = SubscriptionManager.getPhoneId(subId);
- return getCallStateForSlot(phoneId);
+ ITelephony telephony = getITelephony();
+ if (telephony == null) {
+ return CALL_STATE_IDLE;
+ }
+ try {
+ return telephony.getCallStateForSubscription(subId, mContext.getPackageName(),
+ mContext.getAttributionTag());
+ } catch (RemoteException e) {
+ return CALL_STATE_IDLE;
+ }
}
/**
@@ -5745,22 +5808,28 @@
* Note: This method considers ONLY telephony/mobile calls, where {@link #getCallState()}
* considers the state of calls from other {@link android.telecom.ConnectionService}
* implementations.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+ * targeting API level 31+ or that the calling application has carrier privileges
+ * (see {@link #hasCarrierPrivileges()}).
*
* @param slotIndex the SIM slot index to check call state for.
* @hide
*/
+ @RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
public @CallState int getCallStateForSlot(int slotIndex) {
try {
+ int[] subId = SubscriptionManager.getSubId(slotIndex);
ITelephony telephony = getITelephony();
- if (telephony == null)
+ if (telephony == null || subId == null || subId.length == 0) {
return CALL_STATE_IDLE;
- return telephony.getCallStateForSlot(slotIndex);
- } catch (RemoteException ex) {
+ }
+ return telephony.getCallStateForSubscription(subId[0], mContext.getPackageName(),
+ mContext.getAttributionTag());
+ } catch (RemoteException | NullPointerException ex) {
// the phone process is restarting.
return CALL_STATE_IDLE;
- } catch (NullPointerException ex) {
- // the phone process is restarting.
- return CALL_STATE_IDLE;
}
}
@@ -6240,7 +6309,7 @@
/**
* Error response to
- * {@link android.telephony.TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()}.
+ * {@link TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()}.
*
* Invoked when an error condition prevents updated {@link CellInfo} from being fetched
* and returned from the modem. Callers of requestCellInfoUpdate() should override this
@@ -6258,6 +6327,20 @@
};
/**
+ * Used for checking if the target SDK version for the current process is S or above.
+ *
+ * <p> Applies to the following methods:
+ * {@link #requestCellInfoUpdate},
+ * {@link #setPreferredOpportunisticDataSubscription},
+ * {@link #updateAvailableNetworks},
+ * requestNumberVerification(),
+ * setSimPowerStateForSlot(),
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
+ private static final long NULL_TELEPHONY_THROW_NO_CB = 182185642L;
+
+ /**
* Requests all available cell information from the current subscription for observed
* camped/registered, serving, and neighboring cells.
*
@@ -6277,7 +6360,14 @@
@NonNull @CallbackExecutor Executor executor, @NonNull CellInfoCallback callback) {
try {
ITelephony telephony = getITelephony();
- if (telephony == null) return;
+ if (telephony == null) {
+ if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+ throw new IllegalStateException("Telephony is null");
+ } else {
+ return;
+ }
+ }
+
telephony.requestCellInfoUpdate(
getSubId(),
new ICellInfoCallback.Stub() {
@@ -6304,6 +6394,8 @@
}
}, getOpPackageName(), getAttributionTag());
} catch (RemoteException ex) {
+ runOnBackgroundThread(() -> executor.execute(
+ () -> callback.onError(CellInfoCallback.ERROR_MODEM_ERROR, ex)));
}
}
@@ -6331,7 +6423,14 @@
@NonNull @CallbackExecutor Executor executor, @NonNull CellInfoCallback callback) {
try {
ITelephony telephony = getITelephony();
- if (telephony == null) return;
+ if (telephony == null) {
+ if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+ throw new IllegalStateException("Telephony is null");
+ } else {
+ return;
+ }
+ }
+
telephony.requestCellInfoUpdateWithWorkSource(
getSubId(),
new ICellInfoCallback.Stub() {
@@ -6359,6 +6458,8 @@
}
}, getOpPackageName(), getAttributionTag(), workSource);
} catch (RemoteException ex) {
+ runOnBackgroundThread(() -> executor.execute(
+ () -> callback.onError(CellInfoCallback.ERROR_MODEM_ERROR, ex)));
}
}
@@ -7325,14 +7426,21 @@
try {
ITelephony telephony = getITelephony();
- if (telephony != null) {
- telephony.requestNumberVerification(range, timeoutMillis, internalCallback,
- getOpPackageName());
+ if (telephony == null) {
+ if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+ throw new IllegalStateException("Telephony is null");
+ } else {
+ return;
+ }
}
+
+ telephony.requestNumberVerification(range, timeoutMillis, internalCallback,
+ getOpPackageName());
} catch (RemoteException ex) {
Rlog.e(TAG, "requestNumberVerification RemoteException", ex);
- executor.execute(() ->
- callback.onVerificationFailed(NumberVerificationCallback.REASON_UNSPECIFIED));
+ runOnBackgroundThread(() -> executor.execute(
+ () -> callback.onVerificationFailed(
+ NumberVerificationCallback.REASON_UNSPECIFIED)));
}
}
@@ -10701,6 +10809,8 @@
}
try {
ITelephony telephony = getITelephony();
+ if (telephony == null) throw new IllegalStateException("Telephony is null.");
+
IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
@@ -10708,11 +10818,18 @@
Binder.withCleanCallingIdentity(() -> callback.accept(result)));
}
};
- if (telephony != null) {
- telephony.setSimPowerStateForSlotWithCallback(slotIndex, state, internalCallback);
+ if (telephony == null) {
+ if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+ throw new IllegalStateException("Telephony is null");
+ } else {
+ return;
+ }
}
+ telephony.setSimPowerStateForSlotWithCallback(slotIndex, state, internalCallback);
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#setSimPowerStateForSlot", e);
+ runOnBackgroundThread(() -> executor.execute(
+ () -> callback.accept(SET_SIM_POWER_STATE_MODEM_ERROR)));
} catch (SecurityException e) {
Log.e(TAG, "Permission error calling ITelephony#setSimPowerStateForSlot",
e);
@@ -13285,22 +13402,12 @@
try {
IOns iOpportunisticNetworkService = getIOns();
if (iOpportunisticNetworkService == null) {
- if (executor == null || callback == null) {
- return;
+ if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+ throw new IllegalStateException("Opportunistic Network Service is null");
+ } else {
+ // Let the general remote exception handling catch this.
+ throw new RemoteException("Null Opportunistic Network Service!");
}
- final long identity = Binder.clearCallingIdentity();
- try {
- executor.execute(() -> {
- if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
- callback.accept(SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION);
- } else {
- callback.accept(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
- }
- });
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- return;
}
ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
@Override
@@ -13323,9 +13430,18 @@
.setPreferredDataSubscriptionId(subId, needValidation, callbackStub,
pkgForDebug);
} catch (RemoteException ex) {
- Rlog.e(TAG, "setPreferredDataSubscriptionId RemoteException", ex);
+ Rlog.e(TAG, "setPreferredOpportunisticDataSubscription RemoteException", ex);
+ if (executor == null || callback == null) {
+ return;
+ }
+ runOnBackgroundThread(() -> executor.execute(() -> {
+ if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
+ callback.accept(SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION);
+ } else {
+ callback.accept(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+ }
+ }));
}
- return;
}
/**
@@ -13382,37 +13498,18 @@
@Nullable @CallbackExecutor Executor executor,
@UpdateAvailableNetworksResult @Nullable Consumer<Integer> callback) {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ Objects.requireNonNull(availableNetworks, "availableNetworks must not be null.");
try {
IOns iOpportunisticNetworkService = getIOns();
- if (iOpportunisticNetworkService == null || availableNetworks == null) {
- if (executor == null || callback == null) {
- return;
- }
- if (iOpportunisticNetworkService == null) {
- final long identity = Binder.clearCallingIdentity();
- try {
- executor.execute(() -> {
- if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
- callback.accept(UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION);
- } else {
- callback.accept(UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE);
- }
- });
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ if (iOpportunisticNetworkService == null) {
+ if (Compatibility.isChangeEnabled(NULL_TELEPHONY_THROW_NO_CB)) {
+ throw new IllegalStateException("Opportunistic Network Service is null");
} else {
- final long identity = Binder.clearCallingIdentity();
- try {
- executor.execute(() -> {
- callback.accept(UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
- });
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ // Let the general remote exception handling catch this.
+ throw new RemoteException("Null Opportunistic Network Service!");
}
- return;
}
+
IUpdateAvailableNetworksCallback callbackStub =
new IUpdateAvailableNetworksCallback.Stub() {
@Override
@@ -13420,20 +13517,25 @@
if (executor == null || callback == null) {
return;
}
- final long identity = Binder.clearCallingIdentity();
- try {
- executor.execute(() -> {
- callback.accept(result);
- });
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ Binder.withCleanCallingIdentity(() -> {
+ executor.execute(() -> callback.accept(result));
+ });
}
};
- iOpportunisticNetworkService.updateAvailableNetworks(availableNetworks, callbackStub,
- pkgForDebug);
+ iOpportunisticNetworkService
+ .updateAvailableNetworks(availableNetworks, callbackStub, pkgForDebug);
} catch (RemoteException ex) {
Rlog.e(TAG, "updateAvailableNetworks RemoteException", ex);
+ if (executor == null || callback == null) {
+ return;
+ }
+ runOnBackgroundThread(() -> executor.execute(() -> {
+ if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
+ callback.accept(UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION);
+ } else {
+ callback.accept(UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE);
+ }
+ }));
}
}
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 6315b24..b384e50 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -391,6 +391,7 @@
* event to the framework.
* @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability
* exchange if it is supported by the device.
+ * @hide
*/
public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(
@NonNull Executor executor, @NonNull CapabilityExchangeEventListener listener) {
@@ -399,14 +400,45 @@
}
/**
+ * Retrieve the implementation of UCE for this {@link RcsFeature}, which can use either
+ * presence or OPTIONS for capability exchange.
+ *
+ * Will only be requested by the framework if capability exchange is configured
+ * as capable during a
+ * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}
+ * operation and the RcsFeature sets the status of the capability to true using
+ * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}.
+ *
+ * @param listener A {@link CapabilityExchangeEventListener} to send the capability exchange
+ * event to the framework.
+ * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability
+ * exchange if it is supported by the device.
+ */
+ public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(
+ @NonNull CapabilityExchangeEventListener listener) {
+ // Base Implementation, override to implement functionality
+ return new RcsCapabilityExchangeImplBase();
+ }
+
+ /**
* Remove the given CapabilityExchangeImplBase instance.
* @param capExchangeImpl The {@link RcsCapabilityExchangeImplBase} instance to be removed.
+ * @hide
*/
public void removeCapabilityExchangeImpl(
@NonNull RcsCapabilityExchangeImplBase capExchangeImpl) {
// Override to implement the process of removing RcsCapabilityExchangeImplBase instance.
}
+ /**
+ * Remove the given CapabilityExchangeImplBase instance.
+ * @param capExchangeImpl The {@link RcsCapabilityExchangeImplBase} instance to be destroyed.
+ */
+ public void destroyCapabilityExchangeImpl(
+ @NonNull RcsCapabilityExchangeImplBase capExchangeImpl) {
+ // Override to implement the process of destroying RcsCapabilityExchangeImplBase instance.
+ }
+
/**{@inheritDoc}*/
@Override
public void onFeatureRemoved() {
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
index 25b9446..a117adc 100644
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
@@ -356,12 +356,13 @@
void onTerminated(@NonNull String reason, long retryAfterMilliseconds) throws ImsException;
}
- private final Executor mBinderExecutor;
+ private Executor mBinderExecutor;
/**
* Create a new RcsCapabilityExchangeImplBase instance.
*
* @param executor The executor that remote calls from the framework will be called on.
+ * @hide
*/
public RcsCapabilityExchangeImplBase(@NonNull Executor executor) {
if (executor == null) {
@@ -371,6 +372,12 @@
}
/**
+ * Create a new RcsCapabilityExchangeImplBase instance.
+ */
+ public RcsCapabilityExchangeImplBase() {
+ }
+
+ /**
* The user capabilities of one or multiple contacts have been requested by the framework.
* <p>
* The implementer must follow up this call with an
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 46752b7..afc538d 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -298,9 +298,9 @@
int getCallState();
/**
- * Returns the call state for a slot.
+ * Returns the call state for a specific subscriiption.
*/
- int getCallStateForSlot(int slotIndex);
+ int getCallStateForSubscription(int subId, String callingPackage, String featureId);
/**
* Replaced by getDataActivityForSubId.
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index 5b9f67e..7be42f4 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.AttributionSource;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@@ -60,21 +61,20 @@
*/
private class InversionIContentProvider implements IContentProvider {
@Override
- public ContentProviderResult[] applyBatch(String callingPackage,
- @Nullable String featureId, String authority,
- ArrayList<ContentProviderOperation> operations)
+ public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
+ String authority, ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
return MockContentProvider.this.applyBatch(authority, operations);
}
@Override
- public int bulkInsert(String callingPackage, @Nullable String featureId, Uri url,
+ public int bulkInsert(@NonNull AttributionSource attributionSource, Uri url,
ContentValues[] initialValues) throws RemoteException {
return MockContentProvider.this.bulkInsert(url, initialValues);
}
@Override
- public int delete(String callingPackage, @Nullable String featureId, Uri url,
+ public int delete(@NonNull AttributionSource attributionSource, Uri url,
Bundle extras) throws RemoteException {
return MockContentProvider.this.delete(url, extras);
}
@@ -90,40 +90,40 @@
}
@Override
- public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
+ public Uri insert(@NonNull AttributionSource attributionSource, Uri url,
ContentValues initialValues, Bundle extras) throws RemoteException {
return MockContentProvider.this.insert(url, initialValues, extras);
}
@Override
- public AssetFileDescriptor openAssetFile(String callingPackage,
- @Nullable String featureId, Uri url, String mode, ICancellationSignal signal)
+ public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
+ Uri url, String mode, ICancellationSignal signal)
throws RemoteException, FileNotFoundException {
return MockContentProvider.this.openAssetFile(url, mode);
}
@Override
- public ParcelFileDescriptor openFile(String callingPackage, @Nullable String featureId,
- Uri url, String mode, ICancellationSignal signal, IBinder callerToken)
+ public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource,
+ Uri url, String mode, ICancellationSignal signal)
throws RemoteException, FileNotFoundException {
return MockContentProvider.this.openFile(url, mode);
}
@Override
- public Cursor query(String callingPackage, @Nullable String featureId, Uri url,
+ public Cursor query(@NonNull AttributionSource attributionSource, Uri url,
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable ICancellationSignal cancellationSignal) throws RemoteException {
return MockContentProvider.this.query(url, projection, queryArgs, null);
}
@Override
- public int update(String callingPackage, @Nullable String featureId, Uri url,
+ public int update(@NonNull AttributionSource attributionSource, Uri url,
ContentValues values, Bundle extras) throws RemoteException {
return MockContentProvider.this.update(url, values, extras);
}
@Override
- public Bundle call(String callingPackage, @Nullable String featureId, String authority,
+ public Bundle call(@NonNull AttributionSource attributionSource, String authority,
String method, String request, Bundle args) throws RemoteException {
return MockContentProvider.this.call(authority, method, request, args);
}
@@ -139,9 +139,10 @@
}
@Override
- public AssetFileDescriptor openTypedAssetFile(String callingPackage,
- @Nullable String featureId, Uri url, String mimeType, Bundle opts,
- ICancellationSignal signal) throws RemoteException, FileNotFoundException {
+ public AssetFileDescriptor openTypedAssetFile(
+ @NonNull AttributionSource attributionSource, Uri url, String mimeType,
+ Bundle opts, ICancellationSignal signal)
+ throws RemoteException, FileNotFoundException {
return MockContentProvider.this.openTypedAssetFile(url, mimeType, opts);
}
@@ -151,37 +152,37 @@
}
@Override
- public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+ public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri uri)
throws RemoteException {
return MockContentProvider.this.canonicalize(uri);
}
@Override
- public void canonicalizeAsync(String callingPkg, String featureId, Uri uri,
+ public void canonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
RemoteCallback callback) {
MockContentProvider.this.canonicalizeAsync(uri, callback);
}
@Override
- public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+ public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri uri)
throws RemoteException {
return MockContentProvider.this.uncanonicalize(uri);
}
@Override
- public void uncanonicalizeAsync(String callingPkg, String featureId, Uri uri,
+ public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
RemoteCallback callback) {
MockContentProvider.this.uncanonicalizeAsync(uri, callback);
}
@Override
- public boolean refresh(String callingPkg, @Nullable String featureId, Uri url,
+ public boolean refresh(@NonNull AttributionSource attributionSource, Uri url,
Bundle args, ICancellationSignal cancellationSignal) throws RemoteException {
return MockContentProvider.this.refresh(url, args);
}
@Override
- public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri,
+ public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri,
int uid, int modeFlags) {
return MockContentProvider.this.checkUriPermission(uri, uid, modeFlags);
}
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index 82a1cf7..b81c707 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -16,7 +16,9 @@
package android.test.mock;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.AttributionSource;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
@@ -46,14 +48,14 @@
*/
public class MockIContentProvider implements IContentProvider {
@Override
- public int bulkInsert(String callingPackage, @Nullable String featureId, Uri url,
+ public int bulkInsert(@NonNull AttributionSource attributionSource, Uri url,
ContentValues[] initialValues) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
@SuppressWarnings("unused")
- public int delete(String callingPackage, @Nullable String featureId, Uri url,
+ public int delete(@NonNull AttributionSource attributionSource, Uri url,
Bundle extras) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -75,31 +77,31 @@
@Override
@SuppressWarnings("unused")
- public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
+ public Uri insert(@NonNull AttributionSource attributionSource, Uri url,
ContentValues initialValues, Bundle extras) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public ParcelFileDescriptor openFile(String callingPackage, @Nullable String featureId,
- Uri url, String mode, ICancellationSignal signal, IBinder callerToken) {
+ public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource,
+ Uri url, String mode, ICancellationSignal signal) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public AssetFileDescriptor openAssetFile(String callingPackage, @Nullable String featureId,
+ public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
Uri uri, String mode, ICancellationSignal signal) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public ContentProviderResult[] applyBatch(String callingPackage, @Nullable String featureId,
+ public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
String authority, ArrayList<ContentProviderOperation> operations) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public Cursor query(String callingPackage, @Nullable String featureId, Uri url,
+ public Cursor query(@NonNull AttributionSource attributionSource, Uri url,
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable ICancellationSignal cancellationSignal) {
throw new UnsupportedOperationException("unimplemented mock method");
@@ -111,13 +113,13 @@
}
@Override
- public int update(String callingPackage, @Nullable String featureId, Uri url,
+ public int update(@NonNull AttributionSource attributionSource, Uri url,
ContentValues values, Bundle extras) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public Bundle call(String callingPackage, @Nullable String featureId, String authority,
+ public Bundle call(@NonNull AttributionSource attributionSource, String authority,
String method, String request, Bundle args) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -133,9 +135,9 @@
}
@Override
- public AssetFileDescriptor openTypedAssetFile(String callingPackage,
- @Nullable String featureId, Uri url, String mimeType, Bundle opts,
- ICancellationSignal signal) throws RemoteException, FileNotFoundException {
+ public AssetFileDescriptor openTypedAssetFile(@NonNull AttributionSource attributionSource,
+ Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
+ throws RemoteException, FileNotFoundException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -145,48 +147,48 @@
}
@Override
- public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri) {
+ public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri uri) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
@SuppressWarnings("deprecation")
- public void canonicalizeAsync(String callingPkg, String featureId, Uri uri,
+ public void canonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
RemoteCallback remoteCallback) {
AsyncTask.SERIAL_EXECUTOR.execute(() -> {
final Bundle bundle = new Bundle();
bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
- canonicalize(callingPkg, featureId, uri));
+ canonicalize(attributionSource, uri));
remoteCallback.sendResult(bundle);
});
}
@Override
- public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri) {
+ public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri uri) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
@SuppressWarnings("deprecation")
- public void uncanonicalizeAsync(String callingPkg, String featureId, Uri uri,
+ public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri,
RemoteCallback remoteCallback) {
AsyncTask.SERIAL_EXECUTOR.execute(() -> {
final Bundle bundle = new Bundle();
bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
- uncanonicalize(callingPkg, featureId, uri));
+ uncanonicalize(attributionSource, uri));
remoteCallback.sendResult(bundle);
});
}
@Override
- public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args,
+ public boolean refresh(@NonNull AttributionSource attributionSource, Uri url, Bundle args,
ICancellationSignal cancellationSignal) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
/** {@hide} */
@Override
- public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri, int uid,
+ public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri, int uid,
int modeFlags) {
throw new UnsupportedOperationException("unimplemented mock method call");
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index e6a4501..ed0a98d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -101,10 +101,10 @@
}
} else {
assertLayersStart {
- this.coversAtLeast(startingBounds)
+ this.visibleRegion().coversAtLeast(startingBounds)
}
assertLayersEnd {
- this.coversAtLeast(endingBounds)
+ this.visibleRegion().coversAtLeast(endingBounds)
}
}
}
@@ -152,10 +152,10 @@
val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
assertLayersStart {
- this.coversExactly(startingPos, NAV_BAR_LAYER_NAME)
+ this.visibleRegion(NAV_BAR_LAYER_NAME).coversExactly(startingPos)
}
assertLayersEnd {
- this.coversExactly(endingPos, NAV_BAR_LAYER_NAME)
+ this.visibleRegion(NAV_BAR_LAYER_NAME).coversExactly(endingPos)
}
}
@@ -168,10 +168,10 @@
val endingPos = WindowUtils.getStatusBarPosition(endRotation)
assertLayersStart {
- this.coversExactly(startingPos, STATUS_BAR_WINDOW_NAME)
+ this.visibleRegion(STATUS_BAR_WINDOW_NAME).coversExactly(startingPos)
}
assertLayersEnd {
- this.coversExactly(endingPos, STATUS_BAR_WINDOW_NAME)
+ this.visibleRegion(STATUS_BAR_WINDOW_NAME).coversExactly(endingPos)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
index e118363..a524466 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
@@ -19,6 +19,7 @@
import android.app.Instrumentation
import android.platform.test.annotations.Presubmit
import android.view.Surface
+import androidx.test.filters.FlakyTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.FlickerBuilderProvider
import com.android.server.wm.flicker.FlickerTestParameter
@@ -87,13 +88,13 @@
testSpec.statusBarLayerIsAlwaysVisible()
}
- @Presubmit
+ @FlakyTest
@Test
open fun navBarLayerRotatesAndScales() {
testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
}
- @Presubmit
+ @FlakyTest
@Test
open fun statusBarLayerRotatesScales() {
testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
index 619a05e..bd7c185 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
@@ -34,7 +34,7 @@
wmHelper: WindowManagerStateHelper?
) {
// do nothing (the app is focused automatically)
- waitAndAssertIMEShown(device, wmHelper)
+ waitIMEShown(device, wmHelper)
}
override fun open() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
index d8091a9..83fddae 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
@@ -51,17 +51,17 @@
"was left in an unknown state (e.g. in split screen)"
}
editText.click()
- waitAndAssertIMEShown(device, wmHelper)
+ waitIMEShown(device, wmHelper)
}
- protected fun waitAndAssertIMEShown(
+ protected fun waitIMEShown(
device: UiDevice,
wmHelper: WindowManagerStateHelper? = null
) {
if (wmHelper == null) {
device.waitForIdle()
} else {
- require(wmHelper.waitImeWindowShown()) { "IME did not appear" }
+ wmHelper.waitImeWindowShown()
}
}
@@ -78,7 +78,7 @@
if (wmHelper == null) {
device.waitForIdle()
} else {
- require(wmHelper.waitImeWindowGone()) { "IME did did not close" }
+ wmHelper.waitImeWindowGone()
}
}
}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
index d39044ab..7ba9db1 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
@@ -20,6 +20,7 @@
import android.platform.test.annotations.Presubmit
import android.view.Surface
import android.view.WindowManagerPolicyConstants
+import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.FlickerBuilderProvider
@@ -134,7 +135,7 @@
}
}
- @Presubmit
+ @FlakyTest
@Test
fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
testSpec.assertWm {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
new file mode 100644
index 0000000..8e73ab1
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.ime
+
+import android.app.Instrumentation
+import android.platform.test.annotations.Presubmit
+import android.view.WindowManagerPolicyConstants
+import androidx.test.filters.RequiresDevice
+import androidx.test.platform.app.InstrumentationRegistry
+
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.startRotation
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test IME windows switching with 2-Buttons or gestural navigation.
+ * To run this test: `atest FlickerTests:SwitchImeWindowsFromGestureNavTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class SwitchImeWindowsFromGestureNavTest(private val testSpec: FlickerTestParameter) {
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val testApp = SimpleAppHelper(instrumentation)
+ private val imeTestApp = ImeAppHelper(instrumentation)
+
+ @FlickerBuilderProvider
+ fun buildFlicker(): FlickerBuilder {
+ return FlickerBuilder(instrumentation).apply {
+ setup {
+ eachRun {
+ this.setRotation(testSpec.config.startRotation)
+ testApp.launchViaIntent(wmHelper)
+ imeTestApp.launchViaIntent(wmHelper)
+ imeTestApp.openIME(device, wmHelper)
+ }
+ }
+ teardown {
+ eachRun {
+ device.pressHome()
+ wmHelper.waitForHomeActivityVisible()
+ }
+ test {
+ imeTestApp.exit(wmHelper)
+ }
+ }
+ transitions {
+ // [Step1]: Swipe right from imeTestApp to testApp task
+ val displayBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
+ val displayCenterX = displayBounds.bounds.width() / 2
+ device.swipe(displayCenterX, displayBounds.bounds.height(),
+ displayBounds.bounds.width(), displayBounds.bounds.height(), 20)
+ wmHelper.waitForFullScreenApp(testApp.component)
+ }
+ transitions {
+ // [Step2]: Swipe left to back to imeTestApp task
+ val displayBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
+ val displayCenterX = displayBounds.bounds.width() / 2
+ device.swipe(displayBounds.bounds.width(), displayBounds.bounds.height(),
+ displayCenterX, displayBounds.bounds.height(), 20)
+ wmHelper.waitForFullScreenApp(imeTestApp.component)
+ }
+ }
+ }
+
+ @Presubmit
+ @Test
+ fun imeAppWindowIsAlwaysVisible() = testSpec.imeAppWindowIsAlwaysVisible(imeTestApp)
+
+ @Presubmit
+ @Test
+ fun imeLayerBecomesVisible() = testSpec.imeLayerBecomesVisible()
+
+ @Presubmit
+ @Test
+ fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
+
+ @Presubmit
+ @Test
+ fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+ @Presubmit
+ @Test
+ fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+
+ @Presubmit
+ @Test
+ fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+ @Presubmit
+ @Test
+ fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTestParameter> {
+ return FlickerTestParameterFactory.getInstance()
+ .getConfigNonRotationTests(
+ repetitions = 3,
+ supportedNavigationModes = listOf(
+ WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
+ )
+ )
+ }
+ }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index f037f1d..35ad597 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -24,7 +24,6 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -61,20 +60,6 @@
@Presubmit
@Test
- override fun navBarLayerRotatesAndScales() {
- Assume.assumeFalse(testSpec.isRotated)
- super.navBarLayerRotatesAndScales()
- }
-
- @FlakyTest(bugId = 140855415)
- @Test
- fun navBarLayerRotatesAndScales_flaky() {
- Assume.assumeTrue(testSpec.isRotated)
- super.navBarLayerRotatesAndScales()
- }
-
- @Presubmit
- @Test
fun screenshotLayerBecomesInvisible() {
testSpec.assertLayers {
this.isVisible(testApp.getPackage())
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index f037f08..2989035 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -139,7 +139,7 @@
@Test
open fun appLayerRotates_StartingPos() {
testSpec.assertLayersStart {
- this.coversExactly(startingPos, testApp.getPackage())
+ this.visibleRegion(testApp.getPackage()).coversExactly(startingPos)
}
}
@@ -147,7 +147,7 @@
@Test
open fun appLayerRotates_EndingPos() {
testSpec.assertLayersEnd {
- this.coversExactly(endingPos, testApp.getPackage())
+ this.visibleRegion(testApp.getPackage()).coversExactly(endingPos)
}
}
}
\ No newline at end of file
diff --git a/tests/Input/src/com/android/test/input/InputEventSenderAndReceiverTest.kt b/tests/Input/src/com/android/test/input/InputEventSenderAndReceiverTest.kt
index b134fe7..fc1d839 100644
--- a/tests/Input/src/com/android/test/input/InputEventSenderAndReceiverTest.kt
+++ b/tests/Input/src/com/android/test/input/InputEventSenderAndReceiverTest.kt
@@ -75,16 +75,26 @@
class TestInputEventSender(channel: InputChannel, looper: Looper) :
InputEventSender(channel, looper) {
data class FinishedSignal(val seq: Int, val handled: Boolean)
+ data class Timeline(val inputEventId: Int, val gpuCompletedTime: Long, val presentTime: Long)
private val mFinishedSignals = LinkedBlockingQueue<FinishedSignal>()
+ private val mTimelines = LinkedBlockingQueue<Timeline>()
override fun onInputEventFinished(seq: Int, handled: Boolean) {
mFinishedSignals.put(FinishedSignal(seq, handled))
}
+ override fun onTimelineReported(inputEventId: Int, gpuCompletedTime: Long, presentTime: Long) {
+ mTimelines.put(Timeline(inputEventId, gpuCompletedTime, presentTime))
+ }
+
fun getFinishedSignal(): FinishedSignal {
return getEvent(mFinishedSignals)
}
+
+ fun getTimeline(): Timeline {
+ return getEvent(mTimelines)
+ }
}
class InputEventSenderAndReceiverTest {
@@ -125,4 +135,14 @@
// Check sender
assertEquals(TestInputEventSender.FinishedSignal(seq, handled = true), finishedSignal)
}
+
+ // The timeline case is slightly unusual because it goes from InputConsumer to InputPublisher.
+ @Test
+ fun testSendAndReceiveTimeline() {
+ val sent = TestInputEventSender.Timeline(
+ inputEventId = 1, gpuCompletedTime = 2, presentTime = 3)
+ mReceiver.reportTimeline(sent.inputEventId, sent.gpuCompletedTime, sent.presentTime)
+ val received = mSender.getTimeline()
+ assertEquals(sent, received)
+ }
}
diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java
index b7a42ec..fee65f0 100644
--- a/tests/net/java/android/net/VpnTransportInfoTest.java
+++ b/tests/net/java/android/net/VpnTransportInfoTest.java
@@ -16,6 +16,9 @@
package android.net;
+import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
+import static android.net.NetworkCapabilities.REDACT_NONE;
+
import static com.android.testutils.ParcelUtils.assertParcelSane;
import static org.junit.Assert.assertEquals;
@@ -33,23 +36,33 @@
@Test
public void testParceling() {
- VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
- assertParcelSane(v, 1 /* fieldCount */);
+ VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345");
+ assertParcelSane(v, 2 /* fieldCount */);
}
@Test
public void testEqualsAndHashCode() {
- VpnTransportInfo v1 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
- VpnTransportInfo v2 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE);
- VpnTransportInfo v3 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
- VpnTransportInfo v4 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY);
- VpnTransportInfo v5 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM);
+ String session1 = "12345";
+ String session2 = "6789";
+ VpnTransportInfo v11 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
+ VpnTransportInfo v12 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE, session1);
+ VpnTransportInfo v13 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
+ VpnTransportInfo v14 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session1);
+ VpnTransportInfo v15 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM, session1);
+ VpnTransportInfo v21 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session2);
- assertNotEquals(v1, v2);
- assertNotEquals(v3, v4);
- assertNotEquals(v4, v5);
+ VpnTransportInfo v31 = v11.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
+ VpnTransportInfo v32 = v13.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
- assertEquals(v1, v3);
- assertEquals(v1.hashCode(), v3.hashCode());
+ assertNotEquals(v11, v12);
+ assertNotEquals(v13, v14);
+ assertNotEquals(v14, v15);
+ assertNotEquals(v14, v21);
+
+ assertEquals(v11, v13);
+ assertEquals(v31, v32);
+ assertEquals(v11.hashCode(), v13.hashCode());
+ assertEquals(REDACT_FOR_NETWORK_SETTINGS, v32.getApplicableRedactions());
+ assertEquals(session1, v15.makeCopy(REDACT_NONE).sessionId);
}
-}
\ No newline at end of file
+}
diff --git a/tests/net/java/android/net/util/KeepaliveUtilsTest.kt b/tests/net/java/android/net/util/KeepaliveUtilsTest.kt
index b62bdbc..5006d53 100644
--- a/tests/net/java/android/net/util/KeepaliveUtilsTest.kt
+++ b/tests/net/java/android/net/util/KeepaliveUtilsTest.kt
@@ -101,7 +101,7 @@
// Check valid customization generates expected array.
val validRes = arrayOf("0,3", "1,0", "4,4")
- val expectedValidRes = intArrayOf(3, 0, 0, 0, 4, 0, 0, 0)
+ val expectedValidRes = intArrayOf(3, 0, 0, 0, 4, 0, 0, 0, 0)
val mockContext = getMockedContextWithStringArrayRes(
R.array.config_networkSupportedKeepaliveCount,
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index e6ff5d8..c3cb5f8 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
@@ -31,6 +32,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
+import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
@@ -716,6 +718,9 @@
private int mProbesSucceeded;
private String mNmValidationRedirectUrl = null;
private boolean mNmProvNotificationRequested = false;
+ private Runnable mCreatedCallback;
+ private Runnable mUnwantedCallback;
+ private Runnable mDisconnectedCallback;
private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
// Contains the redirectUrl from networkStatus(). Before reading, wait for
@@ -770,6 +775,24 @@
mRedirectUrl = redirectUrl;
mNetworkStatusReceived.open();
}
+
+ @Override
+ public void onNetworkCreated() {
+ super.onNetworkCreated();
+ if (mCreatedCallback != null) mCreatedCallback.run();
+ }
+
+ @Override
+ public void onNetworkUnwanted() {
+ super.onNetworkUnwanted();
+ if (mUnwantedCallback != null) mUnwantedCallback.run();
+ }
+
+ @Override
+ public void onNetworkDestroyed() {
+ super.onNetworkDestroyed();
+ if (mDisconnectedCallback != null) mDisconnectedCallback.run();
+ }
};
assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
@@ -971,6 +994,18 @@
p.timestampMillis = DATA_STALL_TIMESTAMP;
mNmCallbacks.notifyDataStallSuspected(p);
}
+
+ public void setCreatedCallback(Runnable r) {
+ mCreatedCallback = r;
+ }
+
+ public void setUnwantedCallback(Runnable r) {
+ mUnwantedCallback = r;
+ }
+
+ public void setDisconnectedCallback(Runnable r) {
+ mDisconnectedCallback = r;
+ }
}
/**
@@ -1181,10 +1216,12 @@
if (mAgentRegistered) throw new IllegalStateException("already registered");
updateState(NetworkInfo.DetailedState.CONNECTING, "registerAgent");
mConfig = new VpnConfig();
+ mConfig.session = "MySession12345";
setUids(uids);
if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
mInterface = VPN_IFNAME;
- mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
+ mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType(),
+ mConfig.session));
mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
mNetworkCapabilities);
mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
@@ -1361,10 +1398,21 @@
}
private void mockUidNetworkingBlocked() {
- doAnswer(i -> NetworkPolicyManager.isUidBlocked(mBlockedReasons, i.getArgument(1))
+ doAnswer(i -> isUidBlocked(mBlockedReasons, i.getArgument(1))
).when(mNetworkPolicyManager).isUidNetworkingBlocked(anyInt(), anyBoolean());
}
+ private boolean isUidBlocked(int blockedReasons, boolean meteredNetwork) {
+ final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK);
+ if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) {
+ return true;
+ }
+ if (meteredNetwork) {
+ return blockedReasons != BLOCKED_REASON_NONE;
+ }
+ return false;
+ }
+
private void setBlockedReasonChanged(int blockedReasons) {
mBlockedReasons = blockedReasons;
mPolicyCallback.onUidBlockedReasonChanged(Process.myUid(), blockedReasons);
@@ -2427,8 +2475,7 @@
public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
PERMISSION_DENIED);
- mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
- PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
doNetworkCallbacksSanitizationTest(true /* sanitized */);
}
@@ -2436,7 +2483,7 @@
public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
PERMISSION_GRANTED);
- mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
doNetworkCallbacksSanitizationTest(false /* sanitized */);
}
@@ -2444,7 +2491,7 @@
public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
PERMISSION_DENIED);
- mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
doNetworkCallbacksSanitizationTest(false /* sanitized */);
}
@@ -2788,6 +2835,94 @@
}
@Test
+ public void testNetworkAgentCallbacks() throws Exception {
+ // Keeps track of the order of events that happen in this test.
+ final LinkedBlockingQueue<String> eventOrder = new LinkedBlockingQueue<>();
+
+ final NetworkRequest request = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI).build();
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ final AtomicReference<Network> wifiNetwork = new AtomicReference<>();
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+
+ // Expectations for state when various callbacks fire. These expectations run on the handler
+ // thread and not on the test thread because they need to prevent the handler thread from
+ // advancing while they examine state.
+
+ // 1. When onCreated fires, netd has been told to create the network.
+ mWiFiNetworkAgent.setCreatedCallback(() -> {
+ eventOrder.offer("onNetworkCreated");
+ wifiNetwork.set(mWiFiNetworkAgent.getNetwork());
+ assertNotNull(wifiNetwork.get());
+ try {
+ verify(mMockNetd).networkCreatePhysical(wifiNetwork.get().getNetId(),
+ INetd.PERMISSION_NONE);
+ } catch (RemoteException impossible) {
+ fail();
+ }
+ });
+
+ // 2. onNetworkUnwanted isn't precisely ordered with respect to any particular events. Just
+ // check that it is fired at some point after disconnect.
+ mWiFiNetworkAgent.setUnwantedCallback(() -> eventOrder.offer("onNetworkUnwanted"));
+
+ // 3. While the teardown timer is running, connectivity APIs report the network is gone, but
+ // netd has not yet been told to destroy it.
+ final Runnable duringTeardown = () -> {
+ eventOrder.offer("timePasses");
+ assertNull(mCm.getLinkProperties(wifiNetwork.get()));
+ try {
+ verify(mMockNetd, never()).networkDestroy(wifiNetwork.get().getNetId());
+ } catch (RemoteException impossible) {
+ fail();
+ }
+ };
+
+ // 4. After onNetworkDisconnected is called, connectivity APIs report the network is gone,
+ // and netd has been told to destroy it.
+ mWiFiNetworkAgent.setDisconnectedCallback(() -> {
+ eventOrder.offer("onNetworkDisconnected");
+ assertNull(mCm.getLinkProperties(wifiNetwork.get()));
+ try {
+ verify(mMockNetd).networkDestroy(wifiNetwork.get().getNetId());
+ } catch (RemoteException impossible) {
+ fail();
+ }
+ });
+
+ // Connect a network, and file a request for it after it has come up, to ensure the nascent
+ // timer is cleared and the test does not have to wait for it. Filing the request after the
+ // network has come up is necessary because ConnectivityService does not appear to clear the
+ // nascent timer if the first request satisfied by the network was filed before the network
+ // connected.
+ // TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
+ mWiFiNetworkAgent.connectWithoutInternet();
+ waitForIdle();
+ mCm.requestNetwork(request, callback);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+
+ // Set teardown delay and make sure CS has processed it.
+ mWiFiNetworkAgent.getNetworkAgent().setTeardownDelayMs(300);
+ waitForIdle();
+
+ // Post the duringTeardown lambda to the handler so it fires while teardown is in progress.
+ // The delay must be long enough it will run after the unregisterNetworkCallback has torn
+ // down the network and started the teardown timer, and short enough that the lambda is
+ // scheduled to run before the teardown timer.
+ final Handler h = new Handler(mCsHandlerThread.getLooper());
+ h.postDelayed(duringTeardown, 150);
+
+ // Disconnect the network and check that events happened in the right order.
+ mCm.unregisterNetworkCallback(callback);
+ assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ mCm.unregisterNetworkCallback(callback);
+ }
+
+ @Test
public void testExplicitlySelected() throws Exception {
NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
@@ -3480,8 +3615,7 @@
@Test
public void testCaptivePortalApi() throws Exception {
- mServiceContext.setPermission(
- android.Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
@@ -3515,8 +3649,7 @@
private TestNetworkCallback setupNetworkCallbackAndConnectToWifi() throws Exception {
// Grant NETWORK_SETTINGS permission to be able to receive LinkProperties change callbacks
// with sensitive (captive portal) data
- mServiceContext.setPermission(
- android.Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
@@ -3950,8 +4083,7 @@
@Test
public void testRegisterDefaultNetworkCallback() throws Exception {
// NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback.
- mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
- PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
@@ -4110,8 +4242,7 @@
() -> mCm.registerDefaultNetworkCallbackAsUid(APP1_UID, callback, handler));
callback.assertNoCallback();
- mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
- PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
mCm.registerSystemDefaultNetworkCallback(callback, handler);
callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
mCm.unregisterNetworkCallback(callback);
@@ -5481,10 +5612,11 @@
}
@Test
- public void testNetworkCallbackMaximum() {
+ public void testNetworkCallbackMaximum() throws Exception {
final int MAX_REQUESTS = 100;
final int CALLBACKS = 89;
final int INTENTS = 11;
+ final int SYSTEM_ONLY_MAX_REQUESTS = 250;
assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
NetworkRequest networkRequest = new NetworkRequest.Builder().build();
@@ -5533,6 +5665,33 @@
new Intent("d"), FLAG_IMMUTABLE))
);
+ // The system gets another SYSTEM_ONLY_MAX_REQUESTS slots.
+ final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
+ withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
+ ArrayList<NetworkCallback> systemRegistered = new ArrayList<>();
+ for (int i = 0; i < SYSTEM_ONLY_MAX_REQUESTS - 1; i++) {
+ NetworkCallback cb = new NetworkCallback();
+ if (i % 2 == 0) {
+ mCm.registerDefaultNetworkCallbackAsUid(1000000 + i, cb, handler);
+ } else {
+ mCm.registerNetworkCallback(networkRequest, cb);
+ }
+ systemRegistered.add(cb);
+ }
+ waitForIdle();
+
+ assertThrows(TooManyRequestsException.class, () ->
+ mCm.registerDefaultNetworkCallbackAsUid(1001042, new NetworkCallback(),
+ handler));
+ assertThrows(TooManyRequestsException.class, () ->
+ mCm.registerNetworkCallback(networkRequest, new NetworkCallback()));
+
+ for (NetworkCallback callback : systemRegistered) {
+ mCm.unregisterNetworkCallback(callback);
+ }
+ waitForIdle(); // Wait for requests to be unregistered before giving up the permission.
+ });
+
for (Object o : registered) {
if (o instanceof NetworkCallback) {
mCm.unregisterNetworkCallback((NetworkCallback)o);
@@ -5559,6 +5718,30 @@
waitForIdle();
for (int i = 0; i < MAX_REQUESTS; i++) {
+ NetworkCallback networkCallback = new NetworkCallback();
+ mCm.registerDefaultNetworkCallback(networkCallback);
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
+ waitForIdle();
+
+ for (int i = 0; i < MAX_REQUESTS; i++) {
+ NetworkCallback networkCallback = new NetworkCallback();
+ mCm.registerDefaultNetworkCallback(networkCallback);
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
+ waitForIdle();
+
+ withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
+ for (int i = 0; i < MAX_REQUESTS; i++) {
+ NetworkCallback networkCallback = new NetworkCallback();
+ mCm.registerDefaultNetworkCallbackAsUid(1000000 + i, networkCallback,
+ new Handler(ConnectivityThread.getInstanceLooper()));
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
+ });
+ waitForIdle();
+
+ for (int i = 0; i < MAX_REQUESTS; i++) {
final PendingIntent pendingIntent = PendingIntent.getBroadcast(
mContext, 0 /* requestCode */, new Intent("e" + i), FLAG_IMMUTABLE);
mCm.requestNetwork(networkRequest, pendingIntent);
@@ -6551,8 +6734,7 @@
@Test
public void testVpnNetworkActive() throws Exception {
// NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback.
- mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
- PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
final int uid = Process.myUid();
@@ -7044,8 +7226,7 @@
@Test
public void testRestrictedProfileAffectsVpnUidRanges() throws Exception {
// NETWORK_SETTINGS is necessary to see the UID ranges in NetworkCapabilities.
- mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
- PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
final NetworkRequest request = new NetworkRequest.Builder()
.removeCapability(NET_CAPABILITY_NOT_VPN)
@@ -7131,8 +7312,7 @@
mServiceContext.setPermission(
Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
// Necessary to see the UID ranges in NetworkCapabilities.
- mServiceContext.setPermission(
- Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
final NetworkRequest request = new NetworkRequest.Builder()
.removeCapability(NET_CAPABILITY_NOT_VPN)
@@ -7620,8 +7800,7 @@
Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
mServiceContext.setPermission(
Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
- mServiceContext.setPermission(
- Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
final TestNetworkCallback callback = new TestNetworkCallback();
final NetworkRequest request = new NetworkRequest.Builder()
@@ -7857,8 +8036,7 @@
mServiceContext.setPermission(
Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
// For LockdownVpnTracker to call registerSystemDefaultNetworkCallback.
- mServiceContext.setPermission(
- Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
final TestNetworkCallback callback = new TestNetworkCallback();
@@ -8988,8 +9166,7 @@
private void denyAllLocationPrivilegedPermissions() {
mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
PERMISSION_DENIED);
- mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
- PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
mServiceContext.setPermission(Manifest.permission.NETWORK_STACK,
PERMISSION_DENIED);
mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
@@ -9245,7 +9422,7 @@
@Test
public void testCreateForCallerWithLocalMacAddressSanitizedWithSettingsPermission()
throws Exception {
- mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
final TransportInfo transportInfo = mock(TransportInfo.class);
when(transportInfo.getApplicableRedactions())
@@ -10641,8 +10818,7 @@
private void registerDefaultNetworkCallbacks() {
// Using Manifest.permission.NETWORK_SETTINGS for registerSystemDefaultNetworkCallback()
- mServiceContext.setPermission(
- Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
mSystemDefaultNetworkCallback = new TestNetworkCallback();
mDefaultNetworkCallback = new TestNetworkCallback();
mProfileDefaultNetworkCallback = new TestNetworkCallback();
@@ -10652,8 +10828,7 @@
registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback,
TEST_WORK_PROFILE_APP_UID);
// TODO: test using ConnectivityManager#registerDefaultNetworkCallbackAsUid as well.
- mServiceContext.setPermission(
- Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
}
private void unregisterDefaultNetworkCallbacks() {
@@ -10808,7 +10983,7 @@
defaultNetworkCallback.assertNoCallback();
final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
- withPermission(Manifest.permission.NETWORK_SETTINGS, () ->
+ withPermission(NETWORK_SETTINGS, () ->
mCm.registerDefaultNetworkCallbackAsUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
new Handler(ConnectivityThread.getInstanceLooper())));
@@ -10856,7 +11031,7 @@
defaultNetworkCallback.assertNoCallback();
final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
- withPermission(Manifest.permission.NETWORK_SETTINGS, () ->
+ withPermission(NETWORK_SETTINGS, () ->
mCm.registerDefaultNetworkCallbackAsUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
new Handler(ConnectivityThread.getInstanceLooper())));
@@ -10898,7 +11073,7 @@
defaultNetworkCallback.assertNoCallback();
final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
- withPermission(Manifest.permission.NETWORK_SETTINGS, () ->
+ withPermission(NETWORK_SETTINGS, () ->
mCm.registerDefaultNetworkCallbackAsUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
new Handler(ConnectivityThread.getInstanceLooper())));
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 9334e2c..eeeb4fb 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -89,6 +89,7 @@
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.UnderlyingNetworkInfo;
+import android.net.TelephonyNetworkSpecifier;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.os.ConditionVariable;
import android.os.Handler;
@@ -1280,6 +1281,77 @@
}
@Test
+ public void testDualVilteProviderStats() throws Exception {
+ // Pretend that network comes online.
+ expectDefaultSettings();
+ final int subId1 = 1;
+ final int subId2 = 2;
+ final NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{
+ buildImsState(IMSI_1, subId1, TEST_IFACE),
+ buildImsState(IMSI_2, subId2, TEST_IFACE2)};
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
+
+ // Register custom provider and retrieve callback.
+ final TestableNetworkStatsProviderBinder provider =
+ new TestableNetworkStatsProviderBinder();
+ final INetworkStatsProviderCallback cb =
+ mService.registerNetworkStatsProvider("TEST", provider);
+ assertNotNull(cb);
+
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
+
+ // Verifies that one requestStatsUpdate will be called during iface update.
+ provider.expectOnRequestStatsUpdate(0 /* unused */);
+
+ // Create some initial traffic and report to the service.
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ final String vtIface1 = NetworkStats.IFACE_VT + subId1;
+ final String vtIface2 = NetworkStats.IFACE_VT + subId2;
+ final NetworkStats expectedStats = new NetworkStats(0L, 1)
+ .addEntry(new NetworkStats.Entry(vtIface1, UID_RED, SET_DEFAULT,
+ TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
+ 128L, 2L, 128L, 2L, 1L))
+ .addEntry(new NetworkStats.Entry(vtIface2, UID_RED, SET_DEFAULT,
+ TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
+ 64L, 1L, 64L, 1L, 1L));
+ cb.notifyStatsUpdated(0 /* unused */, expectedStats, expectedStats);
+
+ // Make another empty mutable stats object. This is necessary since the new NetworkStats
+ // object will be used to compare with the old one in NetworkStatsRecoder, two of them
+ // cannot be the same object.
+ expectNetworkStatsUidDetail(buildEmptyStats());
+
+ forcePollAndWaitForIdle();
+
+ // Verifies that one requestStatsUpdate and setAlert will be called during polling.
+ provider.expectOnRequestStatsUpdate(0 /* unused */);
+ provider.expectOnSetAlert(MB_IN_BYTES);
+
+ // Verifies that service recorded history, does not verify uid tag part.
+ assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 1);
+
+ // Verifies that onStatsUpdated updates the stats accordingly.
+ NetworkStats stats = mSession.getSummaryForAllUid(
+ sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true);
+ assertEquals(1, stats.size());
+ assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 1L);
+
+ stats = mSession.getSummaryForAllUid(
+ sTemplateImsi2, Long.MIN_VALUE, Long.MAX_VALUE, true);
+ assertEquals(1, stats.size());
+ assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1L);
+
+ // Verifies that unregister the callback will remove the provider from service.
+ cb.unregister();
+ forcePollAndWaitForIdle();
+ provider.assertNoCallback();
+ }
+
+ @Test
public void testStatsProviderSetAlert() throws Exception {
// Pretend that network comes online.
expectDefaultSettings();
@@ -1616,6 +1688,20 @@
TYPE_MOBILE);
}
+ private static NetworkStateSnapshot buildImsState(
+ String subscriberId, int subId, String ifaceName) {
+ final LinkProperties prop = new LinkProperties();
+ prop.setInterfaceName(ifaceName);
+ final NetworkCapabilities capabilities = new NetworkCapabilities();
+ capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, true);
+ capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
+ capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_IMS, true);
+ capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ capabilities.setNetworkSpecifier(new TelephonyNetworkSpecifier(subId));
+ return new NetworkStateSnapshot(
+ MOBILE_NETWORK, capabilities, prop, subscriberId, TYPE_MOBILE);
+ }
+
private long getElapsedRealtime() {
return mElapsedRealtime;
}
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 82da249..77c0872 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -256,53 +256,35 @@
void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& options,
Printer* printer) {
- for (const auto& package : table.packages) {
- ValueHeadlinePrinter headline_printer(package->name, printer);
- ValueBodyPrinter body_printer(package->name, printer);
+ const auto table_view = table.GetPartitionedView();
+ for (const auto& package : table_view.packages) {
+ ValueHeadlinePrinter headline_printer(package.name, printer);
+ ValueBodyPrinter body_printer(package.name, printer);
printer->Print("Package name=");
- printer->Print(package->name);
- if (package->id) {
- printer->Print(StringPrintf(" id=%02x", package->id.value()));
+ printer->Print(package.name);
+ if (package.id) {
+ printer->Print(StringPrintf(" id=%02x", package.id.value()));
}
printer->Println();
printer->Indent();
- for (const auto& type : package->types) {
+ for (const auto& type : package.types) {
printer->Print("type ");
- printer->Print(to_string(type->type));
- if (type->id) {
- printer->Print(StringPrintf(" id=%02x", type->id.value()));
+ printer->Print(to_string(type.type));
+ if (type.id) {
+ printer->Print(StringPrintf(" id=%02x", type.id.value()));
}
- printer->Println(StringPrintf(" entryCount=%zd", type->entries.size()));
-
- std::vector<const ResourceEntry*> sorted_entries;
- for (const auto& entry : type->entries) {
- auto iter = std::lower_bound(
- sorted_entries.begin(), sorted_entries.end(), entry.get(),
- [](const ResourceEntry* a, const ResourceEntry* b) -> bool {
- if (a->id && b->id) {
- return a->id.value() < b->id.value();
- } else if (a->id) {
- return true;
- } else {
- return false;
- }
- });
- sorted_entries.insert(iter, entry.get());
- }
+ printer->Println(StringPrintf(" entryCount=%zd", type.entries.size()));
printer->Indent();
- for (const ResourceEntry* entry : sorted_entries) {
- const ResourceId id(package->id.value_or_default(0), type->id.value_or_default(0),
- entry->id.value_or_default(0));
-
+ for (const ResourceEntry* entry : type.entries) {
printer->Print("resource ");
- printer->Print(id.to_string());
+ printer->Print(entry->id.value_or_default(0).to_string());
printer->Print(" ");
// Write the name without the package (this is obvious and too verbose).
- printer->Print(to_string(type->type));
+ printer->Print(to_string(type.type));
printer->Print("/");
printer->Print(entry->name);
@@ -318,6 +300,10 @@
break;
}
+ if (entry->visibility.staged_api) {
+ printer->Print(" STAGED");
+ }
+
if (entry->overlayable_item) {
printer->Print(" OVERLAYABLE");
}
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index e930b47..830bc5f 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -113,7 +113,7 @@
}
std::string error;
- table = util::make_unique<ResourceTable>(/** validate_resources **/ false);
+ table = util::make_unique<ResourceTable>(ResourceTable::Validation::kDisabled);
if (!DeserializeTableFromPb(pb_table, collection.get(), table.get(), &error)) {
diag->Error(DiagMessage(source)
<< "failed to deserialize " << kProtoResourceTablePath << ": " << error);
@@ -157,7 +157,7 @@
io::IFile* table_file = collection->FindFile(kApkResourceTablePath);
if (table_file != nullptr) {
- table = util::make_unique<ResourceTable>(/** validate_resources **/ false);
+ table = util::make_unique<ResourceTable>(ResourceTable::Validation::kDisabled);
std::unique_ptr<io::IData> data = table_file->OpenAsData();
if (data == nullptr) {
diag->Error(DiagMessage(source) << "failed to open " << kApkResourceTablePath);
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 8fe0eb3..cf93870 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -138,7 +138,7 @@
uint32_t id;
ResourceId();
- ResourceId(const ResourceId& rhs);
+ ResourceId(const ResourceId& rhs) = default;
ResourceId(uint32_t res_id); // NOLINT(google-explicit-constructor)
ResourceId(uint8_t p, uint8_t t, uint16_t e);
@@ -222,8 +222,6 @@
inline ResourceId::ResourceId() : id(0) {}
-inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {}
-
inline ResourceId::ResourceId(uint32_t res_id) : id(res_id) {}
inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e)
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 3d9be59..24c60b7 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -42,6 +42,10 @@
using android::idmap2::policy::kPolicyStringToFlag;
namespace aapt {
+namespace {
+constexpr const char* kPublicGroupTag = "public-group";
+constexpr const char* kStagingPublicGroupTag = "staging-public-group";
+} // namespace
constexpr const char* sXliffNamespaceUri = "urn:oasis:names:tc:xliff:document:1.2";
@@ -102,6 +106,7 @@
ResourceId id;
Visibility::Level visibility_level = Visibility::Level::kUndefined;
+ bool staged_api = false;
bool allow_new = false;
Maybe<OverlayableItem> overlayable_item;
@@ -118,43 +123,44 @@
res->comment = trimmed_comment.to_string();
}
+ NewResourceBuilder res_builder(res->name);
if (res->visibility_level != Visibility::Level::kUndefined) {
Visibility visibility;
visibility.level = res->visibility_level;
+ visibility.staged_api = res->staged_api;
visibility.source = res->source;
visibility.comment = res->comment;
- if (!table->SetVisibilityWithId(res->name, visibility, res->id, diag)) {
- return false;
- }
+ res_builder.SetVisibility(visibility);
+ }
+
+ if (res->id.is_valid()) {
+ res_builder.SetId(res->id);
}
if (res->allow_new) {
AllowNew allow_new;
allow_new.source = res->source;
allow_new.comment = res->comment;
- if (!table->SetAllowNew(res->name, allow_new, diag)) {
- return false;
- }
+ res_builder.SetAllowNew(allow_new);
}
if (res->overlayable_item) {
- if (!table->SetOverlayable(res->name, res->overlayable_item.value(), diag)) {
- return false;
- }
+ res_builder.SetOverlayable(res->overlayable_item.value());
}
if (res->value != nullptr) {
// Attach the comment, source and config to the value.
res->value->SetComment(std::move(res->comment));
res->value->SetSource(std::move(res->source));
-
- if (!table->AddResourceWithId(res->name, res->id, res->config, res->product,
- std::move(res->value), diag)) {
- return false;
- }
+ res_builder.SetValue(std::move(res->value), res->config, res->product);
}
bool error = false;
+ if (!res->name.entry.empty()) {
+ if (!table->AddResource(res_builder.Build(), diag)) {
+ return false;
+ }
+ }
for (ParsedResource& child : res->child_resources) {
error |= !AddResourcesToTable(table, diag, &child);
}
@@ -525,6 +531,7 @@
{"plurals", std::mem_fn(&ResourceParser::ParsePlural)},
{"public", std::mem_fn(&ResourceParser::ParsePublic)},
{"public-group", std::mem_fn(&ResourceParser::ParsePublicGroup)},
+ {"staging-public-group", std::mem_fn(&ResourceParser::ParseStagingPublicGroup)},
{"string-array", std::mem_fn(&ResourceParser::ParseStringArray)},
{"style", std::bind(&ResourceParser::ParseStyle, std::placeholders::_1, ResourceType::kStyle,
std::placeholders::_2, std::placeholders::_3)},
@@ -653,7 +660,8 @@
const auto bag_iter = elToBagMap.find(resource_type);
if (bag_iter != elToBagMap.end()) {
// Ensure we have a name (unless this is a <public-group> or <overlayable>).
- if (resource_type != "public-group" && resource_type != "overlayable") {
+ if (resource_type != kPublicGroupTag && resource_type != kStagingPublicGroupTag &&
+ resource_type != "overlayable") {
if (!maybe_name) {
diag_->Error(DiagMessage(out_resource->source)
<< "<" << parser->element_name() << "> missing 'name' attribute");
@@ -751,7 +759,7 @@
// table.
std::unique_ptr<Id> id = util::make_unique<Id>();
id->SetSource(source_.WithLine(begin_xml_line));
- table_->AddResource(name, {}, {}, std::move(id), diag_);
+ table_->AddResource(NewResourceBuilder(name).SetValue(std::move(id)).Build(), diag_);
};
// Process the raw value.
@@ -890,54 +898,45 @@
return true;
}
-bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource) {
- if (options_.visibility) {
- diag_->Error(DiagMessage(out_resource->source)
- << "<public-group> tag not allowed with --visibility flag");
- return false;
- }
-
+template <typename Func>
+bool static ParseGroupImpl(xml::XmlPullParser* parser, ParsedResource* out_resource,
+ const char* tag_name, IDiagnostics* diag, Func&& func) {
if (out_resource->config != ConfigDescription::DefaultConfig()) {
- diag_->Warn(DiagMessage(out_resource->source)
- << "ignoring configuration '" << out_resource->config
- << "' for <public-group> tag");
+ diag->Warn(DiagMessage(out_resource->source)
+ << "ignoring configuration '" << out_resource->config << "' for <" << tag_name
+ << "> tag");
}
Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type");
if (!maybe_type) {
- diag_->Error(DiagMessage(out_resource->source)
- << "<public-group> must have a 'type' attribute");
+ diag->Error(DiagMessage(out_resource->source)
+ << "<" << tag_name << "> must have a 'type' attribute");
return false;
}
const ResourceType* parsed_type = ParseResourceType(maybe_type.value());
if (!parsed_type) {
- diag_->Error(DiagMessage(out_resource->source) << "invalid resource type '"
- << maybe_type.value()
- << "' in <public-group>");
+ diag->Error(DiagMessage(out_resource->source)
+ << "invalid resource type '" << maybe_type.value() << "' in <" << tag_name << ">");
return false;
}
- Maybe<StringPiece> maybe_id_str =
- xml::FindNonEmptyAttribute(parser, "first-id");
+ Maybe<StringPiece> maybe_id_str = xml::FindNonEmptyAttribute(parser, "first-id");
if (!maybe_id_str) {
- diag_->Error(DiagMessage(out_resource->source)
- << "<public-group> must have a 'first-id' attribute");
+ diag->Error(DiagMessage(out_resource->source)
+ << "<" << tag_name << "> must have a 'first-id' attribute");
return false;
}
- Maybe<ResourceId> maybe_id =
- ResourceUtils::ParseResourceId(maybe_id_str.value());
+ Maybe<ResourceId> maybe_id = ResourceUtils::ParseResourceId(maybe_id_str.value());
if (!maybe_id) {
- diag_->Error(DiagMessage(out_resource->source) << "invalid resource ID '"
- << maybe_id_str.value()
- << "' in <public-group>");
+ diag->Error(DiagMessage(out_resource->source)
+ << "invalid resource ID '" << maybe_id_str.value() << "' in <" << tag_name << ">");
return false;
}
- ResourceId next_id = maybe_id.value();
-
std::string comment;
+ ResourceId next_id = maybe_id.value();
bool error = false;
const size_t depth = parser->depth();
while (xml::XmlPullParser::NextChildNode(parser, depth)) {
@@ -949,53 +948,72 @@
continue;
}
- const Source item_source = source_.WithLine(parser->line_number());
+ const Source item_source = out_resource->source.WithLine(parser->line_number());
const std::string& element_namespace = parser->element_namespace();
const std::string& element_name = parser->element_name();
if (element_namespace.empty() && element_name == "public") {
- Maybe<StringPiece> maybe_name =
- xml::FindNonEmptyAttribute(parser, "name");
+ auto maybe_name = xml::FindNonEmptyAttribute(parser, "name");
if (!maybe_name) {
- diag_->Error(DiagMessage(item_source)
- << "<public> must have a 'name' attribute");
+ diag->Error(DiagMessage(item_source) << "<public> must have a 'name' attribute");
error = true;
continue;
}
if (xml::FindNonEmptyAttribute(parser, "id")) {
- diag_->Error(DiagMessage(item_source)
- << "'id' is ignored within <public-group>");
+ diag->Error(DiagMessage(item_source) << "'id' is ignored within <" << tag_name << ">");
error = true;
continue;
}
if (xml::FindNonEmptyAttribute(parser, "type")) {
- diag_->Error(DiagMessage(item_source)
- << "'type' is ignored within <public-group>");
+ diag->Error(DiagMessage(item_source) << "'type' is ignored within <" << tag_name << ">");
error = true;
continue;
}
- ParsedResource child_resource;
- child_resource.name.type = *parsed_type;
- child_resource.name.entry = maybe_name.value().to_string();
- child_resource.id = next_id;
- // NOLINTNEXTLINE(bugprone-use-after-move) move+reset comment
- child_resource.comment = std::move(comment);
- child_resource.source = item_source;
- child_resource.visibility_level = Visibility::Level::kPublic;
- out_resource->child_resources.push_back(std::move(child_resource));
+ ParsedResource& entry_res = out_resource->child_resources.emplace_back(ParsedResource{
+ .name = ResourceName{{}, *parsed_type, maybe_name.value().to_string()},
+ .source = item_source,
+ .id = next_id,
+ .comment = std::move(comment),
+ });
- next_id.id += 1;
+ // Execute group specific code.
+ func(entry_res, next_id);
+ next_id.id++;
} else if (!ShouldIgnoreElement(element_namespace, element_name)) {
- diag_->Error(DiagMessage(item_source) << ":" << element_name << ">");
+ diag->Error(DiagMessage(item_source) << ":" << element_name << ">");
error = true;
}
}
return !error;
}
+bool ResourceParser::ParseStagingPublicGroup(xml::XmlPullParser* parser,
+ ParsedResource* out_resource) {
+ return ParseGroupImpl(parser, out_resource, kStagingPublicGroupTag, diag_,
+ [](ParsedResource& parsed_entry, ResourceId id) {
+ parsed_entry.id = id;
+ parsed_entry.staged_api = true;
+ parsed_entry.visibility_level = Visibility::Level::kPublic;
+ });
+}
+
+bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource) {
+ if (options_.visibility) {
+ diag_->Error(DiagMessage(out_resource->source)
+ << "<" << kPublicGroupTag << "> tag not allowed with --visibility flag");
+ return false;
+ }
+
+ return ParseGroupImpl(parser, out_resource, kPublicGroupTag, diag_,
+ [](ParsedResource& parsed_entry, ResourceId id) {
+ parsed_entry.id = id;
+ parsed_entry.visibility_level = Visibility::Level::kPublic;
+ });
+}
+
bool ResourceParser::ParseSymbolImpl(xml::XmlPullParser* parser,
ParsedResource* out_resource) {
Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type");
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index 9d3ecc8..af0db8c 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -99,6 +99,7 @@
bool ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource);
bool ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource);
+ bool ParseStagingPublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource);
bool ParseSymbolImpl(xml::XmlPullParser* parser, ParsedResource* out_resource);
bool ParseSymbol(xml::XmlPullParser* parser, ParsedResource* out_resource);
bool ParseOverlayable(xml::XmlPullParser* parser, ParsedResource* out_resource);
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 9b70079..4a509be 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -831,25 +831,38 @@
Maybe<ResourceTable::SearchResult> result = table_.FindResource(test::ParseNameOrDie("attr/foo"));
ASSERT_TRUE(result);
-
- ASSERT_TRUE(result.value().package->id);
- ASSERT_TRUE(result.value().type->id);
ASSERT_TRUE(result.value().entry->id);
- ResourceId actual_id(result.value().package->id.value(),
- result.value().type->id.value(),
- result.value().entry->id.value());
- EXPECT_THAT(actual_id, Eq(ResourceId(0x01010040)));
+ EXPECT_THAT(result.value().entry->id.value(), Eq(ResourceId(0x01010040)));
+
+ result = table_.FindResource(test::ParseNameOrDie("attr/bar"));
+ ASSERT_TRUE(result);
+ ASSERT_TRUE(result.value().entry->id);
+ EXPECT_THAT(result.value().entry->id.value(), Eq(ResourceId(0x01010041)));
+}
+
+TEST_F(ResourceParserTest, StagingPublicGroup) {
+ std::string input = R"(
+ <staging-public-group type="attr" first-id="0x01ff0049">
+ <public name="foo" />
+ <public name="bar" />
+ </staging-public-group>)";
+ ASSERT_TRUE(TestParse(input));
+
+ Maybe<ResourceTable::SearchResult> result = table_.FindResource(test::ParseNameOrDie("attr/foo"));
+ ASSERT_TRUE(result);
+
+ ASSERT_TRUE(result.value().entry->id);
+ EXPECT_THAT(result.value().entry->id.value(), Eq(ResourceId(0x01ff0049)));
+ EXPECT_THAT(result.value().entry->visibility.level, Eq(Visibility::Level::kPublic));
+ EXPECT_TRUE(result.value().entry->visibility.staged_api);
result = table_.FindResource(test::ParseNameOrDie("attr/bar"));
ASSERT_TRUE(result);
- ASSERT_TRUE(result.value().package->id);
- ASSERT_TRUE(result.value().type->id);
ASSERT_TRUE(result.value().entry->id);
- actual_id = ResourceId(result.value().package->id.value(),
- result.value().type->id.value(),
- result.value().entry->id.value());
- EXPECT_THAT(actual_id, Eq(ResourceId(0x01010041)));
+ EXPECT_THAT(result.value().entry->id.value(), Eq(ResourceId(0x01ff004a)));
+ EXPECT_THAT(result.value().entry->visibility.level, Eq(Visibility::Level::kPublic));
+ EXPECT_TRUE(result.value().entry->visibility.staged_api);
}
TEST_F(ResourceParserTest, StrongestSymbolVisibilityWins) {
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index e0a9a31e..27f7bdd 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -18,20 +18,18 @@
#include <algorithm>
#include <memory>
-#include <string>
#include <tuple>
#include "android-base/logging.h"
-#include "android-base/stringprintf.h"
#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"
-#include "Debug.h"
#include "NameMangler.h"
+#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"
-#include "trace/TraceBuffer.h"
#include "text/Unicode.h"
+#include "trace/TraceBuffer.h"
#include "util/Util.h"
using ::aapt::text::IsValidResourceEntryName;
@@ -43,135 +41,97 @@
const char* Overlayable::kActorScheme = "overlay";
-static bool less_than_type_and_id(const std::unique_ptr<ResourceTableType>& lhs,
- const std::pair<ResourceType, Maybe<uint8_t>>& rhs) {
- return lhs->type < rhs.first || (lhs->type == rhs.first && rhs.second && lhs->id < rhs.second);
+namespace {
+bool less_than_type(const std::unique_ptr<ResourceTableType>& lhs, ResourceType rhs) {
+ return lhs->type < rhs;
}
template <typename T>
-static bool less_than_struct_with_name(const std::unique_ptr<T>& lhs, const StringPiece& rhs) {
+bool less_than_struct_with_name(const std::unique_ptr<T>& lhs, const StringPiece& rhs) {
return lhs->name.compare(0, lhs->name.size(), rhs.data(), rhs.size()) < 0;
}
template <typename T>
-static bool less_than_struct_with_name_and_id(const std::unique_ptr<T>& lhs,
- const std::pair<StringPiece, Maybe<uint16_t>>& rhs) {
- int name_cmp = lhs->name.compare(0, lhs->name.size(), rhs.first.data(), rhs.first.size());
- return name_cmp < 0 || (name_cmp == 0 && rhs.second && lhs->id < rhs.second);
+bool greater_than_struct_with_name(const StringPiece& lhs, const std::unique_ptr<T>& rhs) {
+ return rhs->name.compare(0, rhs->name.size(), lhs.data(), lhs.size()) > 0;
}
-ResourceTablePackage* ResourceTable::FindPackage(const StringPiece& name) const {
- const auto last = packages.end();
- auto iter = std::lower_bound(packages.begin(), last, name,
- less_than_struct_with_name<ResourceTablePackage>);
- if (iter != last && name == (*iter)->name) {
- return iter->get();
+template <typename T>
+struct NameEqualRange {
+ bool operator()(const std::unique_ptr<T>& lhs, const StringPiece& rhs) const {
+ return less_than_struct_with_name<T>(lhs, rhs);
}
- return nullptr;
+ bool operator()(const StringPiece& lhs, const std::unique_ptr<T>& rhs) const {
+ return greater_than_struct_with_name<T>(lhs, rhs);
+ }
+};
+
+template <typename T, typename U>
+bool less_than_struct_with_name_and_id(const T& lhs,
+ const std::pair<std::string_view, Maybe<U>>& rhs) {
+ if (lhs.id != rhs.second) {
+ return lhs.id < rhs.second;
+ }
+ return lhs.name.compare(0, lhs.name.size(), rhs.first.data(), rhs.first.size()) < 0;
}
-ResourceTablePackage* ResourceTable::FindPackageById(uint8_t id) const {
- for (auto& package : packages) {
- if (package->id && package->id.value() == id) {
- return package.get();
- }
- }
- return nullptr;
+template <typename T, typename Func, typename Elements>
+T* FindElementsRunAction(const android::StringPiece& name, Elements& entries, Func action) {
+ const auto iter =
+ std::lower_bound(entries.begin(), entries.end(), name, less_than_struct_with_name<T>);
+ const bool found = iter != entries.end() && name == (*iter)->name;
+ return action(found, iter);
}
-ResourceTablePackage* ResourceTable::CreatePackage(const StringPiece& name, Maybe<uint8_t> id) {
- TRACE_CALL();
- ResourceTablePackage* package = FindOrCreatePackage(name);
- if (id && !package->id) {
- package->id = id;
- return package;
- }
+} // namespace
- if (id && package->id && package->id.value() != id.value()) {
- return nullptr;
- }
- return package;
+ResourceTable::ResourceTable(ResourceTable::Validation validation) : validation_(validation) {
}
-ResourceTablePackage* ResourceTable::CreatePackageAllowingDuplicateNames(const StringPiece& name,
- const Maybe<uint8_t> id) {
- const auto last = packages.end();
- auto iter = std::lower_bound(packages.begin(), last, std::make_pair(name, id),
- less_than_struct_with_name_and_id<ResourceTablePackage>);
-
- if (iter != last && name == (*iter)->name && id == (*iter)->id) {
- return iter->get();
- }
-
- std::unique_ptr<ResourceTablePackage> new_package = util::make_unique<ResourceTablePackage>();
- new_package->name = name.to_string();
- new_package->id = id;
- return packages.emplace(iter, std::move(new_package))->get();
+ResourceTablePackage* ResourceTable::FindPackage(const android::StringPiece& name) const {
+ return FindElementsRunAction<ResourceTablePackage>(
+ name, packages, [&](bool found, auto& iter) { return found ? iter->get() : nullptr; });
}
-ResourceTablePackage* ResourceTable::FindOrCreatePackage(const StringPiece& name) {
- const auto last = packages.end();
- auto iter = std::lower_bound(packages.begin(), last, name,
- less_than_struct_with_name<ResourceTablePackage>);
- if (iter != last && name == (*iter)->name) {
- return iter->get();
- }
-
- std::unique_ptr<ResourceTablePackage> new_package = util::make_unique<ResourceTablePackage>();
- new_package->name = name.to_string();
- return packages.emplace(iter, std::move(new_package))->get();
+ResourceTablePackage* ResourceTable::FindOrCreatePackage(const android::StringPiece& name) {
+ return FindElementsRunAction<ResourceTablePackage>(name, packages, [&](bool found, auto& iter) {
+ return found ? iter->get() : packages.emplace(iter, new ResourceTablePackage(name))->get();
+ });
}
-ResourceTableType* ResourceTablePackage::FindType(ResourceType type, const Maybe<uint8_t> id) {
- const auto last = types.end();
- auto iter = std::lower_bound(types.begin(), last, std::make_pair(type, id),
- less_than_type_and_id);
- if (iter != last && (*iter)->type == type && (!id || id == (*iter)->id)) {
- return iter->get();
- }
- return nullptr;
+template <typename Func, typename Elements>
+static ResourceTableType* FindTypeRunAction(ResourceType type, Elements& entries, Func action) {
+ const auto iter = std::lower_bound(entries.begin(), entries.end(), type, less_than_type);
+ const bool found = iter != entries.end() && type == (*iter)->type;
+ return action(found, iter);
}
-ResourceTableType* ResourceTablePackage::FindOrCreateType(ResourceType type,
- const Maybe<uint8_t> id) {
- const auto last = types.end();
- auto iter = std::lower_bound(types.begin(), last, std::make_pair(type, id),
- less_than_type_and_id);
- if (iter != last && (*iter)->type == type && (!id || id == (*iter)->id)) {
- return iter->get();
- }
-
- auto new_type = new ResourceTableType(type);
- new_type->id = id;
- return types.emplace(iter, std::move(new_type))->get();
+ResourceTableType* ResourceTablePackage::FindType(ResourceType type) const {
+ return FindTypeRunAction(type, types,
+ [&](bool found, auto& iter) { return found ? iter->get() : nullptr; });
}
-ResourceEntry* ResourceTableType::FindEntry(const StringPiece& name, const Maybe<uint16_t> id) {
- const auto last = entries.end();
- auto iter = std::lower_bound(entries.begin(), last, std::make_pair(name, id),
- less_than_struct_with_name_and_id<ResourceEntry>);
- if (iter != last && name == (*iter)->name && (!id || id == (*iter)->id)) {
- return iter->get();
- }
- return nullptr;
+ResourceTableType* ResourceTablePackage::FindOrCreateType(ResourceType type) {
+ return FindTypeRunAction(type, types, [&](bool found, auto& iter) {
+ return found ? iter->get() : types.emplace(iter, new ResourceTableType(type))->get();
+ });
}
-ResourceEntry* ResourceTableType::FindOrCreateEntry(const StringPiece& name,
- const Maybe<uint16_t > id) {
- auto last = entries.end();
- auto iter = std::lower_bound(entries.begin(), last, std::make_pair(name, id),
- less_than_struct_with_name_and_id<ResourceEntry>);
- if (iter != last && name == (*iter)->name && (!id || id == (*iter)->id)) {
- return iter->get();
- }
-
- auto new_entry = new ResourceEntry(name);
- new_entry->id = id;
- return entries.emplace(iter, std::move(new_entry))->get();
+ResourceEntry* ResourceTableType::CreateEntry(const android::StringPiece& name) {
+ return FindElementsRunAction<ResourceEntry>(name, entries, [&](bool found, auto& iter) {
+ return entries.emplace(iter, new ResourceEntry(name))->get();
+ });
}
-ResourceConfigValue* ResourceEntry::FindValue(const ConfigDescription& config) {
- return FindValue(config, StringPiece());
+ResourceEntry* ResourceTableType::FindEntry(const android::StringPiece& name) const {
+ return FindElementsRunAction<ResourceEntry>(
+ name, entries, [&](bool found, auto& iter) { return found ? iter->get() : nullptr; });
+}
+
+ResourceEntry* ResourceTableType::FindOrCreateEntry(const android::StringPiece& name) {
+ return FindElementsRunAction<ResourceEntry>(name, entries, [&](bool found, auto& iter) {
+ return found ? iter->get() : entries.emplace(iter, new ResourceEntry(name))->get();
+ });
}
struct ConfigKey {
@@ -188,7 +148,20 @@
}
ResourceConfigValue* ResourceEntry::FindValue(const ConfigDescription& config,
- const StringPiece& product) {
+ android::StringPiece product) {
+ auto iter = std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product},
+ lt_config_key_ref);
+ if (iter != values.end()) {
+ ResourceConfigValue* value = iter->get();
+ if (value->config == config && StringPiece(value->product) == product) {
+ return value;
+ }
+ }
+ return nullptr;
+}
+
+const ResourceConfigValue* ResourceEntry::FindValue(const android::ConfigDescription& config,
+ android::StringPiece product) const {
auto iter = std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product},
lt_config_key_ref);
if (iter != values.end()) {
@@ -323,303 +296,242 @@
return CollisionResult::kConflict;
}
-ResourceTable::CollisionResult ResourceTable::IgnoreCollision(Value* /** existing **/,
- Value* /** incoming **/) {
- return CollisionResult::kKeepBoth;
-}
-
-static StringPiece ResourceNameValidator(const StringPiece& name) {
- if (!IsValidResourceEntryName(name)) {
- return name;
- }
- return {};
-}
-
-static StringPiece SkipNameValidator(const StringPiece& /*name*/) {
- return {};
-}
-
-bool ResourceTable::AddResource(const ResourceNameRef& name,
- const ConfigDescription& config,
- const StringPiece& product,
- std::unique_ptr<Value> value,
- IDiagnostics* diag) {
- return AddResourceImpl(name, ResourceId{}, config, product, std::move(value),
- (validate_resources_ ? ResourceNameValidator : SkipNameValidator),
- (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
-}
-
-bool ResourceTable::AddResourceWithId(const ResourceNameRef& name, const ResourceId& res_id,
- const ConfigDescription& config, const StringPiece& product,
- std::unique_ptr<Value> value, IDiagnostics* diag) {
- return AddResourceImpl(name, res_id, config, product, std::move(value),
- (validate_resources_ ? ResourceNameValidator : SkipNameValidator),
- (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
-}
-
-bool ResourceTable::AddResourceMangled(const ResourceNameRef& name, const ConfigDescription& config,
- const StringPiece& product, std::unique_ptr<Value> value,
- IDiagnostics* diag) {
- return AddResourceImpl(name, ResourceId{}, config, product, std::move(value), SkipNameValidator,
- (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
-}
-
-bool ResourceTable::AddResourceWithIdMangled(const ResourceNameRef& name, const ResourceId& id,
- const ConfigDescription& config,
- const StringPiece& product,
- std::unique_ptr<Value> value, IDiagnostics* diag) {
- return AddResourceImpl(name, id, config, product, std::move(value), SkipNameValidator,
- (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
-}
-
-bool ResourceTable::ValidateName(NameValidator name_validator, const ResourceNameRef& name,
- const Source& source, IDiagnostics* diag) {
- const StringPiece bad_char = name_validator(name.entry);
- if (!bad_char.empty()) {
- diag->Error(DiagMessage(source) << "resource '" << name << "' has invalid entry name '"
- << name.entry << "'. Invalid character '" << bad_char << "'");
- return false;
- }
- return true;
-}
-
-bool ResourceTable::AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
- const ConfigDescription& config, const StringPiece& product,
- std::unique_ptr<Value> value, NameValidator name_validator,
- const CollisionResolverFunc& conflict_resolver,
- IDiagnostics* diag) {
- CHECK(value != nullptr);
- CHECK(diag != nullptr);
-
- const Source& source = value->GetSource();
- if (!ValidateName(name_validator, name, source, diag)) {
- return false;
+template <typename T, typename Comparer>
+struct SortedVectorInserter : public Comparer {
+ std::pair<bool, typename std::vector<T>::iterator> LowerBound(std::vector<T>& el,
+ const T& value) {
+ auto it = std::lower_bound(el.begin(), el.end(), value, [&](auto& lhs, auto& rhs) {
+ return Comparer::operator()(lhs, rhs);
+ });
+ bool found =
+ it != el.end() && !Comparer::operator()(*it, value) && !Comparer::operator()(value, *it);
+ return std::make_pair(found, it);
}
- // Check for package names appearing twice with two different package ids
- ResourceTablePackage* package = FindOrCreatePackage(name.package);
- if (res_id.is_valid() && package->id && package->id.value() != res_id.package_id()) {
- diag->Error(DiagMessage(source)
- << "trying to add resource '" << name << "' with ID " << res_id
- << " but package '" << package->name << "' already has ID "
- << StringPrintf("%02x", package->id.value()));
- return false;
+ T* Insert(std::vector<T>& el, T&& value) {
+ auto [found, it] = LowerBound(el, value);
+ if (found) {
+ return &*it;
+ }
+ return &*el.insert(it, std::move(value));
}
+};
- // Whether or not to error on duplicate resources
- bool check_id = validate_resources_ && res_id.is_valid();
- // Whether or not to create a duplicate resource if the id does not match
- bool use_id = !validate_resources_ && res_id.is_valid();
-
- ResourceTableType* type = package->FindOrCreateType(name.type, use_id ? res_id.type_id()
- : Maybe<uint8_t>());
-
- // Check for types appearing twice with two different type ids
- if (check_id && type->id && type->id.value() != res_id.type_id()) {
- diag->Error(DiagMessage(source)
- << "trying to add resource '" << name << "' with ID " << res_id
- << " but type '" << type->type << "' already has ID "
- << StringPrintf("%02x", type->id.value()));
- return false;
+struct PackageViewComparer {
+ bool operator()(const ResourceTablePackageView& lhs, const ResourceTablePackageView& rhs) {
+ return less_than_struct_with_name_and_id<ResourceTablePackageView, uint8_t>(
+ lhs, std::make_pair(rhs.name, rhs.id));
}
+};
- ResourceEntry* entry = type->FindOrCreateEntry(name.entry, use_id ? res_id.entry_id()
- : Maybe<uint16_t>());
-
- // Check for entries appearing twice with two different entry ids
- if (check_id && entry->id && entry->id.value() != res_id.entry_id()) {
- diag->Error(DiagMessage(source)
- << "trying to add resource '" << name << "' with ID " << res_id
- << " but resource already has ID "
- << ResourceId(package->id.value(), type->id.value(), entry->id.value()));
- return false;
+struct TypeViewComparer {
+ bool operator()(const ResourceTableTypeView& lhs, const ResourceTableTypeView& rhs) {
+ return lhs.id != rhs.id ? lhs.id < rhs.id : lhs.type < rhs.type;
}
+};
- ResourceConfigValue* config_value = entry->FindOrCreateValue(config, product);
- if (!config_value->value) {
- // Resource does not exist, add it now.
- config_value->value = std::move(value);
- } else {
- switch (conflict_resolver(config_value->value.get(), value.get())) {
- case CollisionResult::kKeepBoth:
- // Insert the value ignoring for duplicate configurations
- entry->values.push_back(util::make_unique<ResourceConfigValue>(config, product));
- entry->values.back()->value = std::move(value);
- break;
+struct EntryViewComparer {
+ bool operator()(const ResourceEntry* lhs, const ResourceEntry* rhs) {
+ return less_than_struct_with_name_and_id<ResourceEntry, ResourceId>(
+ *lhs, std::make_pair(rhs->name, rhs->id));
+ }
+};
- case CollisionResult::kTakeNew:
- // Take the incoming value.
- config_value->value = std::move(value);
- break;
+ResourceTableView ResourceTable::GetPartitionedView() const {
+ ResourceTableView view;
+ SortedVectorInserter<ResourceTablePackageView, PackageViewComparer> package_inserter;
+ SortedVectorInserter<ResourceTableTypeView, TypeViewComparer> type_inserter;
+ SortedVectorInserter<const ResourceEntry*, EntryViewComparer> entry_inserter;
- case CollisionResult::kConflict:
- diag->Error(DiagMessage(source) << "duplicate value for resource '" << name << "' "
- << "with config '" << config << "'");
- diag->Error(DiagMessage(source) << "resource previously defined here");
- return false;
+ for (const auto& package : packages) {
+ for (const auto& type : package->types) {
+ for (const auto& entry : type->entries) {
+ ResourceTablePackageView new_package{
+ package->name, entry->id ? entry->id.value().package_id() : Maybe<uint8_t>{}};
+ auto view_package = package_inserter.Insert(view.packages, std::move(new_package));
- case CollisionResult::kKeepOriginal:
- break;
+ ResourceTableTypeView new_type{type->type,
+ entry->id ? entry->id.value().type_id() : Maybe<uint8_t>{}};
+ auto view_type = type_inserter.Insert(view_package->types, std::move(new_type));
+
+ if (entry->visibility.level == Visibility::Level::kPublic) {
+ // Only mark the type visibility level as public, it doesn't care about being private.
+ view_type->visibility_level = Visibility::Level::kPublic;
+ }
+
+ entry_inserter.Insert(view_type->entries, entry.get());
+ }
}
}
- if (res_id.is_valid()) {
- package->id = res_id.package_id();
- type->id = res_id.type_id();
- entry->id = res_id.entry_id();
+ // The android runtime does not support querying resources when the there are multiple type ids
+ // for the same resource type within the same package. For this reason, if there are types with
+ // multiple type ids, each type needs to exist in its own package in order to be queried by name.
+ std::vector<ResourceTablePackageView> new_packages;
+ for (auto& package : view.packages) {
+ // If a new package was already created for a different type within this package, then
+ // we can reuse those packages for other types that need to be extracted from this package.
+ // `start_index` is the index of the first newly created package that can be reused.
+ const size_t start_index = new_packages.size();
+ std::map<ResourceType, size_t> type_new_package_index;
+ for (auto type_it = package.types.begin(); type_it != package.types.end();) {
+ auto& type = *type_it;
+ auto type_index_iter = type_new_package_index.find(type.type);
+ if (type_index_iter == type_new_package_index.end()) {
+ // First occurrence of the resource type in this package. Keep it in this package.
+ type_new_package_index.insert(type_index_iter, std::make_pair(type.type, start_index));
+ ++type_it;
+ continue;
+ }
+
+ // The resource type has already been seen for this package, so this type must be extracted to
+ // a new separate package.
+ const size_t index = type_index_iter->second;
+ if (new_packages.size() == index) {
+ new_packages.emplace_back(ResourceTablePackageView{package.name, package.id});
+ type_new_package_index[type.type] = index + 1;
+ }
+
+ // Move the type into a new package
+ auto& other_package = new_packages[index];
+ type_inserter.Insert(other_package.types, std::move(type));
+ type_it = package.types.erase(type_it);
+ }
}
- return true;
-}
-
-bool ResourceTable::GetValidateResources() {
- return validate_resources_;
-}
-
-bool ResourceTable::SetVisibility(const ResourceNameRef& name, const Visibility& visibility,
- IDiagnostics* diag) {
- return SetVisibilityImpl(name, visibility, {}, ResourceNameValidator, diag);
-}
-
-bool ResourceTable::SetVisibilityWithId(const ResourceNameRef& name, const Visibility& visibility,
- const ResourceId& res_id, IDiagnostics* diag) {
- return SetVisibilityImpl(name, visibility, res_id, ResourceNameValidator, diag);
-}
-
-bool ResourceTable::SetVisibilityWithIdMangled(const ResourceNameRef& name,
- const Visibility& visibility,
- const ResourceId& res_id, IDiagnostics* diag) {
- return SetVisibilityImpl(name, visibility, res_id, SkipNameValidator, diag);
-}
-
-bool ResourceTable::SetVisibilityImpl(const ResourceNameRef& name, const Visibility& visibility,
- const ResourceId& res_id, NameValidator name_validator,
- IDiagnostics* diag) {
- CHECK(diag != nullptr);
-
- const Source& source = visibility.source;
- if (!ValidateName(name_validator, name, source, diag)) {
- return false;
+ for (auto& new_package : new_packages) {
+ // Insert newly created packages after their original packages
+ auto [_, it] = package_inserter.LowerBound(view.packages, new_package);
+ view.packages.insert(++it, std::move(new_package));
}
- // Check for package names appearing twice with two different package ids
- ResourceTablePackage* package = FindOrCreatePackage(name.package);
- if (res_id.is_valid() && package->id && package->id.value() != res_id.package_id()) {
+ return view;
+}
+
+bool ResourceTable::AddResource(NewResource&& res, IDiagnostics* diag) {
+ CHECK(diag != nullptr) << "Diagnostic pointer is null";
+
+ const bool validate = validation_ == Validation::kEnabled;
+ const Source source = res.value ? res.value->GetSource() : Source{};
+ if (validate && !res.allow_mangled && !IsValidResourceEntryName(res.name.entry)) {
diag->Error(DiagMessage(source)
- << "trying to add resource '" << name << "' with ID " << res_id
- << " but package '" << package->name << "' already has ID "
- << StringPrintf("%02x", package->id.value()));
+ << "resource '" << res.name << "' has invalid entry name '" << res.name.entry);
return false;
}
- // Whether or not to error on duplicate resources
- bool check_id = validate_resources_ && res_id.is_valid();
- // Whether or not to create a duplicate resource if the id does not match
- bool use_id = !validate_resources_ && res_id.is_valid();
-
- ResourceTableType* type = package->FindOrCreateType(name.type, use_id ? res_id.type_id()
- : Maybe<uint8_t>());
-
- // Check for types appearing twice with two different type ids
- if (check_id && type->id && type->id.value() != res_id.type_id()) {
- diag->Error(DiagMessage(source)
- << "trying to add resource '" << name << "' with ID " << res_id
- << " but type '" << type->type << "' already has ID "
- << StringPrintf("%02x", type->id.value()));
+ if (res.id.has_value() && !res.id->first.is_valid()) {
+ diag->Error(DiagMessage(source) << "trying to add resource '" << res.name << "' with ID "
+ << res.id->first << " but that ID is invalid");
return false;
}
- ResourceEntry* entry = type->FindOrCreateEntry(name.entry, use_id ? res_id.entry_id()
- : Maybe<uint16_t>());
+ auto package = FindOrCreatePackage(res.name.package);
+ auto type = package->FindOrCreateType(res.name.type);
+ auto entry_it = std::equal_range(type->entries.begin(), type->entries.end(), res.name.entry,
+ NameEqualRange<ResourceEntry>{});
+ const size_t entry_count = std::distance(entry_it.first, entry_it.second);
- // Check for entries appearing twice with two different entry ids
- if (check_id && entry->id && entry->id.value() != res_id.entry_id()) {
- diag->Error(DiagMessage(source)
- << "trying to add resource '" << name << "' with ID " << res_id
- << " but resource already has ID "
- << ResourceId(package->id.value(), type->id.value(), entry->id.value()));
- return false;
+ ResourceEntry* entry;
+ if (entry_count == 0) {
+ // Adding a new resource
+ entry = type->CreateEntry(res.name.entry);
+ } else if (entry_count == 1) {
+ // Assume that the existing resource is being modified
+ entry = entry_it.first->get();
+ } else {
+ // Multiple resources with the same name exist in the resource table. The only way to
+ // distinguish between them is using resource id since each resource should have a unique id.
+ CHECK(res.id.has_value()) << "ambiguous modification of resource entry '" << res.name
+ << "' without specifying a resource id.";
+ entry = entry_it.first->get();
+ for (auto it = entry_it.first; it != entry_it.second; ++it) {
+ CHECK((bool)(*it)->id) << "ambiguous modification of resource entry '" << res.name
+ << "' with multiple entries without resource ids";
+ if ((*it)->id == res.id->first) {
+ entry = it->get();
+ break;
+ }
+ }
}
- if (res_id.is_valid()) {
- package->id = res_id.package_id();
- type->id = res_id.type_id();
- entry->id = res_id.entry_id();
+ if (res.id.has_value()) {
+ if (entry->id && entry->id.value() != res.id->first) {
+ if (res.id->second != OnIdConflict::CREATE_ENTRY) {
+ diag->Error(DiagMessage(source)
+ << "trying to add resource '" << res.name << "' with ID " << res.id->first
+ << " but resource already has ID " << entry->id.value());
+ return false;
+ }
+ entry = type->CreateEntry(res.name.entry);
+ }
+ entry->id = res.id->first;
}
- // Only mark the type visibility level as public, it doesn't care about being private.
- if (visibility.level == Visibility::Level::kPublic) {
- type->visibility_level = Visibility::Level::kPublic;
+ if (res.visibility.has_value()) {
+ // Only mark the type visibility level as public, it doesn't care about being private.
+ if (res.visibility->level == Visibility::Level::kPublic) {
+ type->visibility_level = Visibility::Level::kPublic;
+ }
+
+ if (res.visibility->level > entry->visibility.level) {
+ // This symbol definition takes precedence, replace.
+ entry->visibility = res.visibility.value();
+ }
+
+ if (res.visibility->staged_api) {
+ entry->visibility.staged_api = entry->visibility.staged_api;
+ }
}
- if (visibility.level == Visibility::Level::kUndefined &&
- entry->visibility.level != Visibility::Level::kUndefined) {
- // We can't undefine a symbol (remove its visibility). Ignore.
- return true;
+ if (res.overlayable.has_value()) {
+ if (entry->overlayable_item) {
+ diag->Error(DiagMessage(res.overlayable->source)
+ << "duplicate overlayable declaration for resource '" << res.name << "'");
+ diag->Error(DiagMessage(entry->overlayable_item.value().source)
+ << "previous declaration here");
+ return false;
+ }
+ entry->overlayable_item = res.overlayable.value();
}
- if (visibility.level < entry->visibility.level) {
- // We can't downgrade public to private. Ignore.
- return true;
+ if (res.allow_new.has_value()) {
+ entry->allow_new = res.allow_new.value();
}
- // This symbol definition takes precedence, replace.
- entry->visibility = visibility;
- return true;
-}
+ if (res.value != nullptr) {
+ auto config_value = entry->FindOrCreateValue(res.config, res.product);
+ if (!config_value->value) {
+ // Resource does not exist, add it now.
+ config_value->value = std::move(res.value);
+ } else {
+ // When validation is enabled, ensure that a resource cannot have multiple values defined for
+ // the same configuration.
+ auto result = validate ? ResolveValueCollision(config_value->value.get(), res.value.get())
+ : CollisionResult::kKeepBoth;
+ switch (result) {
+ case CollisionResult::kKeepBoth:
+ // Insert the value ignoring for duplicate configurations
+ entry->values.push_back(util::make_unique<ResourceConfigValue>(res.config, res.product));
+ entry->values.back()->value = std::move(res.value);
+ break;
-bool ResourceTable::SetAllowNew(const ResourceNameRef& name, const AllowNew& allow_new,
- IDiagnostics* diag) {
- return SetAllowNewImpl(name, allow_new, ResourceNameValidator, diag);
-}
+ case CollisionResult::kTakeNew:
+ // Take the incoming value.
+ config_value->value = std::move(res.value);
+ break;
-bool ResourceTable::SetAllowNewMangled(const ResourceNameRef& name, const AllowNew& allow_new,
- IDiagnostics* diag) {
- return SetAllowNewImpl(name, allow_new, SkipNameValidator, diag);
-}
+ case CollisionResult::kConflict:
+ diag->Error(DiagMessage(source) << "duplicate value for resource '" << res.name << "' "
+ << "with config '" << res.config << "'");
+ diag->Error(DiagMessage(source) << "resource previously defined here");
+ return false;
-bool ResourceTable::SetAllowNewImpl(const ResourceNameRef& name, const AllowNew& allow_new,
- NameValidator name_validator, IDiagnostics* diag) {
- CHECK(diag != nullptr);
-
- if (!ValidateName(name_validator, name, allow_new.source, diag)) {
- return false;
+ case CollisionResult::kKeepOriginal:
+ break;
+ }
+ }
}
- ResourceTablePackage* package = FindOrCreatePackage(name.package);
- ResourceTableType* type = package->FindOrCreateType(name.type);
- ResourceEntry* entry = type->FindOrCreateEntry(name.entry);
- entry->allow_new = allow_new;
- return true;
-}
-
-bool ResourceTable::SetOverlayable(const ResourceNameRef& name, const OverlayableItem& overlayable,
- IDiagnostics* diag) {
- return SetOverlayableImpl(name, overlayable, ResourceNameValidator, diag);
-}
-
-bool ResourceTable::SetOverlayableImpl(const ResourceNameRef& name,
- const OverlayableItem& overlayable,
- NameValidator name_validator, IDiagnostics *diag) {
- CHECK(diag != nullptr);
-
- if (!ValidateName(name_validator, name, overlayable.source, diag)) {
- return false;
- }
-
- ResourceTablePackage* package = FindOrCreatePackage(name.package);
- ResourceTableType* type = package->FindOrCreateType(name.type);
- ResourceEntry* entry = type->FindOrCreateEntry(name.entry);
-
- if (entry->overlayable_item) {
- diag->Error(DiagMessage(overlayable.source)
- << "duplicate overlayable declaration for resource '" << name << "'");
- diag->Error(DiagMessage(entry->overlayable_item.value().source)
- << "previous declaration here");
- return false;
- }
-
- entry->overlayable_item = overlayable;
return true;
}
@@ -641,17 +553,38 @@
return SearchResult{package, type, entry};
}
+Maybe<ResourceTable::SearchResult> ResourceTable::FindResource(const ResourceNameRef& name,
+ ResourceId id) const {
+ ResourceTablePackage* package = FindPackage(name.package);
+ if (package == nullptr) {
+ return {};
+ }
+
+ ResourceTableType* type = package->FindType(name.type);
+ if (type == nullptr) {
+ return {};
+ }
+
+ auto entry_it = std::equal_range(type->entries.begin(), type->entries.end(), name.entry,
+ NameEqualRange<ResourceEntry>{});
+ for (auto it = entry_it.first; it != entry_it.second; ++it) {
+ if ((*it)->id == id) {
+ return SearchResult{package, type, it->get()};
+ }
+ }
+ return {};
+}
+
std::unique_ptr<ResourceTable> ResourceTable::Clone() const {
std::unique_ptr<ResourceTable> new_table = util::make_unique<ResourceTable>();
for (const auto& pkg : packages) {
- ResourceTablePackage* new_pkg = new_table->CreatePackage(pkg->name, pkg->id);
+ ResourceTablePackage* new_pkg = new_table->FindOrCreatePackage(pkg->name);
for (const auto& type : pkg->types) {
ResourceTableType* new_type = new_pkg->FindOrCreateType(type->type);
- new_type->id = type->id;
new_type->visibility_level = type->visibility_level;
for (const auto& entry : type->entries) {
- ResourceEntry* new_entry = new_type->FindOrCreateEntry(entry->name);
+ ResourceEntry* new_entry = new_type->CreateEntry(entry->name);
new_entry->id = entry->id;
new_entry->visibility = entry->visibility;
new_entry->allow_new = entry->allow_new;
@@ -668,4 +601,51 @@
return new_table;
}
+NewResourceBuilder::NewResourceBuilder(const ResourceNameRef& name) {
+ res_.name = name.ToResourceName();
+}
+
+NewResourceBuilder::NewResourceBuilder(const std::string& name) {
+ ResourceNameRef ref;
+ CHECK(ResourceUtils::ParseResourceName(name, &ref)) << "invalid resource name: " << name;
+ res_.name = ref.ToResourceName();
+}
+
+NewResourceBuilder& NewResourceBuilder::SetValue(std::unique_ptr<Value> value,
+ android::ConfigDescription config,
+ std::string product) {
+ res_.value = std::move(value);
+ res_.config = std::move(config);
+ res_.product = std::move(product);
+ return *this;
+}
+
+NewResourceBuilder& NewResourceBuilder::SetId(ResourceId id, OnIdConflict on_conflict) {
+ res_.id = std::make_pair(id, on_conflict);
+ return *this;
+}
+
+NewResourceBuilder& NewResourceBuilder::SetVisibility(Visibility visibility) {
+ res_.visibility = std::move(visibility);
+ return *this;
+}
+
+NewResourceBuilder& NewResourceBuilder::SetOverlayable(OverlayableItem overlayable) {
+ res_.overlayable = std::move(overlayable);
+ return *this;
+}
+NewResourceBuilder& NewResourceBuilder::SetAllowNew(AllowNew allow_new) {
+ res_.allow_new = std::move(allow_new);
+ return *this;
+}
+
+NewResourceBuilder& NewResourceBuilder::SetAllowMangled(bool allow_mangled) {
+ res_.allow_mangled = allow_mangled;
+ return *this;
+}
+
+NewResource NewResourceBuilder::Build() {
+ return std::move(res_);
+}
+
} // namespace aapt
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 93a7a31..080ecc2 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -51,6 +51,11 @@
Level level = Level::kUndefined;
Source source;
std::string comment;
+
+ // Indicates that the resource id may change across builds and that the public R.java identifier
+ // for this resource should not be final. This is set to `true` for resources in `staging-group`
+ // tags.
+ bool staged_api = false;
};
// Represents <add-resource> in an overlay.
@@ -109,7 +114,7 @@
const std::string name;
// The entry ID for this resource (the EEEE in 0xPPTTEEEE).
- Maybe<uint16_t> id;
+ Maybe<ResourceId> id;
// Whether this resource is public (and must maintain the same entry ID across builds).
Visibility visibility;
@@ -124,10 +129,10 @@
explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
- ResourceConfigValue* FindValue(const android::ConfigDescription& config);
-
ResourceConfigValue* FindValue(const android::ConfigDescription& config,
- const android::StringPiece& product);
+ android::StringPiece product = {});
+ const ResourceConfigValue* FindValue(const android::ConfigDescription& config,
+ android::StringPiece product = {}) const;
ResourceConfigValue* FindOrCreateValue(const android::ConfigDescription& config,
const android::StringPiece& product);
@@ -156,9 +161,6 @@
// The logical type of resource (string, drawable, layout, etc.).
const ResourceType type;
- // The type ID for this resource (the TT in 0xPPTTEEEE).
- Maybe<uint8_t> id;
-
// Whether this type is public (and must maintain the same type ID across builds).
Visibility::Level visibility_level = Visibility::Level::kUndefined;
@@ -167,10 +169,9 @@
explicit ResourceTableType(const ResourceType type) : type(type) {}
- ResourceEntry* FindEntry(const android::StringPiece& name,
- Maybe<uint16_t> id = Maybe<uint16_t>());
- ResourceEntry* FindOrCreateEntry(const android::StringPiece& name,
- Maybe<uint16_t> id = Maybe<uint16_t>());
+ ResourceEntry* CreateEntry(const android::StringPiece& name);
+ ResourceEntry* FindEntry(const android::StringPiece& name) const;
+ ResourceEntry* FindOrCreateEntry(const android::StringPiece& name);
private:
DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
@@ -180,70 +181,99 @@
public:
std::string name;
- // The package ID (the PP in 0xPPTTEEEE).
- Maybe<uint8_t> id;
-
std::vector<std::unique_ptr<ResourceTableType>> types;
+ explicit ResourceTablePackage(const android::StringPiece& name) : name(name.to_string()) {
+ }
+
ResourceTablePackage() = default;
- ResourceTableType* FindType(ResourceType type, Maybe<uint8_t> id = Maybe<uint8_t>());
- ResourceTableType* FindOrCreateType(const ResourceType type,
- Maybe<uint8_t> id = Maybe<uint8_t>());
+ ResourceTableType* FindType(ResourceType type) const;
+ ResourceTableType* FindOrCreateType(ResourceType type);
private:
DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
};
+struct ResourceTableTypeView {
+ ResourceType type;
+ Maybe<uint8_t> id;
+ Visibility::Level visibility_level = Visibility::Level::kUndefined;
+
+ // Entries sorted in ascending entry id order. If ids have not been assigned, the entries are
+ // // sorted lexicographically.
+ std::vector<const ResourceEntry*> entries;
+};
+
+struct ResourceTablePackageView {
+ std::string name;
+ Maybe<uint8_t> id;
+ // Types sorted in ascending type id order. If ids have not been assigned, the types are sorted by
+ // their declaration order in the ResourceType enum.
+ std::vector<ResourceTableTypeView> types;
+};
+
+struct ResourceTableView {
+ // Packages sorted in ascending package id order. If ids have not been assigned, the packages are
+ // sorted lexicographically.
+ std::vector<ResourceTablePackageView> packages;
+};
+
+enum class OnIdConflict {
+ // If the resource entry already exists but has a different resource id, the resource value will
+ // not be added to the table.
+ ERROR,
+
+ // If the resource entry already exists but has a different resource id, create a new resource
+ // with this resource name and id combination.
+ CREATE_ENTRY,
+};
+
+struct NewResource {
+ ResourceName name;
+ std::unique_ptr<Value> value;
+ android::ConfigDescription config;
+ std::string product;
+ std::optional<std::pair<ResourceId, OnIdConflict>> id;
+ std::optional<Visibility> visibility;
+ std::optional<OverlayableItem> overlayable;
+ std::optional<AllowNew> allow_new;
+ bool allow_mangled = false;
+};
+
+struct NewResourceBuilder {
+ explicit NewResourceBuilder(const ResourceNameRef& name);
+ explicit NewResourceBuilder(const std::string& name);
+ NewResourceBuilder& SetValue(std::unique_ptr<Value> value, android::ConfigDescription config = {},
+ std::string product = {});
+ NewResourceBuilder& SetId(ResourceId id, OnIdConflict on_conflict = OnIdConflict::ERROR);
+ NewResourceBuilder& SetVisibility(Visibility id);
+ NewResourceBuilder& SetOverlayable(OverlayableItem overlayable);
+ NewResourceBuilder& SetAllowNew(AllowNew allow_new);
+ NewResourceBuilder& SetAllowMangled(bool allow_mangled);
+ NewResource Build();
+
+ private:
+ NewResource res_;
+};
+
// The container and index for all resources defined for an app.
class ResourceTable {
public:
- ResourceTable() = default;
- explicit ResourceTable(bool validate_resources) : validate_resources_(validate_resources) {}
+ enum class Validation {
+ kEnabled,
+ kDisabled,
+ };
enum class CollisionResult { kKeepBoth, kKeepOriginal, kConflict, kTakeNew };
- using CollisionResolverFunc = std::function<CollisionResult(Value*, Value*)>;
+ ResourceTable() = default;
+ explicit ResourceTable(Validation validation);
- // When a collision of resources occurs, this method decides which value to keep.
- static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
+ bool AddResource(NewResource&& res, IDiagnostics* diag);
- // When a collision of resources occurs, this method keeps both values
- static CollisionResult IgnoreCollision(Value* existing, Value* incoming);
-
- bool AddResource(const ResourceNameRef& name, const android::ConfigDescription& config,
- const android::StringPiece& product, std::unique_ptr<Value> value,
- IDiagnostics* diag);
-
- bool AddResourceWithId(const ResourceNameRef& name, const ResourceId& res_id,
- const android::ConfigDescription& config,
- const android::StringPiece& product, std::unique_ptr<Value> value,
- IDiagnostics* diag);
-
- // Same as AddResource, but doesn't verify the validity of the name. This is used
- // when loading resources from an existing binary resource table that may have mangled names.
- bool AddResourceMangled(const ResourceNameRef& name, const android::ConfigDescription& config,
- const android::StringPiece& product, std::unique_ptr<Value> value,
- IDiagnostics* diag);
-
- bool AddResourceWithIdMangled(const ResourceNameRef& name, const ResourceId& id,
- const android::ConfigDescription& config,
- const android::StringPiece& product, std::unique_ptr<Value> value,
- IDiagnostics* diag);
-
- bool GetValidateResources();
-
- bool SetVisibility(const ResourceNameRef& name, const Visibility& visibility, IDiagnostics* diag);
- bool SetVisibilityWithId(const ResourceNameRef& name, const Visibility& visibility,
- const ResourceId& res_id, IDiagnostics* diag);
- bool SetVisibilityWithIdMangled(const ResourceNameRef& name, const Visibility& visibility,
- const ResourceId& res_id, IDiagnostics* diag);
-
- bool SetOverlayable(const ResourceNameRef& name, const OverlayableItem& overlayable,
- IDiagnostics *diag);
-
- bool SetAllowNew(const ResourceNameRef& name, const AllowNew& allow_new, IDiagnostics* diag);
- bool SetAllowNewMangled(const ResourceNameRef& name, const AllowNew& allow_new,
- IDiagnostics* diag);
+ // Retrieves a sorted a view of the packages, types, and entries sorted in ascending resource id
+ // order.
+ ResourceTableView GetPartitionedView() const;
struct SearchResult {
ResourceTablePackage* package;
@@ -252,23 +282,19 @@
};
Maybe<SearchResult> FindResource(const ResourceNameRef& name) const;
+ Maybe<SearchResult> FindResource(const ResourceNameRef& name, ResourceId id) const;
// Returns the package struct with the given name, or nullptr if such a package does not
// exist. The empty string is a valid package and typically is used to represent the
// 'current' package before it is known to the ResourceTable.
ResourceTablePackage* FindPackage(const android::StringPiece& name) const;
-
- ResourceTablePackage* FindPackageById(uint8_t id) const;
-
- ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
-
- // Attempts to find a package having the specified name and ID. If not found, a new package
- // of the specified parameters is created and returned.
- ResourceTablePackage* CreatePackageAllowingDuplicateNames(const android::StringPiece& name,
- const Maybe<uint8_t> id);
+ ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
std::unique_ptr<ResourceTable> Clone() const;
+ // When a collision of resources occurs, this method decides which value to keep.
+ static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
+
// The string pool used by this resource table. Values that reference strings must use
// this pool to create their strings.
// NOTE: `string_pool` must come before `packages` so that it is destroyed after.
@@ -286,36 +312,9 @@
std::map<size_t, std::string> included_packages_;
private:
- // The function type that validates a symbol name. Returns a non-empty StringPiece representing
- // the offending character (which may be more than one byte in UTF-8). Returns an empty string
- // if the name was valid.
- using NameValidator = android::StringPiece(const android::StringPiece&);
-
- ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
-
- bool ValidateName(NameValidator validator, const ResourceNameRef& name, const Source& source,
- IDiagnostics* diag);
-
- bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
- const android::ConfigDescription& config,
- const android::StringPiece& product, std::unique_ptr<Value> value,
- NameValidator name_validator, const CollisionResolverFunc& conflict_resolver,
- IDiagnostics* diag);
-
- bool SetVisibilityImpl(const ResourceNameRef& name, const Visibility& visibility,
- const ResourceId& res_id, NameValidator name_validator,
- IDiagnostics* diag);
-
- bool SetAllowNewImpl(const ResourceNameRef& name, const AllowNew& allow_new,
- NameValidator name_validator, IDiagnostics* diag);
-
- bool SetOverlayableImpl(const ResourceNameRef &name, const OverlayableItem& overlayable,
- NameValidator name_validator, IDiagnostics *diag);
-
- // Controls whether the table validates resource names and prevents duplicate resource names
- bool validate_resources_ = true;
-
DISALLOW_COPY_AND_ASSIGN(ResourceTable);
+
+ Validation validation_ = Validation::kEnabled;
};
} // namespace aapt
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
index 9271a7e..38391c9 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -37,31 +37,32 @@
TEST(ResourceTableTest, FailToAddResourceWithBadName) {
ResourceTable table;
- EXPECT_FALSE(table.AddResource(
- test::ParseNameOrDie("android:id/hey,there"), ConfigDescription{}, "",
- test::ValueBuilder<Id>().SetSource("test.xml", 21u).Build(),
- test::GetDiagnostics()));
+ EXPECT_FALSE(
+ table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:id/hey,there")).Build(),
+ test::GetDiagnostics()));
- EXPECT_FALSE(table.AddResource(
- test::ParseNameOrDie("android:id/hey:there"), ConfigDescription{}, "",
- test::ValueBuilder<Id>().SetSource("test.xml", 21u).Build(),
- test::GetDiagnostics()));
+ EXPECT_FALSE(
+ table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:id/hey:there")).Build(),
+ test::GetDiagnostics()));
}
TEST(ResourceTableTest, AddResourceWithWeirdNameWhenAddingMangledResources) {
ResourceTable table;
- EXPECT_TRUE(table.AddResourceMangled(
- test::ParseNameOrDie("android:id/heythere "), ConfigDescription{}, "",
- test::ValueBuilder<Id>().SetSource("test.xml", 21u).Build(), test::GetDiagnostics()));
+ EXPECT_TRUE(
+ table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:id/heythere "))
+ .SetAllowMangled(true)
+ .Build(),
+ test::GetDiagnostics()));
}
TEST(ResourceTableTest, AddOneResource) {
ResourceTable table;
EXPECT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:attr/id"), ConfigDescription{}, "",
- test::ValueBuilder<Id>().SetSource("test/path/file.xml", 23u).Build(),
+ NewResourceBuilder(test::ParseNameOrDie("android:attr/id"))
+ .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 23u).Build())
+ .Build(),
test::GetDiagnostics()));
EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/id"), NotNull());
@@ -70,32 +71,36 @@
TEST(ResourceTableTest, AddMultipleResources) {
ResourceTable table;
- ConfigDescription config;
ConfigDescription language_config;
memcpy(language_config.language, "pl", sizeof(language_config.language));
EXPECT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:attr/layout_width"), config, "",
- test::ValueBuilder<Id>().SetSource("test/path/file.xml", 10u).Build(),
- test::GetDiagnostics()));
-
- EXPECT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:attr/id"), config, "",
- test::ValueBuilder<Id>().SetSource("test/path/file.xml", 12u).Build(),
- test::GetDiagnostics()));
-
- EXPECT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/ok"), config, "",
- test::ValueBuilder<Id>().SetSource("test/path/file.xml", 14u).Build(),
- test::GetDiagnostics()));
-
- EXPECT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/ok"), language_config, "",
- test::ValueBuilder<BinaryPrimitive>(android::Res_value{})
- .SetSource("test/path/file.xml", 20u)
+ NewResourceBuilder(test::ParseNameOrDie("android:attr/layout_width"))
+ .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 10u).Build())
.Build(),
test::GetDiagnostics()));
+ EXPECT_TRUE(table.AddResource(
+ NewResourceBuilder(test::ParseNameOrDie("android:attr/id"))
+ .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 12u).Build())
+ .Build(),
+ test::GetDiagnostics()));
+
+ EXPECT_TRUE(table.AddResource(
+ NewResourceBuilder(test::ParseNameOrDie("android:string/ok"))
+ .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 14u).Build())
+ .Build(),
+ test::GetDiagnostics()));
+
+ EXPECT_TRUE(
+ table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:string/ok"))
+ .SetValue(test::ValueBuilder<BinaryPrimitive>(android::Res_value{})
+ .SetSource("test/path/file.xml", 20u)
+ .Build(),
+ language_config)
+ .Build(),
+ test::GetDiagnostics()));
+
EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/layout_width"), NotNull());
EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/id"), NotNull());
EXPECT_THAT(test::GetValue<Id>(&table, "android:string/ok"), NotNull());
@@ -104,17 +109,19 @@
TEST(ResourceTableTest, OverrideWeakResourceValue) {
ResourceTable table;
-
- ASSERT_TRUE(table.AddResource(test::ParseNameOrDie("android:attr/foo"), ConfigDescription{}, "",
- test::AttributeBuilder().SetWeak(true).Build(),
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:attr/foo"))
+ .SetValue(test::AttributeBuilder().SetWeak(true).Build())
+ .Build(),
test::GetDiagnostics()));
Attribute* attr = test::GetValue<Attribute>(&table, "android:attr/foo");
ASSERT_THAT(attr, NotNull());
EXPECT_TRUE(attr->IsWeak());
- ASSERT_TRUE(table.AddResource(test::ParseNameOrDie("android:attr/foo"), ConfigDescription{}, "",
- util::make_unique<Attribute>(), test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:attr/foo"))
+ .SetValue(util::make_unique<Attribute>())
+ .Build(),
+ test::GetDiagnostics()));
attr = test::GetValue<Attribute>(&table, "android:attr/foo");
ASSERT_THAT(attr, NotNull());
@@ -130,23 +137,27 @@
Attribute attr_two(android::ResTable_map::TYPE_STRING | android::ResTable_map::TYPE_REFERENCE);
attr_two.SetWeak(true);
- ASSERT_TRUE(table.AddResource(name, ConfigDescription{}, "",
- util::make_unique<Attribute>(attr_one), test::GetDiagnostics()));
- ASSERT_TRUE(table.AddResource(name, ConfigDescription{}, "",
- util::make_unique<Attribute>(attr_two), test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(
+ NewResourceBuilder(name).SetValue(util::make_unique<Attribute>(attr_one)).Build(),
+ test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(
+ NewResourceBuilder(name).SetValue(util::make_unique<Attribute>(attr_two)).Build(),
+ test::GetDiagnostics()));
}
TEST(ResourceTableTest, ProductVaryingValues) {
ResourceTable table;
+ ASSERT_TRUE(table.AddResource(
+ NewResourceBuilder(test::ParseNameOrDie("android:string/foo"))
+ .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land"), "tablet")
+ .Build(),
+ test::GetDiagnostics()));
- EXPECT_TRUE(table.AddResource(test::ParseNameOrDie("android:string/foo"),
- test::ParseConfigOrDie("land"), "tablet",
- util::make_unique<Id>(),
- test::GetDiagnostics()));
- EXPECT_TRUE(table.AddResource(test::ParseNameOrDie("android:string/foo"),
- test::ParseConfigOrDie("land"), "phone",
- util::make_unique<Id>(),
- test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(
+ NewResourceBuilder(test::ParseNameOrDie("android:string/foo"))
+ .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land"), "phone")
+ .Build(),
+ test::GetDiagnostics()));
EXPECT_THAT(test::GetValueForConfigAndProduct<Id>(&table, "android:string/foo",test::ParseConfigOrDie("land"), "tablet"), NotNull());
EXPECT_THAT(test::GetValueForConfigAndProduct<Id>(&table, "android:string/foo",test::ParseConfigOrDie("land"), "phone"), NotNull());
@@ -203,22 +214,26 @@
Visibility visibility;
visibility.level = Visibility::Level::kPrivate;
visibility.comment = "private";
- ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
+ test::GetDiagnostics()));
ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPrivate, "private"));
visibility.level = Visibility::Level::kUndefined;
visibility.comment = "undefined";
- ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
+ test::GetDiagnostics()));
ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPrivate, "private"));
visibility.level = Visibility::Level::kPublic;
visibility.comment = "public";
- ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
+ test::GetDiagnostics()));
ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPublic, "public"));
visibility.level = Visibility::Level::kPrivate;
visibility.comment = "private";
- ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
+ test::GetDiagnostics()));
ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPublic, "public"));
}
@@ -230,14 +245,16 @@
Maybe<ResourceTable::SearchResult> result;
allow_new.comment = "first";
- ASSERT_TRUE(table.SetAllowNew(name, allow_new, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetAllowNew(allow_new).Build(),
+ test::GetDiagnostics()));
result = table.FindResource(name);
ASSERT_TRUE(result);
ASSERT_TRUE(result.value().entry->allow_new);
ASSERT_THAT(result.value().entry->allow_new.value().comment, StrEq("first"));
allow_new.comment = "second";
- ASSERT_TRUE(table.SetAllowNew(name, allow_new, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetAllowNew(allow_new).Build(),
+ test::GetDiagnostics()));
result = table.FindResource(name);
ASSERT_TRUE(result);
ASSERT_TRUE(result.value().entry->allow_new);
@@ -255,7 +272,8 @@
overlayable_item.source = Source("res/values/overlayable.xml", 42);
const ResourceName name = test::ParseNameOrDie("android:string/foo");
- ASSERT_TRUE(table.SetOverlayable(name, overlayable_item, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item).Build(),
+ test::GetDiagnostics()));
Maybe<ResourceTable::SearchResult> search_result = table.FindResource(name);
ASSERT_TRUE(search_result);
@@ -280,17 +298,20 @@
auto group = std::make_shared<Overlayable>("Name", "overlay://theme");
OverlayableItem overlayable(group);
overlayable.policies = PolicyFlags::PRODUCT_PARTITION;
- ASSERT_TRUE(table.SetOverlayable(foo, overlayable, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(foo).SetOverlayable(overlayable).Build(),
+ test::GetDiagnostics()));
const ResourceName bar = test::ParseNameOrDie("android:string/bar");
OverlayableItem overlayable2(group);
overlayable2.policies = PolicyFlags::PRODUCT_PARTITION;
- ASSERT_TRUE(table.SetOverlayable(bar, overlayable2, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(bar).SetOverlayable(overlayable2).Build(),
+ test::GetDiagnostics()));
const ResourceName baz = test::ParseNameOrDie("android:string/baz");
OverlayableItem overlayable3(group);
overlayable3.policies = PolicyFlags::VENDOR_PARTITION;
- ASSERT_TRUE(table.SetOverlayable(baz, overlayable3, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(baz).SetOverlayable(overlayable3).Build(),
+ test::GetDiagnostics()));
}
TEST(ResourceTableTest, SetOverlayableDifferentResourcesDifferentName) {
@@ -299,12 +320,14 @@
const ResourceName foo = test::ParseNameOrDie("android:string/foo");
OverlayableItem overlayable_item(std::make_shared<Overlayable>("Name", "overlay://theme"));
overlayable_item.policies = PolicyFlags::PRODUCT_PARTITION;
- ASSERT_TRUE(table.SetOverlayable(foo, overlayable_item, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(foo).SetOverlayable(overlayable_item).Build(),
+ test::GetDiagnostics()));
const ResourceName bar = test::ParseNameOrDie("android:string/bar");
OverlayableItem overlayable_item2(std::make_shared<Overlayable>("Name2", "overlay://theme"));
overlayable_item2.policies = PolicyFlags::PRODUCT_PARTITION;
- ASSERT_TRUE(table.SetOverlayable(bar, overlayable_item2, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(bar).SetOverlayable(overlayable_item2).Build(),
+ test::GetDiagnostics()));
}
TEST(ResourceTableTest, SetOverlayableSameResourcesFail) {
@@ -313,10 +336,12 @@
auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme");
OverlayableItem overlayable_item(overlayable);
- ASSERT_TRUE(table.SetOverlayable(name, overlayable_item, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item).Build(),
+ test::GetDiagnostics()));
OverlayableItem overlayable_item2(overlayable);
- ASSERT_FALSE(table.SetOverlayable(name, overlayable_item2, test::GetDiagnostics()));
+ ASSERT_FALSE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item2).Build(),
+ test::GetDiagnostics()));
}
TEST(ResourceTableTest, SetOverlayableSameResourcesDifferentNameFail) {
@@ -325,51 +350,38 @@
auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme");
OverlayableItem overlayable_item(overlayable);
- ASSERT_TRUE(table.SetOverlayable(name, overlayable_item, test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item).Build(),
+ test::GetDiagnostics()));
auto overlayable2 = std::make_shared<Overlayable>("Other", "overlay://theme");
OverlayableItem overlayable_item2(overlayable2);
- ASSERT_FALSE(table.SetOverlayable(name, overlayable_item2, test::GetDiagnostics()));
+ ASSERT_FALSE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item2).Build(),
+ test::GetDiagnostics()));
}
-TEST(ResourceTableTest, AllowDuplictaeResourcesNames) {
- ResourceTable table(/* validate_resources */ false);
+TEST(ResourceTableTest, ConflictingIds) {
+ ResourceTable table;
+ const ResourceName name = test::ParseNameOrDie("android:string/foo");
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetId(0x01010000).Build(),
+ test::GetDiagnostics()));
+ ASSERT_FALSE(table.AddResource(NewResourceBuilder(name).SetId(0x01010001).Build(),
+ test::GetDiagnostics()));
+}
- const ResourceName foo_name = test::ParseNameOrDie("android:bool/foo");
- ASSERT_TRUE(table.AddResourceWithId(foo_name, ResourceId(0x7f0100ff), ConfigDescription{} , "",
- test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, 0),
- test::GetDiagnostics()));
- ASSERT_TRUE(table.AddResourceWithId(foo_name, ResourceId(0x7f010100), ConfigDescription{} , "",
- test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, 1),
- test::GetDiagnostics()));
+TEST(ResourceTableTest, ConflictingIdsCreateEntry) {
+ ResourceTable table;
+ const ResourceName name = test::ParseNameOrDie("android:string/foo");
+ ASSERT_TRUE(table.AddResource(
+ NewResourceBuilder(name).SetId(0x01010000, OnIdConflict::CREATE_ENTRY).Build(),
+ test::GetDiagnostics()));
+ ASSERT_TRUE(table.AddResource(
+ NewResourceBuilder(name).SetId(0x01010001, OnIdConflict::CREATE_ENTRY).Build(),
+ test::GetDiagnostics()));
- ASSERT_TRUE(table.SetVisibilityWithId(foo_name, Visibility{Visibility::Level::kPublic},
- ResourceId(0x7f0100ff), test::GetDiagnostics()));
- ASSERT_TRUE(table.SetVisibilityWithId(foo_name, Visibility{Visibility::Level::kPrivate},
- ResourceId(0x7f010100), test::GetDiagnostics()));
-
- auto package = table.FindPackageById(0x7f);
- ASSERT_THAT(package, NotNull());
- auto type = package->FindType(ResourceType::kBool);
- ASSERT_THAT(type, NotNull());
-
- auto entry1 = type->FindEntry("foo", 0x00ff);
- ASSERT_THAT(entry1, NotNull());
- ASSERT_THAT(entry1->id, Eq(0x00ff));
- ASSERT_THAT(entry1->values[0], NotNull());
- ASSERT_THAT(entry1->values[0]->value, NotNull());
- ASSERT_THAT(ValueCast<BinaryPrimitive>(entry1->values[0]->value.get()), NotNull());
- ASSERT_THAT(ValueCast<BinaryPrimitive>(entry1->values[0]->value.get())->value.data, Eq(0u));
- ASSERT_THAT(entry1->visibility.level, Visibility::Level::kPublic);
-
- auto entry2 = type->FindEntry("foo", 0x0100);
- ASSERT_THAT(entry2, NotNull());
- ASSERT_THAT(entry2->id, Eq(0x0100));
- ASSERT_THAT(entry2->values[0], NotNull());
- ASSERT_THAT(entry1->values[0]->value, NotNull());
- ASSERT_THAT(ValueCast<BinaryPrimitive>(entry2->values[0]->value.get()), NotNull());
- ASSERT_THAT(ValueCast<BinaryPrimitive>(entry2->values[0]->value.get())->value.data, Eq(1u));
- ASSERT_THAT(entry2->visibility.level, Visibility::Level::kPrivate);
+ // Non-ambiguous query
+ ASSERT_TRUE(table.AddResource(
+ NewResourceBuilder(name).SetId(0x01010001).SetValue(std::make_unique<Id>()).Build(),
+ test::GetDiagnostics()));
}
} // namespace aapt
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index b1e1a77..4247ec5 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -132,6 +132,11 @@
// The comment associated with the <public> tag.
string comment = 3;
+
+ // Indicates that the resource id may change across builds and that the public R.java identifier
+ // for this resource should not be final. This is set to `true` for resources in `staging-group`
+ // tags.
+ bool staged_api = 4;
}
// Whether a resource comes from a compile-time overlay and is explicitly allowed to not overlay an
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index ff54fcc..cd5015e 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -190,17 +190,6 @@
}
}
- // Ensure we have the compilation package at least.
- table.CreatePackage(context->GetCompilationPackage());
-
- // Assign an ID to any package that has resources.
- for (auto& pkg : table.packages) {
- if (!pkg->id) {
- // If no package ID was set while parsing (public identifiers), auto assign an ID.
- pkg->id = context->GetPackageId();
- }
- }
-
// Create the file/zip entry.
if (!writer->StartEntry(output_path, 0)) {
context->GetDiagnostics()->Error(DiagMessage(output_path) << "failed to open");
diff --git a/tools/aapt2/cmd/Compile_test.cpp b/tools/aapt2/cmd/Compile_test.cpp
index 8cbd998..8975713 100644
--- a/tools/aapt2/cmd/Compile_test.cpp
+++ b/tools/aapt2/cmd/Compile_test.cpp
@@ -217,6 +217,7 @@
}, compiled_files_dir, &diag));
std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+ ASSERT_NE(apk, nullptr);
ResourceTable* table = apk->GetResourceTable();
ASSERT_NE(table, nullptr);
diff --git a/tools/aapt2/cmd/Diff.cpp b/tools/aapt2/cmd/Diff.cpp
index d56994e..df31087 100644
--- a/tools/aapt2/cmd/Diff.cpp
+++ b/tools/aapt2/cmd/Diff.cpp
@@ -83,7 +83,7 @@
}
static bool IsSymbolVisibilityDifferent(const Visibility& vis_a, const Visibility& vis_b) {
- return vis_a.level != vis_b.level;
+ return vis_a.level != vis_b.level || vis_a.staged_api != vis_b.staged_api;
}
template <typename Id>
@@ -95,17 +95,17 @@
return false;
}
-static bool EmitResourceConfigValueDiff(IAaptContext* context, LoadedApk* apk_a,
- ResourceTablePackage* pkg_a, ResourceTableType* type_a,
- ResourceEntry* entry_a, ResourceConfigValue* config_value_a,
- LoadedApk* apk_b, ResourceTablePackage* pkg_b,
- ResourceTableType* type_b, ResourceEntry* entry_b,
- ResourceConfigValue* config_value_b) {
+static bool EmitResourceConfigValueDiff(
+ IAaptContext* context, LoadedApk* apk_a, const ResourceTablePackageView& pkg_a,
+ const ResourceTableTypeView& type_a, const ResourceEntry* entry_a,
+ const ResourceConfigValue* config_value_a, LoadedApk* apk_b,
+ const ResourceTablePackageView& pkg_b, const ResourceTableTypeView& type_b,
+ const ResourceEntry* entry_b, const ResourceConfigValue* config_value_b) {
Value* value_a = config_value_a->value.get();
Value* value_b = config_value_b->value.get();
if (!value_a->Equals(value_b)) {
std::stringstream str_stream;
- str_stream << "value " << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
+ str_stream << "value " << pkg_a.name << ":" << type_a.type << "/" << entry_a->name
<< " config=" << config_value_a->config << " does not match:\n";
value_a->Print(&str_stream);
str_stream << "\n vs \n";
@@ -117,16 +117,17 @@
}
static bool EmitResourceEntryDiff(IAaptContext* context, LoadedApk* apk_a,
- ResourceTablePackage* pkg_a, ResourceTableType* type_a,
- ResourceEntry* entry_a, LoadedApk* apk_b,
- ResourceTablePackage* pkg_b, ResourceTableType* type_b,
- ResourceEntry* entry_b) {
+ const ResourceTablePackageView& pkg_a,
+ const ResourceTableTypeView& type_a, const ResourceEntry* entry_a,
+ LoadedApk* apk_b, const ResourceTablePackageView& pkg_b,
+ const ResourceTableTypeView& type_b,
+ const ResourceEntry* entry_b) {
bool diff = false;
- for (std::unique_ptr<ResourceConfigValue>& config_value_a : entry_a->values) {
- ResourceConfigValue* config_value_b = entry_b->FindValue(config_value_a->config);
+ for (const std::unique_ptr<ResourceConfigValue>& config_value_a : entry_a->values) {
+ auto config_value_b = entry_b->FindValue(config_value_a->config);
if (!config_value_b) {
std::stringstream str_stream;
- str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
+ str_stream << "missing " << pkg_a.name << ":" << type_a.type << "/" << entry_a->name
<< " config=" << config_value_a->config;
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
@@ -138,42 +139,60 @@
}
// Check for any newly added config values.
- for (std::unique_ptr<ResourceConfigValue>& config_value_b : entry_b->values) {
- ResourceConfigValue* config_value_a = entry_a->FindValue(config_value_b->config);
+ for (const std::unique_ptr<ResourceConfigValue>& config_value_b : entry_b->values) {
+ auto config_value_a = entry_a->FindValue(config_value_b->config);
if (!config_value_a) {
std::stringstream str_stream;
- str_stream << "new config " << pkg_b->name << ":" << type_b->type << "/" << entry_b->name
+ str_stream << "new config " << pkg_b.name << ":" << type_b.type << "/" << entry_b->name
<< " config=" << config_value_b->config;
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
}
}
- return false;
+ return diff;
}
static bool EmitResourceTypeDiff(IAaptContext* context, LoadedApk* apk_a,
- ResourceTablePackage* pkg_a, ResourceTableType* type_a,
- LoadedApk* apk_b, ResourceTablePackage* pkg_b,
- ResourceTableType* type_b) {
+ const ResourceTablePackageView& pkg_a,
+ const ResourceTableTypeView& type_a, LoadedApk* apk_b,
+ const ResourceTablePackageView& pkg_b,
+ const ResourceTableTypeView& type_b) {
bool diff = false;
- for (std::unique_ptr<ResourceEntry>& entry_a : type_a->entries) {
- ResourceEntry* entry_b = type_b->FindEntry(entry_a->name);
- if (!entry_b) {
+ auto entry_a_iter = type_a.entries.begin();
+ auto entry_b_iter = type_b.entries.begin();
+ while (entry_a_iter != type_a.entries.end() || entry_b_iter != type_b.entries.end()) {
+ if (entry_b_iter == type_b.entries.end()) {
+ // Type A contains a type that type B does not have.
std::stringstream str_stream;
- str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/" << entry_a->name;
+ str_stream << "missing " << pkg_a.name << ":" << type_a.type << "/" << (*entry_a_iter)->name;
+ EmitDiffLine(apk_a->GetSource(), str_stream.str());
+ diff = true;
+ } else if (entry_a_iter == type_a.entries.end()) {
+ // Type B contains a type that type A does not have.
+ std::stringstream str_stream;
+ str_stream << "new entry " << pkg_b.name << ":" << type_b.type << "/"
+ << (*entry_b_iter)->name;
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
} else {
+ const auto& entry_a = *entry_a_iter;
+ const auto& entry_b = *entry_b_iter;
if (IsSymbolVisibilityDifferent(entry_a->visibility, entry_b->visibility)) {
std::stringstream str_stream;
- str_stream << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
+ str_stream << pkg_a.name << ":" << type_a.type << "/" << entry_a->name
<< " has different visibility (";
+ if (entry_b->visibility.staged_api) {
+ str_stream << "STAGED ";
+ }
if (entry_b->visibility.level == Visibility::Level::kPublic) {
str_stream << "PUBLIC";
} else {
str_stream << "PRIVATE";
}
str_stream << " vs ";
+ if (entry_a->visibility.staged_api) {
+ str_stream << "STAGED ";
+ }
if (entry_a->visibility.level == Visibility::Level::kPublic) {
str_stream << "PUBLIC";
} else {
@@ -185,7 +204,7 @@
} else if (IsIdDiff(entry_a->visibility.level, entry_a->id, entry_b->visibility.level,
entry_b->id)) {
std::stringstream str_stream;
- str_stream << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
+ str_stream << pkg_a.name << ":" << type_a.type << "/" << entry_a->name
<< " has different public ID (";
if (entry_b->id) {
str_stream << "0x" << std::hex << entry_b->id.value();
@@ -202,46 +221,51 @@
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
}
- diff |= EmitResourceEntryDiff(context, apk_a, pkg_a, type_a, entry_a.get(), apk_b, pkg_b,
- type_b, entry_b);
+ diff |= EmitResourceEntryDiff(context, apk_a, pkg_a, type_a, entry_a, apk_b, pkg_b, type_b,
+ entry_b);
}
- }
-
- // Check for any newly added entries.
- for (std::unique_ptr<ResourceEntry>& entry_b : type_b->entries) {
- ResourceEntry* entry_a = type_a->FindEntry(entry_b->name);
- if (!entry_a) {
- std::stringstream str_stream;
- str_stream << "new entry " << pkg_b->name << ":" << type_b->type << "/" << entry_b->name;
- EmitDiffLine(apk_b->GetSource(), str_stream.str());
- diff = true;
+ if (entry_a_iter != type_a.entries.end()) {
+ ++entry_a_iter;
+ }
+ if (entry_b_iter != type_b.entries.end()) {
+ ++entry_b_iter;
}
}
return diff;
}
static bool EmitResourcePackageDiff(IAaptContext* context, LoadedApk* apk_a,
- ResourceTablePackage* pkg_a, LoadedApk* apk_b,
- ResourceTablePackage* pkg_b) {
+ const ResourceTablePackageView& pkg_a, LoadedApk* apk_b,
+ const ResourceTablePackageView& pkg_b) {
bool diff = false;
- for (std::unique_ptr<ResourceTableType>& type_a : pkg_a->types) {
- ResourceTableType* type_b = pkg_b->FindType(type_a->type);
- if (!type_b) {
+ auto type_a_iter = pkg_a.types.begin();
+ auto type_b_iter = pkg_b.types.begin();
+ while (type_a_iter != pkg_a.types.end() || type_b_iter != pkg_b.types.end()) {
+ if (type_b_iter == pkg_b.types.end()) {
+ // Type A contains a type that type B does not have.
std::stringstream str_stream;
- str_stream << "missing " << pkg_a->name << ":" << type_a->type;
+ str_stream << "missing " << pkg_a.name << ":" << type_a_iter->type;
EmitDiffLine(apk_a->GetSource(), str_stream.str());
diff = true;
+ } else if (type_a_iter == pkg_a.types.end()) {
+ // Type B contains a type that type A does not have.
+ std::stringstream str_stream;
+ str_stream << "new type " << pkg_b.name << ":" << type_b_iter->type;
+ EmitDiffLine(apk_b->GetSource(), str_stream.str());
+ diff = true;
} else {
- if (type_a->visibility_level != type_b->visibility_level) {
+ const auto& type_a = *type_a_iter;
+ const auto& type_b = *type_b_iter;
+ if (type_a.visibility_level != type_b.visibility_level) {
std::stringstream str_stream;
- str_stream << pkg_a->name << ":" << type_a->type << " has different visibility (";
- if (type_b->visibility_level == Visibility::Level::kPublic) {
+ str_stream << pkg_a.name << ":" << type_a.type << " has different visibility (";
+ if (type_b.visibility_level == Visibility::Level::kPublic) {
str_stream << "PUBLIC";
} else {
str_stream << "PRIVATE";
}
str_stream << " vs ";
- if (type_a->visibility_level == Visibility::Level::kPublic) {
+ if (type_a.visibility_level == Visibility::Level::kPublic) {
str_stream << "PUBLIC";
} else {
str_stream << "PRIVATE";
@@ -249,18 +273,17 @@
str_stream << ")";
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
- } else if (IsIdDiff(type_a->visibility_level, type_a->id, type_b->visibility_level,
- type_b->id)) {
+ } else if (IsIdDiff(type_a.visibility_level, type_a.id, type_b.visibility_level, type_b.id)) {
std::stringstream str_stream;
- str_stream << pkg_a->name << ":" << type_a->type << " has different public ID (";
- if (type_b->id) {
- str_stream << "0x" << std::hex << type_b->id.value();
+ str_stream << pkg_a.name << ":" << type_a.type << " has different public ID (";
+ if (type_b.id) {
+ str_stream << "0x" << std::hex << type_b.id.value();
} else {
str_stream << "none";
}
str_stream << " vs ";
- if (type_a->id) {
- str_stream << "0x " << std::hex << type_a->id.value();
+ if (type_a.id) {
+ str_stream << "0x " << std::hex << type_a.id.value();
} else {
str_stream << "none";
}
@@ -268,47 +291,52 @@
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
}
- diff |= EmitResourceTypeDiff(context, apk_a, pkg_a, type_a.get(), apk_b, pkg_b, type_b);
+ diff |= EmitResourceTypeDiff(context, apk_a, pkg_a, type_a, apk_b, pkg_b, type_b);
}
- }
-
- // Check for any newly added types.
- for (std::unique_ptr<ResourceTableType>& type_b : pkg_b->types) {
- ResourceTableType* type_a = pkg_a->FindType(type_b->type);
- if (!type_a) {
- std::stringstream str_stream;
- str_stream << "new type " << pkg_b->name << ":" << type_b->type;
- EmitDiffLine(apk_b->GetSource(), str_stream.str());
- diff = true;
+ if (type_a_iter != pkg_a.types.end()) {
+ ++type_a_iter;
+ }
+ if (type_b_iter != pkg_b.types.end()) {
+ ++type_b_iter;
}
}
return diff;
}
static bool EmitResourceTableDiff(IAaptContext* context, LoadedApk* apk_a, LoadedApk* apk_b) {
- ResourceTable* table_a = apk_a->GetResourceTable();
- ResourceTable* table_b = apk_b->GetResourceTable();
+ const auto table_a = apk_a->GetResourceTable()->GetPartitionedView();
+ const auto table_b = apk_b->GetResourceTable()->GetPartitionedView();
bool diff = false;
- for (std::unique_ptr<ResourceTablePackage>& pkg_a : table_a->packages) {
- ResourceTablePackage* pkg_b = table_b->FindPackage(pkg_a->name);
- if (!pkg_b) {
+ auto package_a_iter = table_a.packages.begin();
+ auto package_b_iter = table_b.packages.begin();
+ while (package_a_iter != table_a.packages.end() || package_b_iter != table_b.packages.end()) {
+ if (package_b_iter == table_b.packages.end()) {
+ // Table A contains a package that table B does not have.
std::stringstream str_stream;
- str_stream << "missing package " << pkg_a->name;
+ str_stream << "missing package " << package_a_iter->name;
+ EmitDiffLine(apk_a->GetSource(), str_stream.str());
+ diff = true;
+ } else if (package_a_iter == table_a.packages.end()) {
+ // Table B contains a package that table A does not have.
+ std::stringstream str_stream;
+ str_stream << "new package " << package_b_iter->name;
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
} else {
- if (pkg_a->id != pkg_b->id) {
+ const auto& package_a = *package_a_iter;
+ const auto& package_b = *package_b_iter;
+ if (package_a.id != package_b.id) {
std::stringstream str_stream;
- str_stream << "package '" << pkg_a->name << "' has different id (";
- if (pkg_b->id) {
- str_stream << "0x" << std::hex << pkg_b->id.value();
+ str_stream << "package '" << package_a.name << "' has different id (";
+ if (package_b.id) {
+ str_stream << "0x" << std::hex << package_b.id.value();
} else {
str_stream << "none";
}
str_stream << " vs ";
- if (pkg_a->id) {
- str_stream << "0x" << std::hex << pkg_a->id.value();
+ if (package_a.id) {
+ str_stream << "0x" << std::hex << package_b.id.value();
} else {
str_stream << "none";
}
@@ -316,20 +344,16 @@
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
}
- diff |= EmitResourcePackageDiff(context, apk_a, pkg_a.get(), apk_b, pkg_b);
+ diff |= EmitResourcePackageDiff(context, apk_a, package_a, apk_b, package_b);
+ }
+ if (package_a_iter != table_a.packages.end()) {
+ ++package_a_iter;
+ }
+ if (package_b_iter != table_b.packages.end()) {
+ ++package_b_iter;
}
}
- // Check for any newly added packages.
- for (std::unique_ptr<ResourceTablePackage>& pkg_b : table_b->packages) {
- ResourceTablePackage* pkg_a = table_a->FindPackage(pkg_b->name);
- if (!pkg_a) {
- std::stringstream str_stream;
- str_stream << "new package " << pkg_b->name;
- EmitDiffLine(apk_b->GetSource(), str_stream.str());
- diff = true;
- }
- }
return diff;
}
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 13e090d..ee6a764 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -25,6 +25,7 @@
#include <vector>
#include "android-base/errors.h"
+#include "android-base/expected.h"
#include "android-base/file.h"
#include "android-base/stringprintf.h"
#include "androidfw/Locale.h"
@@ -74,10 +75,25 @@
using ::aapt::io::FileInputStream;
using ::android::ConfigDescription;
using ::android::StringPiece;
+using ::android::base::expected;
using ::android::base::StringPrintf;
+using ::android::base::unexpected;
namespace aapt {
+namespace {
+
+expected<ResourceTablePackage*, const char*> GetStaticLibraryPackage(ResourceTable* table) {
+ // Resource tables built by aapt2 always contain one package. This is a post condition of
+ // VerifyNoExternalPackages.
+ if (table->packages.size() != 1u) {
+ return unexpected("static library contains more than one package");
+ }
+ return table->packages.back().get();
+}
+
+} // namespace
+
constexpr uint8_t kAndroidPackageId = 0x01;
class LinkContext : public IAaptContext {
@@ -633,13 +649,18 @@
const ResourceFile& file = doc->file;
dst_path = ResourceUtils::BuildResourceFileName(file, context_->GetNameMangler());
- std::unique_ptr<FileReference> file_ref =
+ auto file_ref =
util::make_unique<FileReference>(table->string_pool.MakeRef(dst_path));
file_ref->SetSource(doc->file.source);
+
// Update the output format of this XML file.
file_ref->type = XmlFileTypeForOutputFormat(options_.output_format);
- if (!table->AddResourceMangled(file.name, file.config, {}, std::move(file_ref),
- context_->GetDiagnostics())) {
+ bool result = table->AddResource(NewResourceBuilder(file.name)
+ .SetValue(std::move(file_ref), file.config)
+ .SetAllowMangled(true)
+ .Build(),
+ context_->GetDiagnostics());
+ if (!result) {
return false;
}
}
@@ -842,18 +863,15 @@
ResourceTable* table = static_apk->GetResourceTable();
// If we are using --no-static-lib-packages, we need to rename the package of this table to
- // our compilation package.
- if (options_.no_static_lib_packages) {
- // Since package names can differ, and multiple packages can exist in a ResourceTable,
- // we place the requirement that all static libraries are built with the package
- // ID 0x7f. So if one is not found, this is an error.
- if (ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId)) {
- pkg->name = context_->GetCompilationPackage();
- } else {
- context_->GetDiagnostics()->Error(DiagMessage(path)
- << "no package with ID 0x7f found in static library");
+ // our compilation package so the symbol package name does not get mangled into the entry
+ // name.
+ if (options_.no_static_lib_packages && !table->packages.empty()) {
+ auto lib_package_result = GetStaticLibraryPackage(table);
+ if (!lib_package_result.has_value()) {
+ context_->GetDiagnostics()->Error(DiagMessage(path) << lib_package_result.error());
return false;
}
+ lib_package_result.value()->name = context_->GetCompilationPackage();
}
context_->GetExternalSymbols()->AppendSource(
@@ -982,8 +1000,7 @@
// stripped, or there is an error and false is returned.
bool VerifyNoExternalPackages() {
auto is_ext_package_func = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
- return context_->GetCompilationPackage() != pkg->name || !pkg->id ||
- pkg->id.value() != context_->GetPackageId();
+ return context_->GetCompilationPackage() != pkg->name;
};
bool error = false;
@@ -1027,19 +1044,11 @@
bool VerifyNoIdsSet() {
for (const auto& package : final_table_.packages) {
for (const auto& type : package->types) {
- if (type->id) {
- context_->GetDiagnostics()->Error(DiagMessage() << "type " << type->type << " has ID "
- << StringPrintf("%02x", type->id.value())
- << " assigned");
- return false;
- }
-
for (const auto& entry : type->entries) {
if (entry->id) {
ResourceNameRef res_name(package->name, type->type, entry->name);
- context_->GetDiagnostics()->Error(
- DiagMessage() << "entry " << res_name << " has ID "
- << StringPrintf("%02x", entry->id.value()) << " assigned");
+ context_->GetDiagnostics()->Error(DiagMessage() << "resource " << res_name << " has ID "
+ << entry->id.value() << " assigned");
return false;
}
}
@@ -1313,12 +1322,17 @@
}
ResourceTable* table = apk->GetResourceTable();
- ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId);
- if (!pkg) {
- context_->GetDiagnostics()->Error(DiagMessage(input) << "static library has no package");
+ if (table->packages.empty()) {
+ return true;
+ }
+
+ auto lib_package_result = GetStaticLibraryPackage(table);
+ if (!lib_package_result.has_value()) {
+ context_->GetDiagnostics()->Error(DiagMessage(input) << lib_package_result.error());
return false;
}
+ ResourceTablePackage* pkg = lib_package_result.value();
bool result;
if (options_.no_static_lib_packages) {
// Merge all resources as if they were in the compilation package. This is the old behavior
@@ -1365,11 +1379,11 @@
res_name = mangled_name.value();
}
- std::unique_ptr<Id> id = util::make_unique<Id>();
+ auto id = util::make_unique<Id>();
id->SetSource(source.WithLine(exported_symbol.line));
- bool result =
- final_table_.AddResourceMangled(res_name, ConfigDescription::DefaultConfig(),
- std::string(), std::move(id), context_->GetDiagnostics());
+ bool result = final_table_.AddResource(
+ NewResourceBuilder(res_name).SetValue(std::move(id)).SetAllowMangled(true).Build(),
+ context_->GetDiagnostics());
if (!result) {
return false;
}
@@ -1750,7 +1764,7 @@
// anything else being generated, which includes the Java classes.
// If required, the package name is modifed before flattening, and then modified back
// to its original name.
- ResourceTablePackage* package_to_rewrite = nullptr;
+ std::optional<ResourceTablePackageView> package_to_rewrite;
// Pre-O, the platform treats negative resource IDs [those with a package ID of 0x80
// or higher] as invalid. In order to work around this limitation, we allow the use
// of traditionally reserved resource IDs [those between 0x02 and 0x7E]. Allow the
@@ -1764,10 +1778,11 @@
// The base APK is included, and this is a feature split. If the base package is
// the same as this package, then we are building an old style Android Instant Apps feature
// split and must apply this workaround to avoid requiring namespaces support.
- package_to_rewrite = table->FindPackage(context_->GetCompilationPackage());
- if (package_to_rewrite != nullptr) {
+ auto table_view = table->GetPartitionedView();
+ if (!table_view.packages.empty() &&
+ table_view.packages.back().name == context_->GetCompilationPackage()) {
+ package_to_rewrite = std::move(table_view.packages.back());
CHECK_EQ(1u, table->packages.size()) << "can't change name of package when > 1 package";
-
std::string new_package_name =
StringPrintf("%s.%s", package_to_rewrite->name.c_str(),
app_info_.split_name.value_or_default("feature").c_str());
@@ -1783,7 +1798,7 @@
bool success = FlattenTable(table, options_.output_format, writer);
- if (package_to_rewrite != nullptr) {
+ if (package_to_rewrite.has_value()) {
// Change the name back.
package_to_rewrite->name = context_->GetCompilationPackage();
if (package_to_rewrite->id) {
@@ -1925,8 +1940,7 @@
for (auto& entry : type->entries) {
ResourceName name(package->name, type->type, entry->name);
// The IDs are guaranteed to exist.
- options_.stable_id_map[std::move(name)] =
- ResourceId(package->id.value(), type->id.value(), entry->id.value());
+ options_.stable_id_map[std::move(name)] = entry->id.value();
}
}
}
diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp
index 73072a9..dfdac6b 100644
--- a/tools/aapt2/cmd/Link_test.cpp
+++ b/tools/aapt2/cmd/Link_test.cpp
@@ -25,6 +25,7 @@
using testing::Eq;
using testing::HasSubstr;
using testing::Ne;
+using testing::NotNull;
namespace aapt {
@@ -47,6 +48,8 @@
// Load the binary xml tree
android::ResXMLTree tree;
std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+ ASSERT_THAT(apk, Ne(nullptr));
+
std::unique_ptr<io::IData> data = OpenFileAsData(apk.get(), "res/xml/test.xml");
ASSERT_THAT(data, Ne(nullptr));
AssertLoadXml(apk.get(), data.get(), &tree);
@@ -73,6 +76,8 @@
// Load the binary xml tree
android::ResXMLTree tree;
std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+ ASSERT_THAT(apk, Ne(nullptr));
+
std::unique_ptr<io::IData> data = OpenFileAsData(apk.get(), "res/xml/test.xml");
ASSERT_THAT(data, Ne(nullptr));
AssertLoadXml(apk.get(), data.get(), &tree);
@@ -208,6 +213,8 @@
ASSERT_TRUE(Link(link_args, compiled_files_dir, &diag));
std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+ ASSERT_THAT(apk, Ne(nullptr));
+
const Style* actual_style = test::GetValue<Style>(
apk->GetResourceTable(), std::string(kDefaultPackageName) + ":style/MyStyle");
ASSERT_NE(actual_style, nullptr);
@@ -250,6 +257,8 @@
ASSERT_TRUE(Link(link_args, compiled_files_dir, &diag));
std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+ ASSERT_THAT(apk, Ne(nullptr));
+
const Style* actual_style = test::GetValue<Style>(
apk->GetResourceTable(), std::string(kDefaultPackageName) + ":style/MyStyle");
ASSERT_NE(actual_style, nullptr);
@@ -392,4 +401,127 @@
EXPECT_THAT(client_r_contents, HasSubstr(" com.example.lib.R.attr.foo, 0x7f010000"));
}
+TEST_F(LinkTest, StagedAndroidApi) {
+ StdErrDiagnostics diag;
+ const std::string android_values =
+ R"(<resources>
+ <public type="attr" name="finalized_res" id="0x01010001"/>
+
+ <!-- S staged attributes (support staged resources in the same type id) -->
+ <staging-public-group type="attr" first-id="0x01010050">
+ <public name="staged_s_res" />
+ </staging-public-group>
+
+ <!-- SV2 staged attributes (support staged resources in a separate type id) -->
+ <staging-public-group type="attr" first-id="0x01ff0049">
+ <public name="staged_s2_res" />
+ </staging-public-group>
+
+ <!-- T staged attributes (support staged resources in multiple separate type ids) -->
+ <staging-public-group type="attr" first-id="0x01fe0063">
+ <public name="staged_t_res" />
+ </staging-public-group>
+
+ <staging-public-group type="string" first-id="0x01fd0072">
+ <public name="staged_t_string" />
+ </staging-public-group>
+
+ <attr name="finalized_res" />
+ <attr name="staged_s_res" />
+ <attr name="staged_s2_res" />
+ <attr name="staged_t_res" />
+ <string name="staged_t_string">Hello</string>
+ </resources>)";
+
+ const std::string app_values =
+ R"(<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <attr name="bar" />
+ <declare-styleable name="ClientStyleable">
+ <attr name="android:finalized_res" />
+ <attr name="android:staged_s_res" />
+ <attr name="bar" />
+ </declare-styleable>
+ </resources>)";
+
+ const std::string android_res = GetTestPath("android-res");
+ ASSERT_TRUE(
+ CompileFile(GetTestPath("res/values/values.xml"), android_values, android_res, &diag));
+
+ const std::string android_apk = GetTestPath("android.apk");
+ const std::string android_java = GetTestPath("android_java");
+ // clang-format off
+ auto android_manifest = ManifestBuilder(this)
+ .SetPackageName("android")
+ .Build();
+
+ auto android_link_args = LinkCommandBuilder(this)
+ .SetManifestFile(android_manifest)
+ .AddParameter("--private-symbols", "com.android.internal")
+ .AddParameter("--java", android_java)
+ .AddCompiledResDir(android_res, &diag)
+ .Build(android_apk);
+ // clang-format on
+ ASSERT_TRUE(Link(android_link_args, &diag));
+
+ const std::string android_r_java = android_java + "/android/R.java";
+ std::string android_r_contents;
+ ASSERT_TRUE(android::base::ReadFileToString(android_r_java, &android_r_contents));
+ EXPECT_THAT(android_r_contents, HasSubstr(" public static final int finalized_res=0x01010001;"));
+ EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_s_res=0x01010050;"));
+ EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_s2_res=0x01ff0049;"));
+ EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_t_res=0x01fe0063;"));
+ EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_t_string=0x01fd0072;"));
+
+ // Build an app that uses the framework attribute in a declare-styleable
+ const std::string client_res = GetTestPath("app-res");
+ ASSERT_TRUE(CompileFile(GetTestPath("res/values/values.xml"), app_values, client_res, &diag));
+
+ const std::string app_apk = GetTestPath("app.apk");
+ const std::string app_java = GetTestPath("app_java");
+ // clang-format off
+ auto app_manifest = ManifestBuilder(this)
+ .SetPackageName("com.example.app")
+ .Build();
+
+ auto app_link_args = LinkCommandBuilder(this)
+ .SetManifestFile(app_manifest)
+ .AddParameter("--java", app_java)
+ .AddParameter("-I", android_apk)
+ .AddCompiledResDir(client_res, &diag)
+ .Build(app_apk);
+ // clang-format on
+ ASSERT_TRUE(Link(app_link_args, &diag));
+
+ const std::string client_r_java = app_java + "/com/example/app/R.java";
+ std::string client_r_contents;
+ ASSERT_TRUE(android::base::ReadFileToString(client_r_java, &client_r_contents));
+ EXPECT_THAT(client_r_contents, HasSubstr(" 0x01010001, android.R.attr.staged_s_res, 0x7f010000"));
+
+ // Test that the resource ids of staged and non-staged resource can be retrieved
+ android::AssetManager2 am;
+ auto android_asset = android::ApkAssets::Load(android_apk);
+ ASSERT_THAT(android_asset, NotNull());
+ ASSERT_TRUE(am.SetApkAssets({android_asset.get()}));
+
+ auto result = am.GetResourceId("android:attr/finalized_res");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(*result, Eq(0x01010001));
+
+ result = am.GetResourceId("android:attr/staged_s_res");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(*result, Eq(0x01010050));
+
+ result = am.GetResourceId("android:attr/staged_s2_res");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(*result, Eq(0x01ff0049));
+
+ result = am.GetResourceId("android:attr/staged_t_res");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(*result, Eq(0x01fe0063));
+
+ result = am.GetResourceId("android:string/staged_t_string");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_THAT(*result, Eq(0x01fd0072));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp
index 17c22c5..9a50b26 100644
--- a/tools/aapt2/compile/IdAssigner.cpp
+++ b/tools/aapt2/compile/IdAssigner.cpp
@@ -17,76 +17,135 @@
#include "compile/IdAssigner.h"
#include <map>
+#include <unordered_map>
+#include "android-base/expected.h"
#include "android-base/logging.h"
#include "ResourceTable.h"
#include "process/IResourceTableConsumer.h"
#include "util/Util.h"
+using android::base::expected;
+using android::base::unexpected;
+
namespace aapt {
-/**
- * Assigns the intended ID to the ResourceTablePackage, ResourceTableType, and
- * ResourceEntry,
- * as long as there is no existing ID or the ID is the same.
- */
-static bool AssignId(IDiagnostics* diag, const ResourceId& id,
- const ResourceName& name, ResourceTablePackage* pkg,
- ResourceTableType* type, ResourceEntry* entry) {
- if (pkg->id.value() == id.package_id()) {
- if (!type->id || type->id.value() == id.type_id()) {
- type->id = id.type_id();
+namespace {
+template <typename T>
+using Result = expected<T, std::string>;
- if (!entry->id || entry->id.value() == id.entry_id()) {
- entry->id = id.entry_id();
- return true;
- }
- }
+template <typename Id, typename Key>
+struct NextIdFinder {
+ explicit NextIdFinder(Id start_id = 0u) : next_id_(start_id){};
+
+ // Attempts to reserve an identifier for the specified key.
+ // If the identifier is already reserved by a different key, an error message is returned.
+ // Reserving identifiers must be completed before `NextId` is called for the first time.
+ Result<Id> ReserveId(Key key, Id id);
+
+ // Retrieves the next available identifier that has not been reserved.
+ std::optional<Id> NextId();
+
+ private:
+ // Attempts to set `next_id_` to the next available identifier that has not been reserved.
+ // Returns whether there were any available identifiers.
+ std::optional<Id> SkipToNextAvailableId();
+
+ Id next_id_;
+ bool next_id_called_ = false;
+ bool exhausted_ = false;
+ std::map<Id, Key> pre_assigned_ids_;
+ typename std::map<Id, Key>::iterator next_preassigned_id_;
+};
+
+struct TypeGroup {
+ explicit TypeGroup(uint8_t package_id, uint8_t type_id)
+ : package_id_(package_id), type_id_(type_id){};
+
+ // Attempts to reserve the resource id for the specified resource name.
+ // If the id is already reserved by a different name, an error message is returned.
+ // Reserving identifiers must be completed before `NextId` is called for the first time.
+ Result<std::monostate> ReserveId(const ResourceName& name, ResourceId id);
+
+ // Retrieves the next available resource id that has not been reserved.
+ Result<ResourceId> NextId();
+
+ private:
+ uint8_t package_id_;
+ uint8_t type_id_;
+ NextIdFinder<uint16_t, ResourceName> next_entry_id_;
+};
+
+struct ResourceTypeKey {
+ ResourceType type;
+ uint8_t id;
+
+ bool operator<(const ResourceTypeKey& other) const {
+ return (type != other.type) ? type < other.type : id < other.id;
}
- const ResourceId existing_id(pkg->id.value(), type->id ? type->id.value() : 0,
- entry->id ? entry->id.value() : 0);
- diag->Error(DiagMessage() << "can't assign ID " << id << " to resource "
- << name << " with conflicting ID " << existing_id);
- return false;
+ bool operator==(const ResourceTypeKey& other) const {
+ return type == other.type && id == other.id;
+ }
+
+ bool operator!=(const ResourceTypeKey& other) const {
+ return !(*this == other);
+ }
+};
+
+::std::ostream& operator<<(::std::ostream& out, const ResourceTypeKey& type) {
+ return out << type.type;
}
+struct IdAssignerContext {
+ IdAssignerContext(std::string package_name, uint8_t package_id)
+ : package_name_(std::move(package_name)), package_id_(package_id) {
+ }
+
+ // Attempts to reserve the resource id for the specified resource name.
+ // Returns whether the id was reserved successfully.
+ // Reserving identifiers must be completed before `NextId` is called for the first time.
+ bool ReserveId(const ResourceName& name, ResourceId id, const Visibility& visibility,
+ IDiagnostics* diag);
+
+ // Retrieves the next available resource id that has not been reserved.
+ std::optional<ResourceId> NextId(const ResourceName& name, IDiagnostics* diag);
+
+ private:
+ std::string package_name_;
+ uint8_t package_id_;
+ std::map<ResourceTypeKey, TypeGroup> types_;
+ std::map<ResourceType, uint8_t> non_staged_type_ids_;
+ NextIdFinder<uint8_t, ResourceTypeKey> type_id_finder_ =
+ NextIdFinder<uint8_t, ResourceTypeKey>(1);
+};
+
+} // namespace
+
bool IdAssigner::Consume(IAaptContext* context, ResourceTable* table) {
- std::map<ResourceId, ResourceName> assigned_ids;
-
+ IdAssignerContext assigned_ids(context->GetCompilationPackage(), context->GetPackageId());
for (auto& package : table->packages) {
- CHECK(bool(package->id)) << "packages must have manually assigned IDs";
-
for (auto& type : package->types) {
for (auto& entry : type->entries) {
const ResourceName name(package->name, type->type, entry->name);
+ if (entry->id) {
+ if (!assigned_ids.ReserveId(name, entry->id.value(), entry->visibility,
+ context->GetDiagnostics())) {
+ return false;
+ }
+ }
if (assigned_id_map_) {
// Assign the pre-assigned stable ID meant for this resource.
const auto iter = assigned_id_map_->find(name);
if (iter != assigned_id_map_->end()) {
const ResourceId assigned_id = iter->second;
- const bool result =
- AssignId(context->GetDiagnostics(), assigned_id, name,
- package.get(), type.get(), entry.get());
- if (!result) {
+ if (!assigned_ids.ReserveId(name, assigned_id, entry->visibility,
+ context->GetDiagnostics())) {
return false;
}
- }
- }
-
- if (package->id && type->id && entry->id) {
- // If the ID is set for this resource, then reserve it.
- ResourceId resource_id(package->id.value(), type->id.value(),
- entry->id.value());
- auto result = assigned_ids.insert({resource_id, name});
- const ResourceName& existing_name = result.first->second;
- if (!result.second) {
- context->GetDiagnostics()->Error(
- DiagMessage() << "resource " << name << " has same ID "
- << resource_id << " as " << existing_name);
- return false;
+ entry->id = assigned_id;
}
}
}
@@ -94,125 +153,185 @@
}
if (assigned_id_map_) {
- // Reserve all the IDs mentioned in the stable ID map. That way we won't
- // assign
- // IDs that were listed in the map if they don't exist in the table.
+ // Reserve all the IDs mentioned in the stable ID map. That way we won't assig IDs that were
+ // listed in the map if they don't exist in the table.
for (const auto& stable_id_entry : *assigned_id_map_) {
const ResourceName& pre_assigned_name = stable_id_entry.first;
const ResourceId& pre_assigned_id = stable_id_entry.second;
- auto result = assigned_ids.insert({pre_assigned_id, pre_assigned_name});
- const ResourceName& existing_name = result.first->second;
- if (!result.second && existing_name != pre_assigned_name) {
- context->GetDiagnostics()->Error(
- DiagMessage() << "stable ID " << pre_assigned_id << " for resource "
- << pre_assigned_name
- << " is already taken by resource " << existing_name);
+ if (!assigned_ids.ReserveId(pre_assigned_name, pre_assigned_id, {},
+ context->GetDiagnostics())) {
return false;
}
}
}
- // Assign any resources without IDs the next available ID. Gaps will be filled
- // if possible,
+ // Assign any resources without IDs the next available ID. Gaps will be filled if possible,
// unless those IDs have been reserved.
-
- const auto assigned_ids_iter_end = assigned_ids.end();
for (auto& package : table->packages) {
- CHECK(bool(package->id)) << "packages must have manually assigned IDs";
-
- // Build a half filled ResourceId object, which will be used to find the
- // closest matching
- // reserved ID in the assignedId map. From that point the next available
- // type ID can be
- // found.
- ResourceId resource_id(package->id.value(), 0, 0);
- uint8_t next_expected_type_id = 1;
-
- // Find the closest matching ResourceId that is <= the one with only the
- // package set.
- auto next_type_iter = assigned_ids.lower_bound(resource_id);
for (auto& type : package->types) {
- if (!type->id) {
- // We need to assign a type ID. Iterate over the reserved IDs until we
- // find
- // some type ID that is a distance of 2 greater than the last one we've
- // seen.
- // That means there is an available type ID between these reserved IDs.
- while (next_type_iter != assigned_ids_iter_end) {
- if (next_type_iter->first.package_id() != package->id.value()) {
- break;
- }
-
- const uint8_t type_id = next_type_iter->first.type_id();
- if (type_id > next_expected_type_id) {
- // There is a gap in the type IDs, so use the missing one.
- type->id = next_expected_type_id++;
- break;
- }
-
- // Set our expectation to be the next type ID after the reserved one
- // we
- // just saw.
- next_expected_type_id = type_id + 1;
-
- // Move to the next reserved ID.
- ++next_type_iter;
- }
-
- if (!type->id) {
- // We must have hit the end of the reserved IDs and not found a gap.
- // That means the next ID is available.
- type->id = next_expected_type_id++;
- }
- }
-
- resource_id = ResourceId(package->id.value(), type->id.value(), 0);
- uint16_t next_expected_entry_id = 0;
-
- // Find the closest matching ResourceId that is <= the one with only the
- // package
- // and type set.
- auto next_entry_iter = assigned_ids.lower_bound(resource_id);
for (auto& entry : type->entries) {
- if (!entry->id) {
- // We need to assign an entry ID. Iterate over the reserved IDs until
- // we find
- // some entry ID that is a distance of 2 greater than the last one
- // we've seen.
- // That means there is an available entry ID between these reserved
- // IDs.
- while (next_entry_iter != assigned_ids_iter_end) {
- if (next_entry_iter->first.package_id() != package->id.value() ||
- next_entry_iter->first.type_id() != type->id.value()) {
- break;
- }
-
- const uint16_t entry_id = next_entry_iter->first.entry_id();
- if (entry_id > next_expected_entry_id) {
- // There is a gap in the entry IDs, so use the missing one.
- entry->id = next_expected_entry_id++;
- break;
- }
-
- // Set our expectation to be the next type ID after the reserved one
- // we
- // just saw.
- next_expected_entry_id = entry_id + 1;
-
- // Move to the next reserved entry ID.
- ++next_entry_iter;
- }
-
- if (!entry->id) {
- // We must have hit the end of the reserved IDs and not found a gap.
- // That means the next ID is available.
- entry->id = next_expected_entry_id++;
- }
+ const ResourceName name(package->name, type->type, entry->name);
+ if (entry->id) {
+ continue;
}
+ auto id = assigned_ids.NextId(name, context->GetDiagnostics());
+ if (!id.has_value()) {
+ return false;
+ }
+ entry->id = id.value();
}
}
}
return true;
}
+namespace {
+template <typename Id, typename Key>
+Result<Id> NextIdFinder<Id, Key>::ReserveId(Key key, Id id) {
+ CHECK(!next_id_called_) << "ReserveId cannot be called after NextId";
+ auto assign_result = pre_assigned_ids_.emplace(id, key);
+ if (!assign_result.second && assign_result.first->second != key) {
+ std::stringstream error;
+ error << "ID is already assigned to " << assign_result.first->second;
+ return unexpected(error.str());
+ }
+ return id;
+}
+
+template <typename Id, typename Key>
+std::optional<Id> NextIdFinder<Id, Key>::NextId() {
+ if (!next_id_called_) {
+ next_id_called_ = true;
+ next_preassigned_id_ = pre_assigned_ids_.begin();
+ }
+ return SkipToNextAvailableId();
+}
+
+template <typename Id, typename Key>
+std::optional<Id> NextIdFinder<Id, Key>::SkipToNextAvailableId() {
+ if (exhausted_) {
+ return {};
+ }
+ while (next_preassigned_id_ != pre_assigned_ids_.end()) {
+ if (next_preassigned_id_->first == next_id_) {
+ if (next_id_ == std::numeric_limits<Id>::max()) {
+ // The last identifier was reserved so there are no more available identifiers.
+ exhausted_ = true;
+ return {};
+ }
+ ++next_id_;
+ ++next_preassigned_id_;
+ continue;
+ }
+ CHECK(next_preassigned_id_->first > next_id_) << "Preassigned IDs are not in sorted order";
+ break;
+ }
+ if (next_id_ == std::numeric_limits<Id>::max()) {
+ // There are no more identifiers after this one, but this one is still available so return it.
+ exhausted_ = true;
+ }
+ return next_id_++;
+}
+
+Result<std::monostate> TypeGroup::ReserveId(const ResourceName& name, ResourceId id) {
+ if (type_id_ != id.type_id()) {
+ // Currently there cannot be multiple type ids for a single type.
+ std::stringstream error;
+ error << "type '" << name.type << "' already has ID " << std::hex << (int)id.type_id();
+ return unexpected(error.str());
+ }
+
+ auto assign_result = next_entry_id_.ReserveId(name, id.entry_id());
+ if (!assign_result.has_value()) {
+ std::stringstream error;
+ error << "entry " << assign_result.error();
+ return unexpected(error.str());
+ }
+ return {};
+}
+
+Result<ResourceId> TypeGroup::NextId() {
+ auto entry_id = next_entry_id_.NextId();
+ if (!entry_id.has_value()) {
+ std::stringstream error;
+ error << "resource type ID has exceeded the maximum number of resource entries ("
+ << (std::numeric_limits<uint16_t>::max() + 1u) << ")";
+ return unexpected(error.str());
+ }
+ return ResourceId(package_id_, type_id_, entry_id.value());
+}
+
+bool IdAssignerContext::ReserveId(const ResourceName& name, ResourceId id,
+ const Visibility& visibility, IDiagnostics* diag) {
+ if (package_id_ != id.package_id()) {
+ diag->Error(DiagMessage() << "can't assign ID " << id << " to resource " << name
+ << " because package already has ID " << std::hex
+ << (int)id.package_id());
+ return false;
+ }
+
+ auto key = ResourceTypeKey{name.type, id.type_id()};
+ auto type = types_.find(key);
+ if (type == types_.end()) {
+ // The type has not been assigned an id yet. Ensure that the specified id is not being used by
+ // another type.
+ auto assign_result = type_id_finder_.ReserveId(key, id.type_id());
+ if (!assign_result.has_value()) {
+ diag->Error(DiagMessage() << "can't assign ID " << id << " to resource " << name
+ << " because type " << assign_result.error());
+ return false;
+ }
+ type = types_.emplace(key, TypeGroup(package_id_, id.type_id())).first;
+ }
+
+ if (!visibility.staged_api) {
+ // Ensure that non-staged resources can only exist in one type ID.
+ auto non_staged_type = non_staged_type_ids_.emplace(name.type, id.type_id());
+ if (!non_staged_type.second && non_staged_type.first->second != id.type_id()) {
+ diag->Error(DiagMessage() << "can't assign ID " << id << " to resource " << name
+ << " because type already has ID " << std::hex
+ << (int)id.type_id());
+ return false;
+ }
+ }
+
+ auto assign_result = type->second.ReserveId(name, id);
+ if (!assign_result.has_value()) {
+ diag->Error(DiagMessage() << "can't assign ID " << id << " to resource " << name << " because "
+ << assign_result.error());
+ return false;
+ }
+
+ return true;
+}
+
+std::optional<ResourceId> IdAssignerContext::NextId(const ResourceName& name, IDiagnostics* diag) {
+ // The package name is not known during the compile stage.
+ // Resources without a package name are considered a part of the app being linked.
+ CHECK(name.package.empty() || name.package == package_name_);
+
+ // Find the type id for non-staged resources of this type.
+ auto non_staged_type = non_staged_type_ids_.find(name.type);
+ if (non_staged_type == non_staged_type_ids_.end()) {
+ auto next_type_id = type_id_finder_.NextId();
+ CHECK(next_type_id.has_value()) << "resource type IDs allocated have exceeded maximum (256)";
+ non_staged_type = non_staged_type_ids_.emplace(name.type, *next_type_id).first;
+ }
+
+ ResourceTypeKey key{name.type, non_staged_type->second};
+ auto type = types_.find(key);
+ if (type == types_.end()) {
+ type = types_.emplace(key, TypeGroup(package_id_, key.id)).first;
+ }
+
+ auto assign_result = type->second.NextId();
+ if (!assign_result.has_value()) {
+ diag->Error(DiagMessage() << "can't assign resource ID to resource " << name << " because "
+ << assign_result.error());
+ return {};
+ }
+ return assign_result.value();
+}
+} // namespace
+
} // namespace aapt
diff --git a/tools/aapt2/compile/IdAssigner_test.cpp b/tools/aapt2/compile/IdAssigner_test.cpp
index 5cff004..6637766 100644
--- a/tools/aapt2/compile/IdAssigner_test.cpp
+++ b/tools/aapt2/compile/IdAssigner_test.cpp
@@ -20,42 +20,40 @@
namespace aapt {
+struct IdAssignerTests : public ::testing::Test {
+ void SetUp() override {
+ context = test::ContextBuilder().SetCompilationPackage("android").SetPackageId(0x01).Build();
+ }
+ std::unique_ptr<IAaptContext> context;
+};
+
::testing::AssertionResult VerifyIds(ResourceTable* table);
-TEST(IdAssignerTest, AssignIds) {
- std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
- .AddSimple("android:attr/foo")
- .AddSimple("android:attr/bar")
- .AddSimple("android:id/foo")
- .SetPackageId("android", 0x01)
- .Build();
-
- std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+TEST_F(IdAssignerTests, AssignIds) {
+ auto table = test::ResourceTableBuilder()
+ .AddSimple("android:attr/foo")
+ .AddSimple("android:attr/bar")
+ .AddSimple("android:id/foo")
+ .Build();
IdAssigner assigner;
ASSERT_TRUE(assigner.Consume(context.get(), table.get()));
ASSERT_TRUE(VerifyIds(table.get()));
}
-TEST(IdAssignerTest, AssignIdsWithReservedIds) {
- std::unique_ptr<ResourceTable> table =
- test::ResourceTableBuilder()
- .AddSimple("android:id/foo", ResourceId(0x01010000))
- .AddSimple("android:dimen/two")
- .AddSimple("android:integer/three")
- .AddSimple("android:string/five")
- .AddSimple("android:attr/fun", ResourceId(0x01040000))
- .AddSimple("android:attr/foo", ResourceId(0x01040006))
- .AddSimple("android:attr/bar")
- .AddSimple("android:attr/baz")
- .AddSimple("app:id/biz")
- .SetPackageId("android", 0x01)
- .SetPackageId("app", 0x7f)
- .Build();
+TEST_F(IdAssignerTests, AssignIdsWithReservedIds) {
+ auto table = test::ResourceTableBuilder()
+ .AddSimple("android:id/foo", ResourceId(0x01010000))
+ .AddSimple("android:dimen/two")
+ .AddSimple("android:integer/three")
+ .AddSimple("android:string/five")
+ .AddSimple("android:attr/fun", ResourceId(0x01040000))
+ .AddSimple("android:attr/foo", ResourceId(0x01040006))
+ .AddSimple("android:attr/bar")
+ .AddSimple("android:attr/baz")
+ .Build();
- std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
IdAssigner assigner;
-
ASSERT_TRUE(assigner.Consume(context.get(), table.get()));
ASSERT_TRUE(VerifyIds(table.get()));
@@ -65,12 +63,12 @@
maybe_result = table->FindResource(test::ParseNameOrDie("android:dimen/two"));
ASSERT_TRUE(maybe_result);
- EXPECT_EQ(make_value<uint8_t>(2), maybe_result.value().type->id);
+ EXPECT_EQ(make_value<ResourceId>(0x01020000), maybe_result.value().entry->id);
maybe_result =
table->FindResource(test::ParseNameOrDie("android:integer/three"));
ASSERT_TRUE(maybe_result);
- EXPECT_EQ(make_value<uint8_t>(3), maybe_result.value().type->id);
+ EXPECT_EQ(make_value<ResourceId>(0x01030000), maybe_result.value().entry->id);
// Expect to bypass the reserved 0x0104XXXX IDs and use the next 0x0105XXXX
// IDs.
@@ -78,107 +76,133 @@
maybe_result =
table->FindResource(test::ParseNameOrDie("android:string/five"));
ASSERT_TRUE(maybe_result);
- EXPECT_EQ(make_value<uint8_t>(5), maybe_result.value().type->id);
+ EXPECT_EQ(make_value<ResourceId>(0x01050000), maybe_result.value().entry->id);
// Expect to fill in the gaps between 0x01040000 and 0x01040006.
maybe_result = table->FindResource(test::ParseNameOrDie("android:attr/bar"));
ASSERT_TRUE(maybe_result);
- EXPECT_EQ(make_value<uint16_t>(1), maybe_result.value().entry->id);
+ EXPECT_EQ(make_value<ResourceId>(0x01040001), maybe_result.value().entry->id);
maybe_result = table->FindResource(test::ParseNameOrDie("android:attr/baz"));
ASSERT_TRUE(maybe_result);
- EXPECT_EQ(make_value<uint16_t>(2), maybe_result.value().entry->id);
+ EXPECT_EQ(make_value<ResourceId>(0x01040002), maybe_result.value().entry->id);
}
-TEST(IdAssignerTest, FailWhenNonUniqueIdsAssigned) {
- std::unique_ptr<ResourceTable> table =
- test::ResourceTableBuilder()
- .AddSimple("android:attr/foo", ResourceId(0x01040006))
- .AddSimple("android:attr/bar", ResourceId(0x01040006))
- .SetPackageId("android", 0x01)
- .SetPackageId("app", 0x7f)
- .Build();
-
- std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+TEST_F(IdAssignerTests, FailWhenNonUniqueIdsAssigned) {
+ auto table = test::ResourceTableBuilder()
+ .AddSimple("android:attr/foo", ResourceId(0x01040006))
+ .AddSimple("android:attr/bar", ResourceId(0x01040006))
+ .Build();
IdAssigner assigner;
-
ASSERT_FALSE(assigner.Consume(context.get(), table.get()));
}
-TEST(IdAssignerTest, AssignIdsWithIdMap) {
- std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
- .AddSimple("android:attr/foo")
- .AddSimple("android:attr/bar")
- .SetPackageId("android", 0x01)
- .Build();
+TEST_F(IdAssignerTests, FailWhenNonUniqueTypeIdsAssigned) {
+ auto table = test::ResourceTableBuilder()
+ .AddSimple("android:string/foo", ResourceId(0x01040000))
+ .AddSimple("android:attr/bar", ResourceId(0x01040006))
+ .Build();
+ IdAssigner assigner;
+ ASSERT_FALSE(assigner.Consume(context.get(), table.get()));
+}
- std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+TEST_F(IdAssignerTests, FailWhenTypeHasTwoNonStagedIds) {
+ auto table = test::ResourceTableBuilder()
+ .AddSimple("android:attr/foo", ResourceId(0x01050000))
+ .AddSimple("android:attr/bar", ResourceId(0x01040006))
+ .Build();
+ IdAssigner assigner;
+ ASSERT_FALSE(assigner.Consume(context.get(), table.get()));
+}
+
+TEST_F(IdAssignerTests, FailWhenTypeHasTwoNonStagedIdsRegardlessOfStagedId) {
+ auto table = test::ResourceTableBuilder()
+ .AddSimple("android:attr/foo", ResourceId(0x01050000))
+ .AddSimple("android:attr/bar", ResourceId(0x01ff0006))
+ .Add(NewResourceBuilder("android:attr/staged_baz")
+ .SetId(0x01ff0000)
+ .SetVisibility({.staged_api = true})
+ .Build())
+ .Build();
+ IdAssigner assigner;
+ ASSERT_FALSE(assigner.Consume(context.get(), table.get()));
+}
+
+TEST_F(IdAssignerTests, AssignIdsWithIdMap) {
+ auto table = test::ResourceTableBuilder()
+ .AddSimple("android:attr/foo")
+ .AddSimple("android:attr/bar")
+ .Build();
std::unordered_map<ResourceName, ResourceId> id_map = {
{test::ParseNameOrDie("android:attr/foo"), ResourceId(0x01010002)}};
IdAssigner assigner(&id_map);
ASSERT_TRUE(assigner.Consume(context.get(), table.get()));
ASSERT_TRUE(VerifyIds(table.get()));
- Maybe<ResourceTable::SearchResult> result =
- table->FindResource(test::ParseNameOrDie("android:attr/foo"));
+ auto result = table->FindResource(test::ParseNameOrDie("android:attr/foo"));
ASSERT_TRUE(result);
const ResourceTable::SearchResult& search_result = result.value();
- EXPECT_EQ(make_value<uint8_t>(0x01), search_result.package->id);
- EXPECT_EQ(make_value<uint8_t>(0x01), search_result.type->id);
- EXPECT_EQ(make_value<uint16_t>(0x0002), search_result.entry->id);
+ EXPECT_EQ(make_value<ResourceId>(0x01010002), search_result.entry->id);
+}
+
+TEST_F(IdAssignerTests, UseAllEntryIds) {
+ ResourceTable table;
+ const size_t max_entry_id = std::numeric_limits<uint16_t>::max();
+ for (size_t i = 0; i <= max_entry_id; i++) {
+ ASSERT_TRUE(
+ table.AddResource(NewResourceBuilder("android:attr/res" + std::to_string(i)).Build(),
+ context->GetDiagnostics()));
+ }
+ IdAssigner assigner;
+ ASSERT_TRUE(assigner.Consume(context.get(), &table));
+}
+
+TEST_F(IdAssignerTests, ExaustEntryIds) {
+ ResourceTable table;
+ const size_t max_entry_id = std::numeric_limits<uint16_t>::max() + 1u;
+ for (size_t i = 0; i <= max_entry_id; i++) {
+ ASSERT_TRUE(
+ table.AddResource(NewResourceBuilder("android:attr/res" + std::to_string(i)).Build(),
+ context->GetDiagnostics()));
+ }
+ IdAssigner assigner;
+ ASSERT_FALSE(assigner.Consume(context.get(), &table));
+}
+
+TEST_F(IdAssignerTests, ExaustEntryIdsLastIdIsPublic) {
+ ResourceTable table;
+ ASSERT_TRUE(table.AddResource(NewResourceBuilder("android:attr/res").SetId(0x0101ffff).Build(),
+ context->GetDiagnostics()));
+ const size_t max_entry_id = std::numeric_limits<uint16_t>::max();
+ for (size_t i = 0; i <= max_entry_id; i++) {
+ ASSERT_TRUE(
+ table.AddResource(NewResourceBuilder("android:attr/res" + std::to_string(i)).Build(),
+ context->GetDiagnostics()));
+ }
+ IdAssigner assigner;
+ ASSERT_FALSE(assigner.Consume(context.get(), &table));
}
::testing::AssertionResult VerifyIds(ResourceTable* table) {
- std::set<uint8_t> package_ids;
+ std::set<ResourceId> seen_ids;
for (auto& package : table->packages) {
- if (!package->id) {
- return ::testing::AssertionFailure() << "package " << package->name
- << " has no ID";
- }
-
- if (!package_ids.insert(package->id.value()).second) {
- return ::testing::AssertionFailure()
- << "package " << package->name << " has non-unique ID " << std::hex
- << (int)package->id.value() << std::dec;
- }
- }
-
- for (auto& package : table->packages) {
- std::set<uint8_t> type_ids;
for (auto& type : package->types) {
- if (!type->id) {
- return ::testing::AssertionFailure() << "type " << type->type
- << " of package " << package->name
- << " has no ID";
- }
-
- if (!type_ids.insert(type->id.value()).second) {
- return ::testing::AssertionFailure()
- << "type " << type->type << " of package " << package->name
- << " has non-unique ID " << std::hex << (int)type->id.value()
- << std::dec;
- }
- }
-
- for (auto& type : package->types) {
- std::set<uint16_t> entry_ids;
for (auto& entry : type->entries) {
if (!entry->id) {
return ::testing::AssertionFailure()
- << "entry " << entry->name << " of type " << type->type
- << " of package " << package->name << " has no ID";
+ << "resource " << ResourceNameRef(package->name, type->type, entry->name)
+ << " has no ID";
}
-
- if (!entry_ids.insert(entry->id.value()).second) {
+ if (!seen_ids.insert(entry->id.value()).second) {
return ::testing::AssertionFailure()
- << "entry " << entry->name << " of type " << type->type
- << " of package " << package->name << " has non-unique ID "
- << std::hex << (int)entry->id.value() << std::dec;
+ << "resource " << ResourceNameRef(package->name, type->type, entry->name)
+ << " has a non-unique ID" << std::hex << entry->id.value() << std::dec;
}
}
}
}
+
return ::testing::AssertionSuccess() << "all IDs are unique and assigned";
}
diff --git a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
index e816c86..432d7bf 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
@@ -236,13 +236,14 @@
TEST(PseudolocaleGeneratorTest, PluralsArePseudolocalized) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
- std::unique_ptr<ResourceTable> table =
- test::ResourceTableBuilder().SetPackageId("com.pkg", 0x7F).Build();
+ std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder().Build();
std::unique_ptr<Plural> plural = util::make_unique<Plural>();
plural->values = {util::make_unique<String>(table->string_pool.MakeRef("zero")),
util::make_unique<String>(table->string_pool.MakeRef("one"))};
- ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("com.pkg:plurals/foo"), ConfigDescription{},
- {}, std::move(plural), context->GetDiagnostics()));
+ ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.pkg:plurals/foo"))
+ .SetValue(std::move(plural))
+ .Build(),
+ context->GetDiagnostics()));
std::unique_ptr<Plural> expected = util::make_unique<Plural>();
expected->values = {util::make_unique<String>(table->string_pool.MakeRef("[žéŕö one]")),
util::make_unique<String>(table->string_pool.MakeRef("[öñé one]"))};
@@ -252,6 +253,7 @@
const auto* actual = test::GetValueForConfig<Plural>(table.get(), "com.pkg:plurals/foo",
test::ParseConfigOrDie("en-rXA"));
+ ASSERT_NE(nullptr, actual);
EXPECT_TRUE(actual->Equals(expected.get()));
}
@@ -273,11 +275,14 @@
auto string = util::make_unique<String>(table->string_pool.MakeRef(original_style.str));
string->untranslatable_sections.push_back(UntranslatableSection{6u, 11u});
- ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("android:string/foo"), ConfigDescription{},
- {} /* product */, std::move(styled_string),
+ ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("android:string/foo"))
+ .SetValue(std::move(styled_string))
+ .Build(),
context->GetDiagnostics()));
- ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("android:string/bar"), ConfigDescription{},
- {} /* product */, std::move(string), context->GetDiagnostics()));
+ ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("android:string/bar"))
+ .SetValue(std::move(string))
+ .Build(),
+ context->GetDiagnostics()));
}
PseudolocaleGenerator generator;
diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp
index cc1cf7f..f29c918 100644
--- a/tools/aapt2/dump/DumpManifest.cpp
+++ b/tools/aapt2/dump/DumpManifest.cpp
@@ -191,18 +191,14 @@
const ConfigDescription& config = DefaultConfig()) {
if (table) {
for (auto& package : table->packages) {
- if (package->id && package->id.value() == res_id.package_id()) {
for (auto& type : package->types) {
- if (type->id && type->id.value() == res_id.type_id()) {
- for (auto& entry : type->entries) {
- if (entry->id && entry->id.value() == res_id.entry_id()) {
- if (auto value = BestConfigValue(entry.get(), config)) {
- return value;
- }
+ for (auto& entry : type->entries) {
+ if (entry->id && entry->id.value() == res_id.id) {
+ if (auto value = BestConfigValue(entry.get(), config)) {
+ return value;
}
}
}
- }
}
}
}
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index cccd9fa..bfb8d58 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -192,8 +192,7 @@
std::u16string package_name = strcpy16_dtoh((const char16_t*)package_header->name,
arraysize(package_header->name));
- ResourceTablePackage* package =
- table_->CreatePackage(util::Utf16ToUtf8(package_name), static_cast<uint8_t>(package_id));
+ ResourceTablePackage* package = table_->FindOrCreatePackage(util::Utf16ToUtf8(package_name));
if (!package) {
diag_->Error(DiagMessage(source_)
<< "incompatible package '" << package_name << "' with ID " << package_id);
@@ -232,13 +231,13 @@
break;
case android::RES_TABLE_TYPE_SPEC_TYPE:
- if (!ParseTypeSpec(package, parser.chunk())) {
+ if (!ParseTypeSpec(package, parser.chunk(), package_id)) {
return false;
}
break;
case android::RES_TABLE_TYPE_TYPE:
- if (!ParseType(package, parser.chunk())) {
+ if (!ParseType(package, parser.chunk(), package_id)) {
return false;
}
break;
@@ -276,7 +275,7 @@
}
bool BinaryResourceParser::ParseTypeSpec(const ResourceTablePackage* package,
- const ResChunk_header* chunk) {
+ const ResChunk_header* chunk, uint8_t package_id) {
if (type_pool_.getError() != NO_ERROR) {
diag_->Error(DiagMessage(source_) << "missing type string pool");
return false;
@@ -317,14 +316,14 @@
const uint32_t* type_spec_flags = reinterpret_cast<const uint32_t*>(
reinterpret_cast<uintptr_t>(type_spec) + util::DeviceToHost16(type_spec->header.headerSize));
for (size_t i = 0; i < entry_count; i++) {
- ResourceId id(package->id.value_or_default(0x0), type_spec->id, static_cast<size_t>(i));
+ ResourceId id(package_id, type_spec->id, static_cast<size_t>(i));
entry_type_spec_flags_[id] = util::DeviceToHost32(type_spec_flags[i]);
}
return true;
}
bool BinaryResourceParser::ParseType(const ResourceTablePackage* package,
- const ResChunk_header* chunk) {
+ const ResChunk_header* chunk, uint8_t package_id) {
if (type_pool_.getError() != NO_ERROR) {
diag_->Error(DiagMessage(source_) << "missing type string pool");
return false;
@@ -354,13 +353,9 @@
const std::string type_str = util::GetString(type_pool_, type->id - 1);
const ResourceType* parsed_type = ParseResourceType(type_str);
if (!parsed_type) {
- // Be lenient on the name of the type if the table is lenient on resource validation.
- bool log_error = table_->GetValidateResources();
- if (log_error) {
- diag_->Error(DiagMessage(source_) << "invalid type name '" << type_str
- << "' for type with ID " << type->id);
- }
- return !log_error;
+ diag_->Warn(DiagMessage(source_)
+ << "invalid type name '" << type_str << "' for type with ID " << type->id);
+ return true;
}
TypeVariant tv(type);
@@ -372,7 +367,7 @@
const ResourceName name(package->name, *parsed_type,
util::GetString(key_pool_, util::DeviceToHost32(entry->key.index)));
- const ResourceId res_id(package->id.value(), type->id, static_cast<uint16_t>(it.index()));
+ const ResourceId res_id(package_id, type->id, static_cast<uint16_t>(it.index()));
std::unique_ptr<Value> resource_value;
if (entry->flags & ResTable_entry::FLAG_COMPLEX) {
@@ -392,17 +387,13 @@
return false;
}
- if (!table_->AddResourceWithIdMangled(name, res_id, config, {}, std::move(resource_value),
- diag_)) {
- return false;
- }
+ NewResourceBuilder res_builder(name);
+ res_builder.SetValue(std::move(resource_value), config)
+ .SetId(res_id, OnIdConflict::CREATE_ENTRY)
+ .SetAllowMangled(true);
if (entry->flags & ResTable_entry::FLAG_PUBLIC) {
- Visibility visibility;
- visibility.level = Visibility::Level::kPublic;
- if (!table_->SetVisibilityWithIdMangled(name, visibility, res_id, diag_)) {
- return false;
- }
+ res_builder.SetVisibility(Visibility{Visibility::Level::kPublic});
// Erase the ID from the map once processed, so that we don't mark the same symbol more than
// once.
@@ -415,6 +406,10 @@
if (cache_iter == id_index_.end()) {
id_index_.insert({res_id, name});
}
+
+ if (!table_->AddResource(res_builder.Build(), diag_)) {
+ return false;
+ }
}
return true;
}
@@ -472,7 +467,12 @@
OverlayableItem overlayable_item(overlayable);
overlayable_item.policies = policy_header->policy_flags;
- if (!table_->SetOverlayable(iter->second, overlayable_item, diag_)) {
+ if (!table_->AddResource(NewResourceBuilder(iter->second)
+ .SetId(res_id, OnIdConflict::CREATE_ENTRY)
+ .SetOverlayable(std::move(overlayable_item))
+ .SetAllowMangled(true)
+ .Build(),
+ diag_)) {
return false;
}
}
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.h b/tools/aapt2/format/binary/BinaryResourceParser.h
index a2eee50..13dd982 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.h
+++ b/tools/aapt2/format/binary/BinaryResourceParser.h
@@ -51,8 +51,10 @@
bool ParseTable(const android::ResChunk_header* chunk);
bool ParsePackage(const android::ResChunk_header* chunk);
- bool ParseTypeSpec(const ResourceTablePackage* package, const android::ResChunk_header* chunk);
- bool ParseType(const ResourceTablePackage* package, const android::ResChunk_header* chunk);
+ bool ParseTypeSpec(const ResourceTablePackage* package, const android::ResChunk_header* chunk,
+ uint8_t package_id);
+ bool ParseType(const ResourceTablePackage* package, const android::ResChunk_header* chunk,
+ uint8_t package_id);
bool ParseLibrary(const android::ResChunk_header* chunk);
bool ParseOverlayable(const android::ResChunk_header* chunk);
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 4b90b4f..17d11a6 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -59,35 +59,35 @@
dst[i] = 0;
}
-static bool cmp_style_entries(const Style::Entry& a, const Style::Entry& b) {
- if (a.key.id) {
- if (b.key.id) {
- return cmp_ids_dynamic_after_framework(a.key.id.value(), b.key.id.value());
+static bool cmp_style_entries(const Style::Entry* a, const Style::Entry* b) {
+ if (a->key.id) {
+ if (b->key.id) {
+ return cmp_ids_dynamic_after_framework(a->key.id.value(), b->key.id.value());
}
return true;
- } else if (!b.key.id) {
- return a.key.name.value() < b.key.name.value();
+ } else if (!b->key.id) {
+ return a->key.name.value() < b->key.name.value();
}
return false;
}
struct FlatEntry {
- ResourceEntry* entry;
- Value* value;
+ const ResourceEntry* entry;
+ const Value* value;
// The entry string pool index to the entry's name.
uint32_t entry_key;
};
-class MapFlattenVisitor : public ValueVisitor {
+class MapFlattenVisitor : public ConstValueVisitor {
public:
- using ValueVisitor::Visit;
+ using ConstValueVisitor::Visit;
MapFlattenVisitor(ResTable_entry_ext* out_entry, BigBuffer* buffer)
: out_entry_(out_entry), buffer_(buffer) {
}
- void Visit(Attribute* attr) override {
+ void Visit(const Attribute* attr) override {
{
Reference key = Reference(ResourceId(ResTable_map::ATTR_TYPE));
BinaryPrimitive val(Res_value::TYPE_INT_DEC, attr->type_mask);
@@ -106,13 +106,13 @@
FlattenEntry(&key, &val);
}
- for (Attribute::Symbol& s : attr->symbols) {
+ for (const Attribute::Symbol& s : attr->symbols) {
BinaryPrimitive val(s.type, s.value);
FlattenEntry(&s.symbol, &val);
}
}
- void Visit(Style* style) override {
+ void Visit(const Style* style) override {
if (style->parent) {
const Reference& parent_ref = style->parent.value();
CHECK(bool(parent_ref.id)) << "parent has no ID";
@@ -120,21 +120,26 @@
}
// Sort the style.
- std::sort(style->entries.begin(), style->entries.end(), cmp_style_entries);
+ std::vector<const Style::Entry*> sorted_entries;
+ for (const auto& entry : style->entries) {
+ sorted_entries.emplace_back(&entry);
+ }
- for (Style::Entry& entry : style->entries) {
- FlattenEntry(&entry.key, entry.value.get());
+ std::sort(sorted_entries.begin(), sorted_entries.end(), cmp_style_entries);
+
+ for (const Style::Entry* entry : sorted_entries) {
+ FlattenEntry(&entry->key, entry->value.get());
}
}
- void Visit(Styleable* styleable) override {
+ void Visit(const Styleable* styleable) override {
for (auto& attr_ref : styleable->entries) {
BinaryPrimitive val(Res_value{});
FlattenEntry(&attr_ref, &val);
}
}
- void Visit(Array* array) override {
+ void Visit(const Array* array) override {
const size_t count = array->elements.size();
for (size_t i = 0; i < count; i++) {
Reference key(android::ResTable_map::ATTR_MIN + i);
@@ -142,7 +147,7 @@
}
}
- void Visit(Plural* plural) override {
+ void Visit(const Plural* plural) override {
const size_t count = plural->values.size();
for (size_t i = 0; i < count; i++) {
if (!plural->values[i]) {
@@ -196,16 +201,16 @@
private:
DISALLOW_COPY_AND_ASSIGN(MapFlattenVisitor);
- void FlattenKey(Reference* key, ResTable_map* out_entry) {
+ void FlattenKey(const Reference* key, ResTable_map* out_entry) {
CHECK(bool(key->id)) << "key has no ID";
out_entry->name.ident = util::HostToDevice32(key->id.value().id);
}
- void FlattenValue(Item* value, ResTable_map* out_entry) {
+ void FlattenValue(const Item* value, ResTable_map* out_entry) {
CHECK(value->Flatten(&out_entry->value)) << "flatten failed";
}
- void FlattenEntry(Reference* key, Item* value) {
+ void FlattenEntry(const Reference* key, Item* value) {
ResTable_map* out_entry = buffer_->NextBlock<ResTable_map>();
FlattenKey(key, out_entry);
FlattenValue(value, out_entry);
@@ -226,7 +231,7 @@
class PackageFlattener {
public:
- PackageFlattener(IAaptContext* context, ResourceTablePackage* package,
+ PackageFlattener(IAaptContext* context, const ResourceTablePackageView& package,
const std::map<size_t, std::string>* shared_libs, bool use_sparse_entries,
bool collapse_key_stringpool,
const std::set<ResourceName>& name_collapse_exemptions)
@@ -243,20 +248,20 @@
TRACE_CALL();
ChunkWriter pkg_writer(buffer);
ResTable_package* pkg_header = pkg_writer.StartChunk<ResTable_package>(RES_TABLE_PACKAGE_TYPE);
- pkg_header->id = util::HostToDevice32(package_->id.value());
+ pkg_header->id = util::HostToDevice32(package_.id.value());
// AAPT truncated the package name, so do the same.
// Shared libraries require full package names, so don't truncate theirs.
if (context_->GetPackageType() != PackageType::kApp &&
- package_->name.size() >= arraysize(pkg_header->name)) {
- diag_->Error(DiagMessage() << "package name '" << package_->name
+ package_.name.size() >= arraysize(pkg_header->name)) {
+ diag_->Error(DiagMessage() << "package name '" << package_.name
<< "' is too long. "
"Shared libraries cannot have truncated package names");
return false;
}
// Copy the package name in device endianness.
- strcpy16_htod(pkg_header->name, arraysize(pkg_header->name), util::Utf8ToUtf16(package_->name));
+ strcpy16_htod(pkg_header->name, arraysize(pkg_header->name), util::Utf8ToUtf16(package_.name));
// Serialize the types. We do this now so that our type and key strings
// are populated. We write those first.
@@ -273,7 +278,7 @@
buffer->AppendBuffer(std::move(type_buffer));
// If there are libraries (or if the package ID is 0x00), encode a library chunk.
- if (package_->id.value() == 0x00 || !shared_libs_->empty()) {
+ if (package_.id.value() == 0x00 || !shared_libs_->empty()) {
FlattenLibrarySpec(buffer);
}
@@ -315,7 +320,7 @@
}
bool FlattenValue(FlatEntry* entry, BigBuffer* buffer) {
- if (Item* item = ValueCast<Item>(entry->value)) {
+ if (const Item* item = ValueCast<Item>(entry->value)) {
WriteEntry<ResTable_entry, true>(entry, buffer);
Res_value* outValue = buffer->NextBlock<Res_value>();
CHECK(item->Flatten(outValue)) << "flatten failed";
@@ -329,7 +334,7 @@
return true;
}
- bool FlattenConfig(const ResourceTableType* type, const ConfigDescription& config,
+ bool FlattenConfig(const ResourceTableTypeView& type, const ConfigDescription& config,
const size_t num_total_entries, std::vector<FlatEntry>* entries,
BigBuffer* buffer) {
CHECK(num_total_entries != 0);
@@ -337,7 +342,7 @@
ChunkWriter type_writer(buffer);
ResTable_type* type_header = type_writer.StartChunk<ResTable_type>(RES_TABLE_TYPE_TYPE);
- type_header->id = type->id.value();
+ type_header->id = type.id.value();
type_header->config = config;
type_header->config.swapHtoD();
@@ -346,12 +351,12 @@
BigBuffer values_buffer(512);
for (FlatEntry& flat_entry : *entries) {
- CHECK(static_cast<size_t>(flat_entry.entry->id.value()) < num_total_entries);
- offsets[flat_entry.entry->id.value()] = values_buffer.size();
+ CHECK(static_cast<size_t>(flat_entry.entry->id.value().entry_id()) < num_total_entries);
+ offsets[flat_entry.entry->id.value().entry_id()] = values_buffer.size();
if (!FlattenValue(&flat_entry, &values_buffer)) {
diag_->Error(DiagMessage()
<< "failed to flatten resource '"
- << ResourceNameRef(package_->name, type->type, flat_entry.entry->name)
+ << ResourceNameRef(package_.name, type.type, flat_entry.entry->name)
<< "' for configuration '" << config << "'");
return false;
}
@@ -399,55 +404,27 @@
return true;
}
- std::vector<ResourceTableType*> CollectAndSortTypes() {
- std::vector<ResourceTableType*> sorted_types;
- for (auto& type : package_->types) {
- if (type->type == ResourceType::kStyleable) {
- // Styleables aren't real Resource Types, they are represented in the
- // R.java file.
- continue;
- }
-
- CHECK(bool(type->id)) << "type must have an ID set";
-
- sorted_types.push_back(type.get());
- }
- std::sort(sorted_types.begin(), sorted_types.end(), cmp_ids<ResourceTableType>);
- return sorted_types;
- }
-
- std::vector<ResourceEntry*> CollectAndSortEntries(ResourceTableType* type) {
- // Sort the entries by entry ID.
- std::vector<ResourceEntry*> sorted_entries;
- for (auto& entry : type->entries) {
- CHECK(bool(entry->id)) << "entry must have an ID set";
- sorted_entries.push_back(entry.get());
- }
- std::sort(sorted_entries.begin(), sorted_entries.end(), cmp_ids<ResourceEntry>);
- return sorted_entries;
- }
-
bool FlattenOverlayable(BigBuffer* buffer) {
std::set<ResourceId> seen_ids;
std::map<std::string, OverlayableChunk> overlayable_chunks;
- CHECK(bool(package_->id)) << "package must have an ID set when flattening <overlayable>";
- for (auto& type : package_->types) {
- CHECK(bool(type->id)) << "type must have an ID set when flattening <overlayable>";
- for (auto& entry : type->entries) {
- CHECK(bool(type->id)) << "entry must have an ID set when flattening <overlayable>";
+ CHECK(bool(package_.id)) << "package must have an ID set when flattening <overlayable>";
+ for (auto& type : package_.types) {
+ CHECK(bool(type.id)) << "type must have an ID set when flattening <overlayable>";
+ for (auto& entry : type.entries) {
+ CHECK(bool(type.id)) << "entry must have an ID set when flattening <overlayable>";
if (!entry->overlayable_item) {
continue;
}
- OverlayableItem& item = entry->overlayable_item.value();
+ const OverlayableItem& item = entry->overlayable_item.value();
// Resource ids should only appear once in the resource table
- ResourceId id = android::make_resid(package_->id.value(), type->id.value(),
- entry->id.value());
+ ResourceId id =
+ android::make_resid(package_.id.value(), type.id.value(), entry->id.value().entry_id());
CHECK(seen_ids.find(id) == seen_ids.end())
<< "multiple overlayable definitions found for resource "
- << ResourceName(package_->name, type->type, entry->name).to_string();
+ << ResourceName(package_.name, type.type, entry->name).to_string();
seen_ids.insert(id);
// Find the overlayable chunk with the specified name
@@ -542,14 +519,14 @@
return true;
}
- bool FlattenTypeSpec(ResourceTableType* type, std::vector<ResourceEntry*>* sorted_entries,
- BigBuffer* buffer) {
+ bool FlattenTypeSpec(const ResourceTableTypeView& type,
+ const std::vector<const ResourceEntry*>& sorted_entries, BigBuffer* buffer) {
ChunkWriter type_spec_writer(buffer);
ResTable_typeSpec* spec_header =
type_spec_writer.StartChunk<ResTable_typeSpec>(RES_TABLE_TYPE_SPEC_TYPE);
- spec_header->id = type->id.value();
+ spec_header->id = type.id.value();
- if (sorted_entries->empty()) {
+ if (sorted_entries.empty()) {
type_spec_writer.Finish();
return true;
}
@@ -557,7 +534,7 @@
// We can't just take the size of the vector. There may be holes in the
// entry ID space.
// Since the entries are sorted by ID, the last one will be the biggest.
- const size_t num_entries = sorted_entries->back()->id.value() + 1;
+ const size_t num_entries = sorted_entries.back()->id.value().entry_id() + 1;
spec_header->entryCount = util::HostToDevice32(num_entries);
@@ -565,21 +542,23 @@
// show for which configuration axis the resource changes.
uint32_t* config_masks = type_spec_writer.NextBlock<uint32_t>(num_entries);
- const size_t actual_num_entries = sorted_entries->size();
- for (size_t entryIndex = 0; entryIndex < actual_num_entries; entryIndex++) {
- ResourceEntry* entry = sorted_entries->at(entryIndex);
+ for (const ResourceEntry* entry : sorted_entries) {
+ const uint16_t entry_id = entry->id.value().entry_id();
// Populate the config masks for this entry.
+ uint32_t& entry_config_masks = config_masks[entry_id];
if (entry->visibility.level == Visibility::Level::kPublic) {
- config_masks[entry->id.value()] |= util::HostToDevice32(ResTable_typeSpec::SPEC_PUBLIC);
+ entry_config_masks |= util::HostToDevice32(ResTable_typeSpec::SPEC_PUBLIC);
+ }
+ if (entry->visibility.staged_api) {
+ entry_config_masks |= util::HostToDevice32(ResTable_typeSpec::SPEC_STAGED_API);
}
const size_t config_count = entry->values.size();
for (size_t i = 0; i < config_count; i++) {
const ConfigDescription& config = entry->values[i]->config;
for (size_t j = i + 1; j < config_count; j++) {
- config_masks[entry->id.value()] |=
- util::HostToDevice32(config.diff(entry->values[j]->config));
+ config_masks[entry_id] |= util::HostToDevice32(config.diff(entry->values[j]->config));
}
}
}
@@ -590,32 +569,31 @@
bool FlattenTypes(BigBuffer* buffer) {
// Sort the types by their IDs. They will be inserted into the StringPool in
// this order.
- std::vector<ResourceTableType*> sorted_types = CollectAndSortTypes();
size_t expected_type_id = 1;
- for (ResourceTableType* type : sorted_types) {
+ for (const ResourceTableTypeView& type : package_.types) {
+ if (type.type == ResourceType::kStyleable) {
+ // Styleables aren't real Resource Types, they are represented in the R.java file.
+ continue;
+ }
+
// If there is a gap in the type IDs, fill in the StringPool
// with empty values until we reach the ID we expect.
- while (type->id.value() > expected_type_id) {
+ while (type.id.value() > expected_type_id) {
std::stringstream type_name;
type_name << "?" << expected_type_id;
type_pool_.MakeRef(type_name.str());
expected_type_id++;
}
expected_type_id++;
- type_pool_.MakeRef(to_string(type->type));
+ type_pool_.MakeRef(to_string(type.type));
- std::vector<ResourceEntry*> sorted_entries = CollectAndSortEntries(type);
- if (sorted_entries.empty()) {
- continue;
- }
-
- if (!FlattenTypeSpec(type, &sorted_entries, buffer)) {
+ if (!FlattenTypeSpec(type, type.entries, buffer)) {
return false;
}
// Since the entries are sorted by ID, the last ID will be the largest.
- const size_t num_entries = sorted_entries.back()->id.value() + 1;
+ const size_t num_entries = type.entries.back()->id.value().entry_id() + 1;
// The binary resource table lists resource entries for each
// configuration.
@@ -628,9 +606,9 @@
// hardcoded string uses characters which make it an invalid resource name
const std::string obfuscated_resource_name = "0_resource_name_obfuscated";
- for (ResourceEntry* entry : sorted_entries) {
+ for (const ResourceEntry* entry : type.entries) {
uint32_t local_key_index;
- ResourceName resource_name({}, type->type, entry->name);
+ ResourceName resource_name({}, type.type, entry->name);
if (!collapse_key_stringpool_ ||
name_collapse_exemptions_.find(resource_name) != name_collapse_exemptions_.end()) {
local_key_index = (uint32_t)key_pool_.MakeRef(entry->name).index();
@@ -660,17 +638,17 @@
ResTable_lib_header* lib_header =
lib_writer.StartChunk<ResTable_lib_header>(RES_TABLE_LIBRARY_TYPE);
- const size_t num_entries = (package_->id.value() == 0x00 ? 1 : 0) + shared_libs_->size();
+ const size_t num_entries = (package_.id.value() == 0x00 ? 1 : 0) + shared_libs_->size();
CHECK(num_entries > 0);
lib_header->count = util::HostToDevice32(num_entries);
ResTable_lib_entry* lib_entry = buffer->NextBlock<ResTable_lib_entry>(num_entries);
- if (package_->id.value() == 0x00) {
+ if (package_.id.value() == 0x00) {
// Add this package
lib_entry->packageId = util::HostToDevice32(0x00);
strcpy16_htod(lib_entry->packageName, arraysize(lib_entry->packageName),
- util::Utf8ToUtf16(package_->name));
+ util::Utf8ToUtf16(package_.name));
++lib_entry;
}
@@ -685,7 +663,7 @@
IAaptContext* context_;
IDiagnostics* diag_;
- ResourceTablePackage* package_;
+ const ResourceTablePackageView package_;
const std::map<size_t, std::string>* shared_libs_;
bool use_sparse_entries_;
StringPool type_pool_;
@@ -709,9 +687,10 @@
});
// Write the ResTable header.
+ const auto& table_view = table->GetPartitionedView();
ChunkWriter table_writer(buffer_);
ResTable_header* table_header = table_writer.StartChunk<ResTable_header>(RES_TABLE_TYPE);
- table_header->packageCount = util::HostToDevice32(table->packages.size());
+ table_header->packageCount = util::HostToDevice32(table_view.packages.size());
// Flatten the values string pool.
StringPool::FlattenUtf8(table_writer.buffer(), table->string_pool,
@@ -720,24 +699,25 @@
BigBuffer package_buffer(1024);
// Flatten each package.
- for (auto& package : table->packages) {
+ for (auto& package : table_view.packages) {
if (context->GetPackageType() == PackageType::kApp) {
// Write a self mapping entry for this package if the ID is non-standard (0x7f).
- const uint8_t package_id = package->id.value();
+ CHECK((bool)package.id) << "Resource ids have not been assigned before flattening the table";
+ const uint8_t package_id = package.id.value();
if (package_id != kFrameworkPackageId && package_id != kAppPackageId) {
- auto result = table->included_packages_.insert({package_id, package->name});
- if (!result.second && result.first->second != package->name) {
+ auto result = table->included_packages_.insert({package_id, package.name});
+ if (!result.second && result.first->second != package.name) {
// A mapping for this package ID already exists, and is a different package. Error!
context->GetDiagnostics()->Error(
DiagMessage() << android::base::StringPrintf(
"can't map package ID %02x to '%s'. Already mapped to '%s'", package_id,
- package->name.c_str(), result.first->second.c_str()));
+ package.name.c_str(), result.first->second.c_str()));
return false;
}
}
}
- PackageFlattener flattener(context, package.get(), &table->included_packages_,
+ PackageFlattener flattener(context, package, &table->included_packages_,
options_.use_sparse_entries, options_.collapse_key_stringpool,
options_.name_collapse_exemptions);
if (!flattener.FlattenPackage(&package_buffer)) {
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index f8b8a1c..f5fe5e3 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -155,7 +155,6 @@
TEST_F(TableFlattenerTest, FlattenFullyLinkedTable) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddSimple("com.app.test:id/one", ResourceId(0x7f020000))
.AddSimple("com.app.test:id/two", ResourceId(0x7f020001))
.AddValue("com.app.test:id/three", ResourceId(0x7f020002),
@@ -204,7 +203,6 @@
TEST_F(TableFlattenerTest, FlattenEntriesWithGapsInIds) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddSimple("com.app.test:id/one", ResourceId(0x7f020001))
.AddSimple("com.app.test:id/three", ResourceId(0x7f020003))
.Build();
@@ -225,7 +223,6 @@
attr.max_int = 23;
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddValue("android:attr/foo", ResourceId(0x01010000), util::make_unique<Attribute>(attr))
.Build();
@@ -248,7 +245,6 @@
2u));
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddValue("android:array/foo", ResourceId(0x01010000), std::move(array))
.Build();
@@ -300,7 +296,6 @@
IAaptContext* context, const ConfigDescription& sparse_config, float load) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId(context->GetCompilationPackage(), context->GetPackageId())
.Build();
// Add regular entries.
@@ -311,15 +306,20 @@
const ResourceId resid(context->GetPackageId(), 0x02, static_cast<uint16_t>(i));
const auto value =
util::make_unique<BinaryPrimitive>(Res_value::TYPE_INT_DEC, static_cast<uint32_t>(i));
- CHECK(table->AddResourceWithId(name, resid, ConfigDescription::DefaultConfig(), "",
- std::unique_ptr<Value>(value->Clone(nullptr)),
- context->GetDiagnostics()));
+ CHECK(table->AddResource(NewResourceBuilder(name)
+ .SetId(resid)
+ .SetValue(std::unique_ptr<Value>(value->Clone(nullptr)))
+ .Build(),
+ context->GetDiagnostics()));
// Every few entries, write out a sparse_config value. This will give us the desired load.
if (i % stride == 0) {
- CHECK(table->AddResourceWithId(name, resid, sparse_config, "",
- std::unique_ptr<Value>(value->Clone(nullptr)),
- context->GetDiagnostics()));
+ CHECK(table->AddResource(
+ NewResourceBuilder(name)
+ .SetId(resid)
+ .SetValue(std::unique_ptr<Value>(value->Clone(nullptr)), sparse_config)
+ .Build(),
+ context->GetDiagnostics()));
}
}
return table;
@@ -417,7 +417,6 @@
test::ContextBuilder().SetCompilationPackage("lib").SetPackageId(0x00).Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("lib", 0x00)
.AddValue("lib:id/foo", ResourceId(0x00010000), util::make_unique<Id>())
.Build();
ResourceTable result;
@@ -426,7 +425,7 @@
Maybe<ResourceTable::SearchResult> search_result =
result.FindResource(test::ParseNameOrDie("lib:id/foo"));
ASSERT_TRUE(search_result);
- EXPECT_EQ(0x00u, search_result.value().package->id.value());
+ EXPECT_EQ(0x00u, search_result.value().entry->id.value().package_id());
auto iter = result.included_packages_.find(0x00);
ASSERT_NE(result.included_packages_.end(), iter);
@@ -438,7 +437,6 @@
test::ContextBuilder().SetCompilationPackage("lib").SetPackageId(0x00).Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("lib", 0x00)
.AddValue("lib:style/Theme",
ResourceId(0x00030001),
test::StyleBuilder()
@@ -458,9 +456,7 @@
Maybe<ResourceTable::SearchResult> search_result =
result.FindResource(test::ParseNameOrDie("lib:style/Theme"));
ASSERT_TRUE(search_result);
- EXPECT_EQ(0x00u, search_result.value().package->id.value());
- EXPECT_EQ(0x03u, search_result.value().type->id.value());
- EXPECT_EQ(0x01u, search_result.value().entry->id.value());
+ EXPECT_EQ(0x00030001u, search_result.value().entry->id.value());
ASSERT_EQ(1u, search_result.value().entry->values.size());
Value* value = search_result.value().entry->values[0]->value.get();
Style* style = ValueCast<Style>(value);
@@ -479,7 +475,6 @@
test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x7f).Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("app", 0x7f)
.AddValue("app:id/foo", ResourceId(0x7f010000),
test::BuildReference("lib_one:id/foo", ResourceId(0x02010000)))
.AddValue("app:id/bar", ResourceId(0x7f010001),
@@ -509,7 +504,6 @@
std::unique_ptr<IAaptContext> context =
test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x80).Build();
std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
- .SetPackageId("app", 0x80)
.AddSimple("app:id/foo", ResourceId(0x80010000))
.Build();
@@ -532,7 +526,6 @@
test::ContextBuilder().SetCompilationPackage(kPackageName).SetPackageId(0x7f).Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId(kPackageName, 0x7f)
.AddSimple(kPackageName + ":id/foo", ResourceId(0x7f010000))
.Build();
@@ -553,7 +546,6 @@
.Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId(kPackageName, 0x7f)
.AddSimple(kPackageName + ":id/foo", ResourceId(0x7f010000))
.Build();
@@ -564,7 +556,6 @@
TEST_F(TableFlattenerTest, ObfuscatingResourceNamesNoNameCollapseExemptionsSucceeds) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddSimple("com.app.test:id/one", ResourceId(0x7f020000))
.AddSimple("com.app.test:id/two", ResourceId(0x7f020001))
.AddValue("com.app.test:id/three", ResourceId(0x7f020002),
@@ -618,7 +609,6 @@
TEST_F(TableFlattenerTest, ObfuscatingResourceNamesWithNameCollapseExemptionsSucceeds) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddSimple("com.app.test:id/one", ResourceId(0x7f020000))
.AddSimple("com.app.test:id/two", ResourceId(0x7f020001))
.AddValue("com.app.test:id/three", ResourceId(0x7f020002),
@@ -680,7 +670,6 @@
std::string name = "com.app.test:integer/overlayable";
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddSimple(name, ResourceId(0x7f020000))
.SetOverlayable(name, overlayable_item)
.Build();
@@ -717,7 +706,6 @@
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddSimple(name_zero, ResourceId(0x7f020000))
.SetOverlayable(name_zero, overlayable_item_zero)
.AddSimple(name_one, ResourceId(0x7f020001))
@@ -780,7 +768,6 @@
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddSimple(name_zero, ResourceId(0x7f020000))
.SetOverlayable(name_zero, overlayable_item_zero)
.AddSimple(name_one, ResourceId(0x7f020001))
@@ -842,7 +829,6 @@
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddSimple(name_zero, ResourceId(0x7f020000))
.SetOverlayable(name_zero, overlayable_item_zero)
.Build();
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 06ac9e5..498d5a2 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -425,15 +425,9 @@
io::IFileCollection* files,
const std::vector<std::shared_ptr<Overlayable>>& overlayables,
ResourceTable* out_table, std::string* out_error) {
- Maybe<uint8_t> id;
- if (pb_package.has_package_id()) {
- id = static_cast<uint8_t>(pb_package.package_id().id());
- }
-
std::map<ResourceId, ResourceNameRef> id_index;
- ResourceTablePackage* pkg =
- out_table->CreatePackageAllowingDuplicateNames(pb_package.package_name(), id);
+ ResourceTablePackage* pkg = out_table->FindOrCreatePackage(pb_package.package_name());
for (const pb::Type& pb_type : pb_package.type()) {
const ResourceType* res_type = ParseResourceType(pb_type.name());
if (res_type == nullptr) {
@@ -444,17 +438,15 @@
}
ResourceTableType* type = pkg->FindOrCreateType(*res_type);
- if (pb_type.has_type_id()) {
- type->id = static_cast<uint8_t>(pb_type.type_id().id());
- }
for (const pb::Entry& pb_entry : pb_type.entry()) {
- ResourceEntry* entry;
- if (pb_entry.has_entry_id()) {
- auto entry_id = static_cast<uint16_t>(pb_entry.entry_id().id());
- entry = type->FindOrCreateEntry(pb_entry.name(), entry_id);
- } else {
- entry = type->FindOrCreateEntry(pb_entry.name());
+ ResourceEntry* entry = type->CreateEntry(pb_entry.name());
+ const ResourceId resource_id(
+ pb_package.has_package_id() ? static_cast<uint8_t>(pb_package.package_id().id()) : 0u,
+ pb_type.has_type_id() ? static_cast<uint8_t>(pb_type.type_id().id()) : 0u,
+ pb_entry.has_entry_id() ? static_cast<uint16_t>(pb_entry.entry_id().id()) : 0u);
+ if (resource_id.id != 0u) {
+ entry->id = resource_id;
}
// Deserialize the symbol status (public/private with source and comments).
@@ -464,6 +456,7 @@
DeserializeSourceFromPb(pb_visibility.source(), src_pool, &entry->visibility.source);
}
entry->visibility.comment = pb_visibility.comment();
+ entry->visibility.staged_api = pb_visibility.staged_api();
const Visibility::Level level = DeserializeVisibilityFromPb(pb_visibility.level());
entry->visibility.level = level;
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 98c5175..f13f82d 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -345,28 +345,29 @@
pb_fingerprint->set_version(util::GetToolFingerprint());
std::vector<Overlayable*> overlayables;
- for (const std::unique_ptr<ResourceTablePackage>& package : table.packages) {
+ auto table_view = table.GetPartitionedView();
+ for (const auto& package : table_view.packages) {
pb::Package* pb_package = out_table->add_package();
- if (package->id) {
- pb_package->mutable_package_id()->set_id(package->id.value());
+ if (package.id) {
+ pb_package->mutable_package_id()->set_id(package.id.value());
}
- pb_package->set_package_name(package->name);
+ pb_package->set_package_name(package.name);
- for (const std::unique_ptr<ResourceTableType>& type : package->types) {
+ for (const auto& type : package.types) {
pb::Type* pb_type = pb_package->add_type();
- if (type->id) {
- pb_type->mutable_type_id()->set_id(type->id.value());
+ if (type.id) {
+ pb_type->mutable_type_id()->set_id(type.id.value());
}
- pb_type->set_name(to_string(type->type).to_string());
+ pb_type->set_name(to_string(type.type).to_string());
// hardcoded string uses characters which make it an invalid resource name
static const char* obfuscated_resource_name = "0_resource_name_obfuscated";
- for (const std::unique_ptr<ResourceEntry>& entry : type->entries) {
+ for (const auto& entry : type.entries) {
pb::Entry* pb_entry = pb_type->add_entry();
if (entry->id) {
- pb_entry->mutable_entry_id()->set_id(entry->id.value());
+ pb_entry->mutable_entry_id()->set_id(entry->id.value().entry_id());
}
- ResourceName resource_name({}, type->type, entry->name);
+ ResourceName resource_name({}, type.type, entry->name);
if (options.collapse_key_stringpool &&
options.name_collapse_exemptions.find(resource_name) ==
options.name_collapse_exemptions.end()) {
@@ -377,6 +378,7 @@
// Write the Visibility struct.
pb::Visibility* pb_visibility = pb_entry->mutable_visibility();
+ pb_visibility->set_staged_api(entry->visibility.staged_api);
pb_visibility->set_level(SerializeVisibilityToPb(entry->visibility.level));
if (source_pool != nullptr) {
SerializeSourceToPb(entry->visibility.source, source_pool.get(),
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index fe4c8aa..591ba149 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -40,18 +40,67 @@
MOCK_METHOD0(GetDirSeparator, char());
};
-ResourceEntry* GetEntry(ResourceTable* table, const ResourceNameRef& res_name,
- uint32_t id) {
- ResourceTablePackage* package = table->FindPackage(res_name.package);
- ResourceTableType* type = package->FindType(res_name.type);
- return type->FindEntry(res_name.entry, id);
+ResourceEntry* GetEntry(ResourceTable* table, const ResourceNameRef& res_name) {
+ auto result = table->FindResource(res_name);
+ return (result) ? result.value().entry : nullptr;
+}
+
+ResourceEntry* GetEntry(ResourceTable* table, const ResourceNameRef& res_name, ResourceId id) {
+ auto result = table->FindResource(res_name, id);
+ return (result) ? result.value().entry : nullptr;
+}
+
+TEST(ProtoSerializeTest, SerializeVisibility) {
+ std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+ std::unique_ptr<ResourceTable> table =
+ test::ResourceTableBuilder()
+ .Add(NewResourceBuilder("com.app.a:bool/foo")
+ .SetVisibility({Visibility::Level::kUndefined})
+ .Build())
+ .Add(NewResourceBuilder("com.app.a:bool/bar")
+ .SetVisibility({Visibility::Level::kPrivate})
+ .Build())
+ .Add(NewResourceBuilder("com.app.a:bool/baz")
+ .SetVisibility({Visibility::Level::kPublic})
+ .Build())
+ .Add(NewResourceBuilder("com.app.a:bool/fiz")
+ .SetVisibility({.level = Visibility::Level::kPublic, .staged_api = true})
+ .Build())
+ .Build();
+
+ ResourceTable new_table;
+ pb::ResourceTable pb_table;
+ MockFileCollection files;
+ std::string error;
+ SerializeTableToPb(*table, &pb_table, context->GetDiagnostics());
+ ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
+ EXPECT_THAT(error, IsEmpty());
+
+ auto search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/foo"));
+ ASSERT_TRUE(search_result);
+ EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
+ EXPECT_FALSE(search_result.value().entry->visibility.staged_api);
+
+ search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/bar"));
+ ASSERT_TRUE(search_result);
+ EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kPrivate));
+ EXPECT_FALSE(search_result.value().entry->visibility.staged_api);
+
+ search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz"));
+ ASSERT_TRUE(search_result);
+ EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kPublic));
+ EXPECT_FALSE(search_result.value().entry->visibility.staged_api);
+
+ search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/fiz"));
+ ASSERT_TRUE(search_result);
+ EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kPublic));
+ EXPECT_TRUE(search_result.value().entry->visibility.staged_api);
}
TEST(ProtoSerializeTest, SerializeSinglePackage) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.AddFileReference("com.app.a:layout/main", ResourceId(0x7f020000), "res/layout/main.xml")
.AddReference("com.app.a:layout/other", ResourceId(0x7f020001), "com.app.a:layout/main")
.AddString("com.app.a:string/text", {}, "hi")
@@ -60,11 +109,11 @@
true /*allow_new*/)
.Build();
- Visibility public_symbol;
- public_symbol.level = Visibility::Level::kPublic;
- ASSERT_TRUE(table->SetVisibilityWithId(test::ParseNameOrDie("com.app.a:layout/main"),
- public_symbol, ResourceId(0x7f020000),
- context->GetDiagnostics()));
+ ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:layout/main"))
+ .SetId(0x7f020000)
+ .SetVisibility({Visibility::Level::kPublic})
+ .Build(),
+ context->GetDiagnostics()));
Id* id = test::GetValue<Id>(table.get(), "com.app.a:id/foo");
ASSERT_THAT(id, NotNull());
@@ -72,25 +121,35 @@
// Make a plural.
std::unique_ptr<Plural> plural = util::make_unique<Plural>();
plural->values[Plural::One] = util::make_unique<String>(table->string_pool.MakeRef("one"));
- ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("com.app.a:plurals/hey"), ConfigDescription{},
- {}, std::move(plural), context->GetDiagnostics()));
+ ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:plurals/hey"))
+ .SetValue(std::move(plural))
+ .Build(),
+ context->GetDiagnostics()));
// Make a styled string.
StyleString style_string;
style_string.str = "hello";
style_string.spans.push_back(Span{"b", 0u, 4u});
- ASSERT_TRUE(
- table->AddResource(test::ParseNameOrDie("com.app.a:string/styled"), ConfigDescription{}, {},
- util::make_unique<StyledString>(table->string_pool.MakeRef(style_string)),
- context->GetDiagnostics()));
+ ASSERT_TRUE(table->AddResource(
+ NewResourceBuilder(test::ParseNameOrDie("com.app.a:string/styled"))
+ .SetValue(util::make_unique<StyledString>(table->string_pool.MakeRef(style_string)))
+ .Build(),
+ context->GetDiagnostics()));
// Make a resource with different products.
- ASSERT_TRUE(table->AddResource(
- test::ParseNameOrDie("com.app.a:integer/one"), test::ParseConfigOrDie("land"), {},
- test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 123u), context->GetDiagnostics()));
- ASSERT_TRUE(table->AddResource(
- test::ParseNameOrDie("com.app.a:integer/one"), test::ParseConfigOrDie("land"), "tablet",
- test::BuildPrimitive(android::Res_value::TYPE_INT_HEX, 321u), context->GetDiagnostics()));
+ ASSERT_TRUE(
+ table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:integer/one"))
+ .SetValue(test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 123u),
+ test::ParseConfigOrDie("land"))
+ .Build(),
+ context->GetDiagnostics()));
+
+ ASSERT_TRUE(
+ table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:integer/one"))
+ .SetValue(test::BuildPrimitive(android::Res_value::TYPE_INT_HEX, 321u),
+ test::ParseConfigOrDie("land"), "tablet")
+ .Build(),
+ context->GetDiagnostics()));
// Make a reference with both resource name and resource ID.
// The reference should point to a resource outside of this table to test that both name and id
@@ -98,16 +157,20 @@
Reference expected_ref;
expected_ref.name = test::ParseNameOrDie("android:layout/main");
expected_ref.id = ResourceId(0x01020000);
- ASSERT_TRUE(table->AddResource(
- test::ParseNameOrDie("com.app.a:layout/abc"), ConfigDescription::DefaultConfig(), {},
- util::make_unique<Reference>(expected_ref), context->GetDiagnostics()));
+ ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:layout/abc"))
+ .SetValue(util::make_unique<Reference>(expected_ref))
+ .Build(),
+ context->GetDiagnostics()));
// Make an overlayable resource.
OverlayableItem overlayable_item(std::make_shared<Overlayable>(
"OverlayableName", "overlay://theme", Source("res/values/overlayable.xml", 40)));
overlayable_item.source = Source("res/values/overlayable.xml", 42);
- ASSERT_TRUE(table->SetOverlayable(test::ParseNameOrDie("com.app.a:integer/overlayable"),
- overlayable_item, test::GetDiagnostics()));
+ ASSERT_TRUE(
+ table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.app.a:integer/overlayable"))
+ .SetOverlayable(overlayable_item)
+ .Build(),
+ context->GetDiagnostics()));
pb::ResourceTable pb_table;
SerializeTableToPb(*table, &pb_table, context->GetDiagnostics());
@@ -680,7 +743,6 @@
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddSimple("com.app.test:id/one", ResourceId(id_one_id))
.AddSimple("com.app.test:id/two", ResourceId(id_two_id))
.AddValue("com.app.test:id/three", ResourceId(id_three_id),
@@ -714,7 +776,7 @@
ResourceName real_id_resource(
"com.app.test", ResourceType::kId, "one");
- EXPECT_THAT(GetEntry(&new_table, real_id_resource, id_one_id), IsNull());
+ EXPECT_THAT(GetEntry(&new_table, real_id_resource), IsNull());
ResourceName obfuscated_id_resource(
"com.app.test", ResourceType::kId, "0_resource_name_obfuscated");
@@ -767,7 +829,6 @@
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddSimple("com.app.test:id/one", ResourceId(id_one_id))
.AddSimple("com.app.test:id/two", ResourceId(id_two_id))
.AddValue("com.app.test:id/three", ResourceId(id_three_id),
diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h
index 995495a..d3648c8 100644
--- a/tools/aapt2/java/ClassDefinition.h
+++ b/tools/aapt2/java/ClassDefinition.h
@@ -59,8 +59,9 @@
template <typename T>
class PrimitiveMember : public ClassMember {
public:
- PrimitiveMember(const android::StringPiece& name, const T& val)
- : name_(name.to_string()), val_(val) {}
+ PrimitiveMember(const android::StringPiece& name, const T& val, bool staged_api = false)
+ : name_(name.to_string()), val_(val), staged_api_(staged_api) {
+ }
bool empty() const override {
return false;
@@ -77,7 +78,7 @@
ClassMember::Print(final, printer, strip_api_annotations);
printer->Print("public static ");
- if (final) {
+ if (final && !staged_api_) {
printer->Print("final ");
}
printer->Print("int ").Print(name_).Print("=").Print(to_string(val_)).Print(";");
@@ -88,14 +89,16 @@
std::string name_;
T val_;
+ bool staged_api_;
};
// Specialization for strings so they get the right type and are quoted with "".
template <>
class PrimitiveMember<std::string> : public ClassMember {
public:
- PrimitiveMember(const android::StringPiece& name, const std::string& val)
- : name_(name.to_string()), val_(val) {}
+ PrimitiveMember(const android::StringPiece& name, const std::string& val, bool staged_api = false)
+ : name_(name.to_string()), val_(val) {
+ }
bool empty() const override {
return false;
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 59dd481..e1e2e01 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -460,7 +460,8 @@
const std::string field_name = TransformToFieldName(name.entry);
if (out_class_def != nullptr) {
- auto resource_member = util::make_unique<ResourceMember>(field_name, real_id);
+ auto resource_member =
+ util::make_unique<ResourceMember>(field_name, real_id, entry.visibility.staged_api);
// Build the comments and annotations for this entry.
AnnotationProcessor* processor = resource_member->GetCommentBuilder();
@@ -542,8 +543,8 @@
// Create an ID if there is one (static libraries don't need one).
ResourceId id;
- if (package.id && type.id && entry->id) {
- id = ResourceId(package.id.value(), type.id.value(), entry->id.value());
+ if (entry->id) {
+ id = entry->id.value();
}
// We need to make sure we hide the fact that we are generating kAttrPrivate attributes.
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index ec5b415..8bb3ee9 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -34,7 +34,6 @@
TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddSimple("android:id/class", ResourceId(0x01020000))
.Build();
@@ -54,7 +53,6 @@
TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddSimple("android:id/hey-man", ResourceId(0x01020000))
.AddValue("android:attr/cool.attr", ResourceId(0x01010000),
test::AttributeBuilder().Build())
@@ -84,7 +82,6 @@
TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddSimple("android:id/one", ResourceId(0x01020000))
.AddSimple("android:id/com.foo$two", ResourceId(0x01020001))
.Build();
@@ -110,8 +107,6 @@
TEST(JavaClassGeneratorTest, StyleableAttributesWithDifferentPackageName) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
- .SetPackageId("app", 0x7f)
.AddValue("app:attr/foo", ResourceId(0x7f010000),
test::AttributeBuilder().Build())
.AddValue("app:attr/bar", ResourceId(0x7f010001),
@@ -159,7 +154,6 @@
TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddSimple("android:attr/two", ResourceId(0x01010001))
.AddSimple("android:^attr-private/one", ResourceId(0x01010000))
.Build();
@@ -184,7 +178,6 @@
StdErrDiagnostics diag;
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddSimple("android:id/one", ResourceId(0x01020000))
.AddSimple("android:id/two", ResourceId(0x01020001))
.AddSimple("android:id/three", ResourceId(0x01020002))
@@ -276,8 +269,6 @@
TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
- .SetPackageId("com.lib", 0x02)
.AddValue("android:attr/bar", ResourceId(0x01010000), test::AttributeBuilder().Build())
.AddValue("com.lib:attr/bar", ResourceId(0x02010000), test::AttributeBuilder().Build())
.AddValue("android:styleable/foo", ResourceId(0x01030000),
@@ -306,7 +297,6 @@
TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddSimple("android:id/foo", ResourceId(0x01010000))
.Build();
test::GetValue<Id>(table.get(), "android:id/foo")
@@ -346,7 +336,6 @@
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddValue("android:attr/one", util::make_unique<Attribute>(attr))
.AddValue("android:styleable/Container",
std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
@@ -384,7 +373,6 @@
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddValue("android:attr/one", util::make_unique<Attribute>(attr))
.AddValue("android:styleable/Container",
std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
@@ -415,7 +403,6 @@
TEST(JavaClassGeneratorTest, StyleableAndIndicesAreColocated) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddValue("android:attr/layout_gravity", util::make_unique<Attribute>())
.AddValue("android:attr/background", util::make_unique<Attribute>())
.AddValue("android:styleable/ActionBar",
@@ -467,7 +454,6 @@
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddValue("android:attr/one", util::make_unique<Attribute>(attr))
.Build();
@@ -499,7 +485,6 @@
TEST(JavaClassGeneratorTest, GenerateOnResourcesLoadedCallbackForSharedLibrary) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x00)
.AddValue("android:attr/foo", ResourceId(0x00010000), util::make_unique<Attribute>())
.AddValue("android:id/foo", ResourceId(0x00020000), util::make_unique<Id>())
.AddValue(
@@ -536,7 +521,6 @@
TEST(JavaClassGeneratorTest, OnlyGenerateRText) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddValue("android:attr/foo", ResourceId(0x01010000), util::make_unique<Attribute>())
.AddValue("android:styleable/hey.dude", ResourceId(0x01020000),
test::StyleableBuilder()
@@ -554,8 +538,6 @@
TEST(JavaClassGeneratorTest, SortsDynamicAttributesAfterFrameworkAttributes) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
- .SetPackageId("lib", 0x00)
.AddValue("android:attr/framework_attr", ResourceId(0x01010000),
test::AttributeBuilder().Build())
.AddValue("lib:attr/dynamic_attr", ResourceId(0x00010000),
diff --git a/tools/aapt2/java/ProguardRules_test.cpp b/tools/aapt2/java/ProguardRules_test.cpp
index c7ae0b6..b7dfec3 100644
--- a/tools/aapt2/java/ProguardRules_test.cpp
+++ b/tools/aapt2/java/ProguardRules_test.cpp
@@ -247,8 +247,10 @@
ResourceTable table;
StdErrDiagnostics errDiagnostics;
- table.AddResource(bar_layout->file.name, ConfigDescription::DefaultConfig(), "",
- util::make_unique<FileReference>(), &errDiagnostics);
+ table.AddResource(NewResourceBuilder(bar_layout->file.name)
+ .SetValue(util::make_unique<FileReference>())
+ .Build(),
+ &errDiagnostics);
std::unique_ptr<IAaptContext> context =
test::ContextBuilder()
diff --git a/tools/aapt2/link/AutoVersioner_test.cpp b/tools/aapt2/link/AutoVersioner_test.cpp
index 1117472..02fd00b 100644
--- a/tools/aapt2/link/AutoVersioner_test.cpp
+++ b/tools/aapt2/link/AutoVersioner_test.cpp
@@ -54,7 +54,6 @@
TEST(AutoVersionerTest, VersionStylesForTable) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("app", 0x7f)
.AddValue(
"app:style/Foo", test::ParseConfigOrDie("v4"),
ResourceId(0x7f020000),
diff --git a/tools/aapt2/link/NoDefaultResourceRemover_test.cpp b/tools/aapt2/link/NoDefaultResourceRemover_test.cpp
index d129c9a..3179fef 100644
--- a/tools/aapt2/link/NoDefaultResourceRemover_test.cpp
+++ b/tools/aapt2/link/NoDefaultResourceRemover_test.cpp
@@ -21,10 +21,9 @@
namespace aapt {
TEST(NoDefaultResourceRemoverTest, RemoveEntryWithNoDefaultAndOnlyLocales) {
- std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+ std::unique_ptr<IAaptContext> context = test::ContextBuilder().SetPackageId(0x01).Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddSimple("android:string/foo")
.AddSimple("android:string/foo", test::ParseConfigOrDie("en-rGB"))
.AddSimple("android:string/foo", test::ParseConfigOrDie("fr-rFR"))
@@ -47,10 +46,10 @@
}
TEST(NoDefaultResourceRemoverTest, KeepEntryWithLocalesAndDensities) {
- std::unique_ptr<IAaptContext> context = test::ContextBuilder().SetMinSdkVersion(26).Build();
+ std::unique_ptr<IAaptContext> context =
+ test::ContextBuilder().SetPackageId(0x01).SetMinSdkVersion(26).Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddSimple("android:drawable/keep1", test::ParseConfigOrDie("mdpi")) // v4
.AddSimple("android:drawable/keep1", test::ParseConfigOrDie("en-rGB"))
.AddSimple("android:drawable/keep1", test::ParseConfigOrDie("fr-rFR"))
@@ -71,10 +70,10 @@
}
TEST(NoDefaultResourceRemoverTest, RemoveEntryWithLocalesAndDensitiesLowVersion) {
- std::unique_ptr<IAaptContext> context = test::ContextBuilder().SetMinSdkVersion(3).Build();
+ std::unique_ptr<IAaptContext> context =
+ test::ContextBuilder().SetPackageId(0x01).SetMinSdkVersion(3).Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddSimple("android:drawable/remove1", test::ParseConfigOrDie("mdpi")) // v4
.AddSimple("android:drawable/remove1", test::ParseConfigOrDie("en-rGB"))
.AddSimple("android:drawable/remove1", test::ParseConfigOrDie("fr-rFR"))
@@ -87,10 +86,10 @@
}
TEST(NoDefaultResourceRemoverTest, KeepEntryWithVersion) {
- std::unique_ptr<IAaptContext> context = test::ContextBuilder().SetMinSdkVersion(8).Build();
+ std::unique_ptr<IAaptContext> context =
+ test::ContextBuilder().SetPackageId(0x01).SetMinSdkVersion(8).Build();
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("android", 0x01)
.AddSimple("android:drawable/keep1", test::ParseConfigOrDie("v8"))
.AddSimple("android:drawable/keep1", test::ParseConfigOrDie("en-rGB"))
.AddSimple("android:drawable/keep1", test::ParseConfigOrDie("fr-rFR"))
diff --git a/tools/aapt2/link/ProductFilter_test.cpp b/tools/aapt2/link/ProductFilter_test.cpp
index dd47674..4f78bbc 100644
--- a/tools/aapt2/link/ProductFilter_test.cpp
+++ b/tools/aapt2/link/ProductFilter_test.cpp
@@ -30,21 +30,29 @@
ResourceTable table;
ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"), land, "",
- test::ValueBuilder<Id>().SetSource(Source("land/default.xml")).Build(),
- context->GetDiagnostics()));
- ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"), land, "tablet",
- test::ValueBuilder<Id>().SetSource(Source("land/tablet.xml")).Build(),
+ NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source("land/default.xml")).Build(), land)
+ .Build(),
context->GetDiagnostics()));
ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"), port, "",
- test::ValueBuilder<Id>().SetSource(Source("port/default.xml")).Build(),
+ NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source("land/tablet.xml")).Build(), land,
+ "tablet")
+ .Build(),
context->GetDiagnostics()));
+
ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"), port, "tablet",
- test::ValueBuilder<Id>().SetSource(Source("port/tablet.xml")).Build(),
+ NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source("port/default.xml")).Build(), port)
+ .Build(),
+ context->GetDiagnostics()));
+
+ ASSERT_TRUE(table.AddResource(
+ NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source("port/tablet.xml")).Build(), port,
+ "tablet")
+ .Build(),
context->GetDiagnostics()));
ProductFilter filter({"tablet"});
@@ -65,15 +73,17 @@
ResourceTable table;
ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"),
- ConfigDescription::DefaultConfig(), "",
- test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build(),
+ NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build())
+ .Build(),
context->GetDiagnostics()));
+
ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"),
- ConfigDescription::DefaultConfig(), "tablet",
- test::ValueBuilder<Id>().SetSource(Source("tablet.xml")).Build(),
+ NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source("tablet.xml")).Build(), {}, "tablet")
+ .Build(),
context->GetDiagnostics()));
+ ;
ProductFilter filter(std::unordered_set<std::string>{});
ASSERT_TRUE(filter.Consume(context.get(), &table));
@@ -91,19 +101,22 @@
ResourceTable table;
ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"),
- ConfigDescription::DefaultConfig(), "",
- test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build(),
+ NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build())
+ .Build(),
context->GetDiagnostics()));
+
ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"),
- ConfigDescription::DefaultConfig(), "tablet",
- test::ValueBuilder<Id>().SetSource(Source("tablet.xml")).Build(),
+ NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source("tablet.xml")).Build(), {}, "tablet")
+ .Build(),
context->GetDiagnostics()));
+
ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"),
- ConfigDescription::DefaultConfig(), "no-sdcard",
- test::ValueBuilder<Id>().SetSource(Source("no-sdcard.xml")).Build(),
+ NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source("no-sdcard.xml")).Build(), {},
+ "no-sdcard")
+ .Build(),
context->GetDiagnostics()));
ProductFilter filter({"tablet", "no-sdcard"});
@@ -114,15 +127,17 @@
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
ResourceTable table;
+ ASSERT_TRUE(
+ table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source(".xml")).Build())
+ .Build(),
+ context->GetDiagnostics()));
+
ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"),
- ConfigDescription::DefaultConfig(), "",
- test::ValueBuilder<Id>().SetSource(Source(".xml")).Build(),
- context->GetDiagnostics()));
- ASSERT_TRUE(table.AddResource(
- test::ParseNameOrDie("android:string/one"),
- ConfigDescription::DefaultConfig(), "default",
- test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build(),
+ NewResourceBuilder(test::ParseNameOrDie("android:string/one"))
+ .SetValue(test::ValueBuilder<Id>().SetSource(Source("default.xml")).Build(), {},
+ "default")
+ .Build(),
context->GetDiagnostics()));
ProductFilter filter(std::unordered_set<std::string>{});
diff --git a/tools/aapt2/link/ReferenceLinker_test.cpp b/tools/aapt2/link/ReferenceLinker_test.cpp
index a31ce94..228c5bd74 100644
--- a/tools/aapt2/link/ReferenceLinker_test.cpp
+++ b/tools/aapt2/link/ReferenceLinker_test.cpp
@@ -28,7 +28,6 @@
TEST(ReferenceLinkerTest, LinkSimpleReferences) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
"com.app.test:string/bar")
@@ -75,7 +74,6 @@
TEST(ReferenceLinkerTest, LinkStyleAttributes) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddValue("com.app.test:style/Theme",
test::StyleBuilder()
.SetParent("android:style/Theme.Material")
@@ -155,7 +153,6 @@
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddValue("com.app.test:style/Theme", ResourceId(0x7f020000),
test::StyleBuilder()
.AddItem("com.android.support:attr/foo",
@@ -176,7 +173,6 @@
TEST(ReferenceLinkerTest, FailToLinkPrivateSymbols) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
"android:string/hidden")
.Build();
@@ -201,7 +197,6 @@
TEST(ReferenceLinkerTest, FailToLinkPrivateMangledSymbols) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
"com.app.lib:string/hidden")
.Build();
@@ -229,7 +224,6 @@
TEST(ReferenceLinkerTest, FailToLinkPrivateStyleAttributes) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .SetPackageId("com.app.test", 0x7f)
.AddValue("com.app.test:style/Theme",
test::StyleBuilder()
.AddItem("android:attr/hidden",
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index ad56092..4ef2882 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -33,8 +33,7 @@
const TableMergerOptions& options)
: context_(context), main_table_(out_table), options_(options) {
// Create the desired package that all tables will be merged into.
- main_package_ =
- main_table_->CreatePackage(context_->GetCompilationPackage(), context_->GetPackageId());
+ main_package_ = main_table_->FindOrCreatePackage(context_->GetCompilationPackage());
CHECK(main_package_ != nullptr) << "package name or ID already taken";
}
@@ -85,20 +84,9 @@
static bool MergeType(IAaptContext* context, const Source& src, ResourceTableType* dst_type,
ResourceTableType* src_type) {
- if (src_type->visibility_level > dst_type->visibility_level) {
+ if (src_type->visibility_level >= dst_type->visibility_level) {
// The incoming type's visibility is stronger, so we should override the visibility.
- if (src_type->visibility_level == Visibility::Level::kPublic) {
- // Only copy the ID if the source is public, or else the ID is meaningless.
- dst_type->id = src_type->id;
- }
dst_type->visibility_level = src_type->visibility_level;
- } else if (dst_type->visibility_level == Visibility::Level::kPublic &&
- src_type->visibility_level == Visibility::Level::kPublic && dst_type->id &&
- src_type->id && dst_type->id.value() != src_type->id.value()) {
- // Both types are public and have different IDs.
- context->GetDiagnostics()->Error(DiagMessage(src) << "cannot merge type '" << src_type->type
- << "': conflicting public IDs");
- return false;
}
return true;
}
@@ -347,7 +335,7 @@
file_ref->type = file_desc.type;
file_ref->file = file;
- ResourceTablePackage* pkg = table.CreatePackage(file_desc.name.package, 0x0);
+ ResourceTablePackage* pkg = table.FindOrCreatePackage(file_desc.name.package);
pkg->FindOrCreateType(file_desc.name.type)
->FindOrCreateEntry(file_desc.name.entry)
->FindOrCreateValue(file_desc.config, {})
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index 69cf5ee..4358fb5 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -55,16 +55,13 @@
TEST_F(TableMergerTest, SimpleMerge) {
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.AddReference("com.app.a:id/foo", "com.app.a:id/bar")
.AddReference("com.app.a:id/bar", "com.app.b:id/foo")
- .AddValue(
- "com.app.a:styleable/view",
- test::StyleableBuilder().AddItem("com.app.b:id/foo").Build())
+ .AddValue("com.app.a:styleable/view",
+ test::StyleableBuilder().AddItem("com.app.b:id/foo").Build())
.Build();
std::unique_ptr<ResourceTable> table_b = test::ResourceTableBuilder()
- .SetPackageId("com.app.b", 0x7f)
.AddSimple("com.app.b:id/foo")
.Build();
@@ -129,12 +126,10 @@
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.AddFileReference("com.app.a:xml/file", "res/xml/file.xml", &file_a)
.Build();
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("com.app.b", 0x7f)
.AddFileReference("com.app.b:xml/file", "res/xml/file.xml", &file_b)
.Build();
@@ -158,12 +153,10 @@
TEST_F(TableMergerTest, OverrideResourceWithOverlay) {
std::unique_ptr<ResourceTable> base =
test::ResourceTableBuilder()
- .SetPackageId("", 0x00)
.AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
.Build();
std::unique_ptr<ResourceTable> overlay =
test::ResourceTableBuilder()
- .SetPackageId("", 0x00)
.AddValue("bool/foo", ResourceUtils::TryParseBool("false"))
.Build();
@@ -194,14 +187,12 @@
std::unique_ptr<ResourceTable> base =
test::ResourceTableBuilder()
- .SetPackageId("", 0x00)
.AddValue("bool/foo", std::move(foo_original))
.AddValue("bool/bar", std::move(bar_original))
.Build();
std::unique_ptr<ResourceTable> overlay =
test::ResourceTableBuilder()
- .SetPackageId("", 0x00)
.AddValue("bool/foo", std::move(foo_overlay))
.AddValue("bool/bar", std::move(bar_overlay))
.AddValue("bool/baz", std::move(baz_overlay))
@@ -226,12 +217,10 @@
TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) {
std::unique_ptr<ResourceTable> base =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
.Build();
std::unique_ptr<ResourceTable> overlay =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
.Build();
@@ -247,12 +236,10 @@
TEST_F(TableMergerTest, FailToOverrideConflictingTypeIdsWithOverlay) {
std::unique_ptr<ResourceTable> base =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
.Build();
std::unique_ptr<ResourceTable> overlay =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.SetSymbolState("bool/foo", ResourceId(0x7f, 0x02, 0x0001), Visibility::Level::kPublic)
.Build();
@@ -268,12 +255,10 @@
TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) {
std::unique_ptr<ResourceTable> base =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
.Build();
std::unique_ptr<ResourceTable> overlay =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0002), Visibility::Level::kPublic)
.Build();
@@ -289,12 +274,10 @@
TEST_F(TableMergerTest, FailConflictingVisibility) {
std::unique_ptr<ResourceTable> base =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
.Build();
std::unique_ptr<ResourceTable> overlay =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPrivate)
.Build();
@@ -318,11 +301,9 @@
}
TEST_F(TableMergerTest, MergeAddResourceFromOverlay) {
- std::unique_ptr<ResourceTable> table_a =
- test::ResourceTableBuilder().SetPackageId("", 0x7f).Build();
+ std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder().Build();
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.SetSymbolState("bool/foo", {}, Visibility::Level::kUndefined, true /*allow new overlay*/)
.AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
.Build();
@@ -337,11 +318,9 @@
}
TEST_F(TableMergerTest, MergeAddResourceFromOverlayWithAutoAddOverlay) {
- std::unique_ptr<ResourceTable> table_a =
- test::ResourceTableBuilder().SetPackageId("", 0x7f).Build();
+ std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder().Build();
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
.Build();
@@ -355,11 +334,9 @@
}
TEST_F(TableMergerTest, FailToMergeNewResourceWithoutAutoAddOverlay) {
- std::unique_ptr<ResourceTable> table_a =
- test::ResourceTableBuilder().SetPackageId("", 0x7f).Build();
+ std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder().Build();
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
.AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
.Build();
@@ -375,7 +352,6 @@
TEST_F(TableMergerTest, OverlaidStyleablesAndStylesShouldBeMerged) {
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.AddValue("com.app.a:styleable/Foo",
test::StyleableBuilder()
.AddItem("com.app.a:attr/bar")
@@ -391,7 +367,6 @@
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.AddValue("com.app.a:styleable/Foo", test::StyleableBuilder()
.AddItem("com.app.a:attr/bat")
.AddItem("com.app.a:attr/foo")
@@ -441,7 +416,6 @@
TEST_F(TableMergerTest, OverrideStyleInsteadOfOverlaying) {
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.AddValue(
"com.app.a:styleable/MyWidget",
test::StyleableBuilder().AddItem("com.app.a:attr/foo", ResourceId(0x1234)).Build())
@@ -452,7 +426,6 @@
.Build();
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.AddValue(
"com.app.a:styleable/MyWidget",
test::StyleableBuilder().AddItem("com.app.a:attr/bar", ResourceId(0x5678)).Build())
@@ -494,13 +467,11 @@
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.SetOverlayable("bool/foo", overlayable_item)
.Build();
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.AddSimple("bool/foo")
.Build();
@@ -527,7 +498,6 @@
"overlay://customization");
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.AddSimple("bool/foo")
.Build();
@@ -536,7 +506,6 @@
overlayable_item.policies |= PolicyFlags::SYSTEM_PARTITION;
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.SetOverlayable("bool/foo", overlayable_item)
.Build();
@@ -565,7 +534,6 @@
overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.SetOverlayable("bool/foo", overlayable_item_first)
.Build();
@@ -575,7 +543,6 @@
overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION;
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.SetOverlayable("bool/foo", overlayable_item_second)
.Build();
@@ -594,7 +561,6 @@
overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.SetOverlayable("bool/foo", overlayable_item_first)
.Build();
@@ -604,7 +570,6 @@
overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION;
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.SetOverlayable("bool/foo", overlayable_item_second)
.Build();
@@ -623,7 +588,6 @@
overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.SetOverlayable("bool/foo", overlayable_item_first)
.Build();
@@ -633,7 +597,6 @@
overlayable_item_second.policies |= PolicyFlags::SIGNATURE;
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.SetOverlayable("bool/foo", overlayable_item_second)
.Build();
@@ -653,7 +616,6 @@
overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.SetOverlayable("bool/foo", overlayable_item_first)
.Build();
@@ -661,7 +623,6 @@
overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION;
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
- .SetPackageId("com.app.a", 0x7f)
.SetOverlayable("bool/foo", overlayable_item_second)
.Build();
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 98ee63d..d385267 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -197,9 +197,10 @@
std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>();
symbol->is_public = (sr.entry->visibility.level == Visibility::Level::kPublic);
- if (sr.package->id && sr.type->id && sr.entry->id) {
- symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(), sr.entry->id.value());
- symbol->is_dynamic = (sr.package->id.value() == 0);
+ if (sr.entry->id) {
+ symbol->id = sr.entry->id.value();
+ symbol->is_dynamic =
+ (sr.entry->id.value().package_id() == 0) || sr.entry->visibility.staged_api;
}
if (name.type == ResourceType::kAttr || name.type == ResourceType::kAttrPrivate) {
@@ -374,7 +375,8 @@
if (s) {
s->is_public = (type_spec_flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
- s->is_dynamic = IsPackageDynamic(ResourceId(res_id).package_id(), real_name.package);
+ s->is_dynamic = IsPackageDynamic(ResourceId(res_id).package_id(), real_name.package) ||
+ (type_spec_flags & android::ResTable_typeSpec::SPEC_STAGED_API) != 0;
return s;
}
return {};
@@ -421,7 +423,8 @@
if (s) {
s->is_public = (*flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
- s->is_dynamic = IsPackageDynamic(ResourceId(id).package_id(), name.package);
+ s->is_dynamic = IsPackageDynamic(ResourceId(id).package_id(), name.package) ||
+ (*flags & android::ResTable_typeSpec::SPEC_STAGED_API) != 0;
return s;
}
return {};
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 6a67271..2f319b1 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -185,7 +185,7 @@
// Initialize all packages for splits.
for (size_t idx = 0; idx < split_count; idx++) {
ResourceTable* split_table = splits_[idx].get();
- split_table->CreatePackage(pkg->name, pkg->id);
+ split_table->FindOrCreatePackage(pkg->name);
}
for (auto& type : pkg->types) {
@@ -241,10 +241,7 @@
// not have actual values for each type/entry.
ResourceTablePackage* split_pkg = split_table->FindPackage(pkg->name);
ResourceTableType* split_type = split_pkg->FindOrCreateType(type->type);
- if (!split_type->id) {
- split_type->id = type->id;
- split_type->visibility_level = type->visibility_level;
- }
+ split_type->visibility_level = type->visibility_level;
ResourceEntry* split_entry = split_type->FindOrCreateEntry(entry->name);
if (!split_entry->id) {
diff --git a/tools/aapt2/split/TableSplitter_test.cpp b/tools/aapt2/split/TableSplitter_test.cpp
index cdf0738..c6a2ff3 100644
--- a/tools/aapt2/split/TableSplitter_test.cpp
+++ b/tools/aapt2/split/TableSplitter_test.cpp
@@ -193,15 +193,23 @@
ResourceTable table;
const ResourceName foo = test::ParseNameOrDie("android:string/foo");
- ASSERT_TRUE(table.AddResource(foo, test::ParseConfigOrDie("land-hdpi"), {},
- util::make_unique<Id>(),
- test::GetDiagnostics()));
- ASSERT_TRUE(table.AddResource(foo, test::ParseConfigOrDie("land-xhdpi"), {},
- util::make_unique<Id>(),
- test::GetDiagnostics()));
- ASSERT_TRUE(table.AddResource(foo, test::ParseConfigOrDie("land-xxhdpi"), {},
- util::make_unique<Id>(),
- test::GetDiagnostics()));
+ ASSERT_TRUE(
+ table.AddResource(NewResourceBuilder(foo)
+ .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land-hdpi"))
+ .Build(),
+ test::GetDiagnostics()));
+
+ ASSERT_TRUE(
+ table.AddResource(NewResourceBuilder(foo)
+ .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land-xhdpi"))
+ .Build(),
+ test::GetDiagnostics()));
+
+ ASSERT_TRUE(table.AddResource(
+ NewResourceBuilder(foo)
+ .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land-xxhdpi"))
+ .Build(),
+ test::GetDiagnostics()));
std::vector<SplitConstraints> constraints;
constraints.push_back(
diff --git a/tools/aapt2/test/Builders.cpp b/tools/aapt2/test/Builders.cpp
index 9a93f2a..4816596 100644
--- a/tools/aapt2/test/Builders.cpp
+++ b/tools/aapt2/test/Builders.cpp
@@ -34,13 +34,6 @@
namespace aapt {
namespace test {
-ResourceTableBuilder& ResourceTableBuilder::SetPackageId(const StringPiece& package_name,
- uint8_t id) {
- ResourceTablePackage* package = table_->CreatePackage(package_name, id);
- CHECK(package != nullptr);
- return *this;
-}
-
ResourceTableBuilder& ResourceTableBuilder::AddSimple(const StringPiece& name,
const ResourceId& id) {
return AddValue(name, id, util::make_unique<Id>());
@@ -118,8 +111,13 @@
const ResourceId& id,
std::unique_ptr<Value> value) {
ResourceName res_name = ParseNameOrDie(name);
- CHECK(table_->AddResourceWithIdMangled(res_name, id, config, {}, std::move(value),
- GetDiagnostics()));
+ NewResourceBuilder builder(res_name);
+ builder.SetValue(std::move(value), config).SetAllowMangled(true);
+ if (id.id != 0U) {
+ builder.SetId(id);
+ }
+
+ CHECK(table_->AddResource(builder.Build(), GetDiagnostics()));
return *this;
}
@@ -128,10 +126,13 @@
Visibility::Level level,
bool allow_new) {
ResourceName res_name = ParseNameOrDie(name);
- Visibility visibility;
- visibility.level = level;
- CHECK(table_->SetVisibilityWithIdMangled(res_name, visibility, id, GetDiagnostics()));
- CHECK(table_->SetAllowNewMangled(res_name, AllowNew{}, GetDiagnostics()));
+ NewResourceBuilder builder(res_name);
+ builder.SetVisibility({level}).SetAllowNew({}).SetAllowMangled(true);
+ if (id.id != 0U) {
+ builder.SetId(id);
+ }
+
+ CHECK(table_->AddResource(builder.Build(), GetDiagnostics()));
return *this;
}
@@ -139,7 +140,14 @@
const OverlayableItem& overlayable) {
ResourceName res_name = ParseNameOrDie(name);
- CHECK(table_->SetOverlayable(res_name, overlayable, GetDiagnostics()));
+ CHECK(table_->AddResource(
+ NewResourceBuilder(res_name).SetOverlayable(overlayable).SetAllowMangled(true).Build(),
+ GetDiagnostics()));
+ return *this;
+}
+
+ResourceTableBuilder& ResourceTableBuilder::Add(NewResource&& res) {
+ CHECK(table_->AddResource(std::move(res), GetDiagnostics()));
return *this;
}
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index c971a1b..3ff955d 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -39,7 +39,6 @@
public:
ResourceTableBuilder() = default;
- ResourceTableBuilder& SetPackageId(const android::StringPiece& package_name, uint8_t id);
ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ResourceId& id = {});
ResourceTableBuilder& AddSimple(const android::StringPiece& name,
const android::ConfigDescription& config,
@@ -75,6 +74,7 @@
Visibility::Level level, bool allow_new = false);
ResourceTableBuilder& SetOverlayable(const android::StringPiece& name,
const OverlayableItem& overlayable);
+ ResourceTableBuilder& Add(NewResource&& res);
StringPool* string_pool();
std::unique_ptr<ResourceTable> Build();