Merge "Add log for IPC failure" into sc-dev
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
index 80317e4..78c4820 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "7396576"
+ build_id: "7471822"
target: "CtsShim"
source_file: "aosp_arm64/CtsShimPriv.apk"
}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
index 3605b6d..a9632ad 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "7396576"
+ build_id: "7471822"
target: "CtsShim"
source_file: "aosp_arm64/CtsShim.apk"
}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
index 025ec3a..df3a0bb 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "7396576"
+ build_id: "7471822"
target: "CtsShim"
source_file: "aosp_x86_64/CtsShimPriv.apk"
}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
index e19235a..1bc6cb8 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "7396576"
+ build_id: "7471822"
target: "CtsShim"
source_file: "aosp_x86_64/CtsShim.apk"
}
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 e524429..400c241 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -37,6 +37,7 @@
import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
import android.app.appsearch.aidl.IAppSearchManager;
import android.app.appsearch.aidl.IAppSearchResultCallback;
+import android.app.appsearch.exceptions.AppSearchException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -58,11 +59,9 @@
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalManagerRegistry;
import com.android.server.SystemService;
-import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
-import com.android.server.appsearch.stats.LoggerInstanceManager;
-import com.android.server.appsearch.stats.PlatformLogger;
import com.android.server.appsearch.util.PackageUtil;
+import com.android.server.appsearch.visibilitystore.VisibilityStore;
import com.android.server.usage.StorageStatsManagerLocal;
import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
@@ -88,9 +87,8 @@
private static final String TAG = "AppSearchManagerService";
private final Context mContext;
private PackageManager mPackageManager;
- private ImplInstanceManager mImplInstanceManager;
private UserManager mUserManager;
- private LoggerInstanceManager mLoggerInstanceManager;
+ private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
// Never call shutdownNow(). It will cancel the futures it's returned. And since
// Executor#execute won't return anything, we will hang forever waiting for the execution.
@@ -115,9 +113,8 @@
public void onStart() {
publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
mPackageManager = getContext().getPackageManager();
- mImplInstanceManager = ImplInstanceManager.getInstance(mContext);
+ mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
mUserManager = mContext.getSystemService(UserManager.class);
- mLoggerInstanceManager = LoggerInstanceManager.getInstance();
registerReceivers();
LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
.registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
@@ -179,8 +176,7 @@
*/
private void handleUserRemoved(@NonNull UserHandle userHandle) {
try {
- mImplInstanceManager.closeAndRemoveAppSearchImplForUser(userHandle);
- mLoggerInstanceManager.removePlatformLoggerForUser(userHandle);
+ mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
} catch (Throwable t) {
Log.e(TAG, "Unable to remove data for: " + userHandle, t);
@@ -218,18 +214,18 @@
UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
try {
if (isUserLocked(userHandle)) {
- //TODO(b/186151459) clear the uninstalled package data when user is unlocked.
+ // We cannot access a locked user's directry and remove package data from it.
+ // We should remove those uninstalled package data when the user is unlocking.
return;
}
- if (ImplInstanceManager.getAppSearchDir(userHandle).exists()) {
- // Only clear the package's data if AppSearch exists for this user.
- PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
- userHandle, AppSearchConfig.getInstance(EXECUTOR));
- AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
- userHandle, logger);
+ // Only clear the package's data if AppSearch exists for this user.
+ if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getOrCreateUserInstance(
+ mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
//TODO(b/145759910) clear visibility setting for package.
- impl.clearPackageData(packageName);
- logger.removeCachedUidForPackage(packageName);
+ instance.getAppSearchImpl().clearPackageData(packageName);
+ instance.getLogger().removeCachedUidForPackage(packageName);
}
} catch (Throwable t) {
Log.e(TAG, "Unable to remove data for package: " + packageName, t);
@@ -239,9 +235,33 @@
@Override
public void onUserUnlocking(@NonNull TargetUser user) {
Objects.requireNonNull(user);
+ UserHandle userHandle = user.getUserHandle();
synchronized (mUnlockedUsersLocked) {
- mUnlockedUsersLocked.add(user.getUserHandle());
+ mUnlockedUsersLocked.add(userHandle);
}
+ EXECUTOR.execute(() -> {
+ try {
+ // Only clear the package's data if AppSearch exists for this user.
+ if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getOrCreateUserInstance(
+ mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
+ List<PackageInfo> installedPackageInfos = mContext
+ .createContextAsUser(userHandle, /*flags=*/0)
+ .getPackageManager()
+ .getInstalledPackages(/*flags=*/0);
+ Set<String> packagesToKeep = new ArraySet<>(installedPackageInfos.size());
+ for (int i = 0; i < installedPackageInfos.size(); i++) {
+ packagesToKeep.add(installedPackageInfos.get(i).packageName);
+ }
+ packagesToKeep.add(VisibilityStore.PACKAGE_NAME);
+ //TODO(b/145759910) clear visibility setting for package.
+ instance.getAppSearchImpl().prunePackageData(packagesToKeep);
+ }
+ } catch (Throwable t) {
+ Log.e(TAG, "Unable to prune packages for " + user, t);
+ }
+ });
}
@Override
@@ -252,7 +272,7 @@
UserHandle userHandle = user.getUserHandle();
mUnlockedUsersLocked.remove(userHandle);
try {
- mImplInstanceManager.closeAndRemoveAppSearchImplForUser(userHandle);
+ mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
} catch (Throwable t) {
Log.e(TAG, "Error handling user stopping.", t);
}
@@ -284,7 +304,7 @@
@NonNull String databaseName,
@NonNull List<Bundle> schemaBundles,
@NonNull List<String> schemasNotDisplayedBySystem,
- @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
+ @NonNull Map<String, List<Bundle>> schemasVisibleToPackagesBundles,
boolean forceOverride,
int schemaVersion,
@NonNull UserHandle userHandle,
@@ -294,7 +314,7 @@
Objects.requireNonNull(databaseName);
Objects.requireNonNull(schemaBundles);
Objects.requireNonNull(schemasNotDisplayedBySystem);
- Objects.requireNonNull(schemasPackageAccessibleBundles);
+ Objects.requireNonNull(schemasVisibleToPackagesBundles);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
@@ -303,7 +323,7 @@
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
- PlatformLogger logger = null;
+ AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
@@ -314,9 +334,9 @@
schemas.add(new AppSearchSchema(schemaBundles.get(i)));
}
Map<String, List<PackageIdentifier>> schemasPackageAccessible =
- new ArrayMap<>(schemasPackageAccessibleBundles.size());
+ new ArrayMap<>(schemasVisibleToPackagesBundles.size());
for (Map.Entry<String, List<Bundle>> entry :
- schemasPackageAccessibleBundles.entrySet()) {
+ schemasVisibleToPackagesBundles.entrySet()) {
List<PackageIdentifier> packageIdentifiers =
new ArrayList<>(entry.getValue().size());
for (int i = 0; i < entry.getValue().size(); i++) {
@@ -325,12 +345,12 @@
}
schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
}
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
- SetSchemaResponse setSchemaResponse = impl.setSchema(
+ instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
packageName,
databaseName,
schemas,
+ instance.getVisibilityStore(),
schemasNotDisplayedBySystem,
schemasPackageAccessible,
forceOverride,
@@ -343,12 +363,12 @@
statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
} finally {
- if (logger != null) {
+ if (instance != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
- logger.logStats(new CallStats.Builder()
+ instance.getLogger().logStats(new CallStats.Builder()
.setPackageName(packageName)
.setDatabase(databaseName)
.setStatusCode(statusCode)
@@ -383,8 +403,10 @@
try {
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- GetSchemaResponse response = impl.getSchema(packageName, databaseName);
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ GetSchemaResponse response =
+ instance.getAppSearchImpl().getSchema(packageName, databaseName);
invokeCallbackOnResult(
callback,
AppSearchResult.newSuccessfulResult(response.getBundle()));
@@ -411,10 +433,12 @@
try {
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- List<String> namespaces = impl.getNamespaces(packageName, databaseName);
- invokeCallbackOnResult(callback,
- AppSearchResult.newSuccessfulResult(namespaces));
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ List<String> namespaces =
+ instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
+ invokeCallbackOnResult(
+ callback, AppSearchResult.newSuccessfulResult(namespaces));
} catch (Throwable t) {
invokeCallbackOnError(callback, t);
}
@@ -440,7 +464,7 @@
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
- PlatformLogger logger = null;
+ AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
@@ -448,17 +472,16 @@
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchBatchResult.Builder<String, Void> resultBuilder =
new AppSearchBatchResult.Builder<>();
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
+ instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
for (int i = 0; i < documentBundles.size(); i++) {
GenericDocument document = new GenericDocument(documentBundles.get(i));
try {
- impl.putDocument(packageName, databaseName, document, logger);
- resultBuilder.setSuccess(document.getId(), /*result=*/ null);
+ instance.getAppSearchImpl().putDocument(
+ packageName, databaseName, document, instance.getLogger());
+ resultBuilder.setSuccess(document.getId(), /*value=*/ null);
++operationSuccessCount;
} catch (Throwable t) {
- resultBuilder.setResult(document.getId(),
- throwableToFailedResult(t));
+ resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
AppSearchResult<Void> result = throwableToFailedResult(t);
resultBuilder.setResult(document.getId(), result);
// Since we can only include one status code in the atom,
@@ -468,19 +491,19 @@
}
}
// Now that the batch has been written. Persist the newly written data.
- impl.persistToDisk(PersistType.Code.LITE);
+ instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
invokeCallbackOnResult(callback, resultBuilder.build());
} catch (Throwable t) {
++operationFailureCount;
statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
} finally {
- if (logger != null) {
+ if (instance != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
- logger.logStats(new CallStats.Builder()
+ instance.getLogger().logStats(new CallStats.Builder()
.setPackageName(packageName)
.setDatabase(databaseName)
.setStatusCode(statusCode)
@@ -521,7 +544,7 @@
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
- PlatformLogger logger = null;
+ AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
@@ -529,18 +552,16 @@
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
new AppSearchBatchResult.Builder<>();
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
+ instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
for (int i = 0; i < ids.size(); i++) {
String id = ids.get(i);
try {
- GenericDocument document =
- impl.getDocument(
- packageName,
- databaseName,
- namespace,
- id,
- typePropertyPaths);
+ GenericDocument document = instance.getAppSearchImpl().getDocument(
+ packageName,
+ databaseName,
+ namespace,
+ id,
+ typePropertyPaths);
++operationSuccessCount;
resultBuilder.setSuccess(id, document.getBundle());
} catch (Throwable t) {
@@ -558,12 +579,12 @@
statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
} finally {
- if (logger != null) {
+ if (instance != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
- logger.logStats(new CallStats.Builder()
+ instance.getLogger().logStats(new CallStats.Builder()
.setPackageName(packageName)
.setDatabase(databaseName)
.setStatusCode(statusCode)
@@ -602,21 +623,19 @@
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
- PlatformLogger logger = null;
+ AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
- SearchResultPage searchResultPage =
- impl.query(
- packageName,
- databaseName,
- queryExpression,
- new SearchSpec(searchSpecBundle),
- logger);
+ instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
+ packageName,
+ databaseName,
+ queryExpression,
+ new SearchSpec(searchSpecBundle),
+ instance.getLogger());
++operationSuccessCount;
invokeCallbackOnResult(
callback,
@@ -626,12 +645,12 @@
statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
} finally {
- if (logger != null) {
+ if (instance != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
- logger.logStats(new CallStats.Builder()
+ instance.getLogger().logStats(new CallStats.Builder()
.setPackageName(packageName)
.setDatabase(databaseName)
.setStatusCode(statusCode)
@@ -668,21 +687,24 @@
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
- PlatformLogger logger = null;
+ AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
- logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- SearchResultPage searchResultPage =
- impl.globalQuery(
- queryExpression,
- new SearchSpec(searchSpecBundle),
- packageName,
- callingUid,
- logger);
+ instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+
+ boolean callerHasSystemAccess =
+ instance.getVisibilityStore().doesCallerHaveSystemAccess(packageName);
+ SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
+ queryExpression,
+ new SearchSpec(searchSpecBundle),
+ packageName,
+ instance.getVisibilityStore(),
+ callingUid,
+ callerHasSystemAccess,
+ instance.getLogger());
++operationSuccessCount;
invokeCallbackOnResult(
callback,
@@ -692,12 +714,12 @@
statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
} finally {
- if (logger != null) {
+ if (instance != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
- logger.logStats(new CallStats.Builder()
+ instance.getLogger().logStats(new CallStats.Builder()
.setPackageName(packageName)
.setStatusCode(statusCode)
.setTotalLatencyMillis(totalLatencyMillis)
@@ -729,8 +751,10 @@
EXECUTOR.execute(() -> {
try {
verifyUserUnlocked(callingUser);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ SearchResultPage searchResultPage =
+ instance.getAppSearchImpl().getNextPage(nextPageToken);
invokeCallbackOnResult(
callback,
AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
@@ -749,8 +773,9 @@
EXECUTOR.execute(() -> {
try {
verifyUserUnlocked(callingUser);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- impl.invalidateNextPageToken(nextPageToken);
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ instance.getAppSearchImpl().invalidateNextPageToken(nextPageToken);
} catch (Throwable t) {
Log.e(TAG, "Unable to invalidate the query page token", t);
}
@@ -779,11 +804,12 @@
EXECUTOR.execute(() -> {
try {
verifyCallingPackage(callingUser, callingUid, packageName);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getUserInstance(callingUser);
// we don't need to append the file. The file is always brand new.
try (DataOutputStream outputStream = new DataOutputStream(
new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
- SearchResultPage searchResultPage = impl.query(
+ SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
packageName,
databaseName,
queryExpression,
@@ -795,7 +821,7 @@
outputStream, searchResultPage.getResults().get(i)
.getGenericDocument().getBundle());
}
- searchResultPage = impl.getNextPage(
+ searchResultPage = instance.getAppSearchImpl().getNextPage(
searchResultPage.getNextPageToken());
}
}
@@ -824,7 +850,8 @@
EXECUTOR.execute(() -> {
try {
verifyCallingPackage(callingUser, callingUid, packageName);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getUserInstance(callingUser);
GenericDocument document;
ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
@@ -839,8 +866,8 @@
break;
}
try {
- impl.putDocument(packageName, databaseName, document,
- /*logger=*/ null);
+ instance.getAppSearchImpl().putDocument(
+ packageName, databaseName, document, /*logger=*/ null);
} catch (Throwable t) {
migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
document.getNamespace(),
@@ -851,7 +878,7 @@
}
}
}
- impl.persistToDisk(PersistType.Code.FULL);
+ instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
invokeCallbackOnResult(callback,
AppSearchResult.newSuccessfulResult(migrationFailureBundles));
} catch (Throwable t) {
@@ -882,17 +909,23 @@
EXECUTOR.execute(() -> {
try {
verifyUserUnlocked(callingUser);
+ verifyCallingPackage(callingUser, callingUid, packageName);
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getUserInstance(callingUser);
- if (systemUsage) {
- // TODO(b/183031844): Validate that the call comes from the system
+ if (systemUsage
+ && !instance.getVisibilityStore()
+ .doesCallerHaveSystemAccess(packageName)) {
+ throw new AppSearchException(
+ AppSearchResult.RESULT_SECURITY_ERROR,
+ packageName + " does not have access to report system usage");
}
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- impl.reportUsage(
+ instance.getAppSearchImpl().reportUsage(
packageName, databaseName, namespace, documentId,
usageTimeMillis, systemUsage);
invokeCallbackOnResult(
- callback, AppSearchResult.newSuccessfulResult(/*result=*/ null));
+ callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
} catch (Throwable t) {
invokeCallbackOnError(callback, t);
}
@@ -920,7 +953,7 @@
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
- PlatformLogger logger = null;
+ AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
@@ -928,12 +961,11 @@
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchBatchResult.Builder<String, Void> resultBuilder =
new AppSearchBatchResult.Builder<>();
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
+ instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
for (int i = 0; i < ids.size(); i++) {
String id = ids.get(i);
try {
- impl.remove(
+ instance.getAppSearchImpl().remove(
packageName,
databaseName,
namespace,
@@ -951,19 +983,19 @@
}
}
// Now that the batch has been written. Persist the newly written data.
- impl.persistToDisk(PersistType.Code.LITE);
+ instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
invokeCallbackOnResult(callback, resultBuilder.build());
} catch (Throwable t) {
++operationFailureCount;
statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
} finally {
- if (logger != null) {
+ if (instance != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
- logger.logStats(new CallStats.Builder()
+ instance.getLogger().logStats(new CallStats.Builder()
.setPackageName(packageName)
.setDatabase(databaseName)
.setStatusCode(statusCode)
@@ -1003,22 +1035,21 @@
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
- PlatformLogger logger = null;
+ AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
- impl.removeByQuery(
+ instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ instance.getAppSearchImpl().removeByQuery(
packageName,
databaseName,
queryExpression,
new SearchSpec(searchSpecBundle),
/*removeStatsBuilder=*/ null);
// Now that the batch has been written. Persist the newly written data.
- impl.persistToDisk(PersistType.Code.LITE);
+ instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
++operationSuccessCount;
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
} catch (Throwable t) {
@@ -1026,12 +1057,12 @@
statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
} finally {
- if (logger != null) {
+ if (instance != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
- logger.logStats(new CallStats.Builder()
+ instance.getLogger().logStats(new CallStats.Builder()
.setPackageName(packageName)
.setDatabase(databaseName)
.setStatusCode(statusCode)
@@ -1066,9 +1097,10 @@
try {
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName,
- databaseName);
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ StorageInfo storageInfo = instance.getAppSearchImpl()
+ .getStorageInfoForDatabase(packageName, databaseName);
Bundle storageInfoBundle = storageInfo.getBundle();
invokeCallbackOnResult(
callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
@@ -1089,26 +1121,25 @@
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
- PlatformLogger logger = null;
+ AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUser);
- AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
- logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
- impl.persistToDisk(PersistType.Code.FULL);
+ instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
++operationSuccessCount;
} catch (Throwable t) {
++operationFailureCount;
statusCode = throwableToFailedResult(t).getResultCode();
Log.e(TAG, "Unable to persist the data to disk", t);
} finally {
- if (logger != null) {
+ if (instance != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
- logger.logStats(new CallStats.Builder()
+ instance.getLogger().logStats(new CallStats.Builder()
.setStatusCode(statusCode)
.setTotalLatencyMillis(totalLatencyMillis)
.setCallType(CallStats.CALL_TYPE_FLUSH)
@@ -1137,15 +1168,13 @@
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
- PlatformLogger logger = null;
+ AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUser);
- logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
- mContext, callingUser,
- AppSearchConfig.getInstance(EXECUTOR));
- mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUser, logger);
+ instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
+ mContext, callingUser, AppSearchConfig.getInstance(EXECUTOR));
++operationSuccessCount;
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
} catch (Throwable t) {
@@ -1153,12 +1182,12 @@
statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
} finally {
- if (logger != null) {
+ if (instance != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
- logger.logStats(new CallStats.Builder()
+ instance.getLogger().logStats(new CallStats.Builder()
.setStatusCode(statusCode)
.setTotalLatencyMillis(totalLatencyMillis)
.setCallType(CallStats.CALL_TYPE_INITIALIZE)
@@ -1255,9 +1284,6 @@
* @param callingUid The actual uid of the caller as determined by Binder.
* @return the user handle that the call should run as. Will always be a concrete user.
*/
- // TODO(b/173553485) verifying that the caller has permission to access target user's data
- // TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
- // TODO(b/173553485) Implement SystemService.onUserStopping()
@NonNull
private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
int callingPid = Binder.getCallingPid();
@@ -1305,12 +1331,11 @@
try {
verifyUserUnlocked(userHandle);
- PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
- mContext, userHandle,
- AppSearchConfig.getInstance(EXECUTOR));
- AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(
- mContext, userHandle, logger);
- stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getOrCreateUserInstance(
+ mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
+ stats.dataSize += instance.getAppSearchImpl()
+ .getStorageInfoForPackage(packageName).getSizeBytes();
} catch (Throwable t) {
Log.e(
TAG,
@@ -1334,14 +1359,12 @@
if (packagesForUid == null) {
return;
}
- PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
- mContext, userHandle,
- AppSearchConfig.getInstance(EXECUTOR));
- AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(
- mContext, userHandle, logger);
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getOrCreateUserInstance(
+ mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
for (int i = 0; i < packagesForUid.length; i++) {
- stats.dataSize +=
- impl.getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
+ stats.dataSize += instance.getAppSearchImpl()
+ .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
}
} catch (Throwable t) {
Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
@@ -1364,14 +1387,13 @@
if (packagesForUser == null) {
return;
}
- PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
- mContext, userHandle,
- AppSearchConfig.getInstance(EXECUTOR));
- AppSearchImpl impl =
- mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userHandle, logger);
+ AppSearchUserInstance instance =
+ mAppSearchUserInstanceManager.getOrCreateUserInstance(
+ mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
for (int i = 0; i < packagesForUser.size(); i++) {
String packageName = packagesForUser.get(i).packageName;
- stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
+ stats.dataSize += instance.getAppSearchImpl()
+ .getStorageInfoForPackage(packageName).getSizeBytes();
}
} catch (Throwable t) {
Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchUserInstance.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchUserInstance.java
new file mode 100644
index 0000000..7e743ed
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchUserInstance.java
@@ -0,0 +1,58 @@
+/*
+ * 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.appsearch;
+
+import android.annotation.NonNull;
+
+import com.android.server.appsearch.external.localstorage.AppSearchImpl;
+import com.android.server.appsearch.stats.PlatformLogger;
+import com.android.server.appsearch.visibilitystore.VisibilityStore;
+
+import java.util.Objects;
+
+/**
+ * Container for AppSearch classes that should only be initialized once per device-user and make up
+ * the core of the AppSearch system.
+ */
+public final class AppSearchUserInstance {
+ private final PlatformLogger mLogger;
+ private final AppSearchImpl mAppSearchImpl;
+ private final VisibilityStore mVisibilityStore;
+
+ AppSearchUserInstance(
+ @NonNull PlatformLogger logger,
+ @NonNull AppSearchImpl appSearchImpl,
+ @NonNull VisibilityStore visibilityStore) {
+ mLogger = Objects.requireNonNull(logger);
+ mAppSearchImpl = Objects.requireNonNull(appSearchImpl);
+ mVisibilityStore = Objects.requireNonNull(visibilityStore);
+ }
+
+ @NonNull
+ public PlatformLogger getLogger() {
+ return mLogger;
+ }
+
+ @NonNull
+ public AppSearchImpl getAppSearchImpl() {
+ return mAppSearchImpl;
+ }
+
+ @NonNull
+ public VisibilityStore getVisibilityStore() {
+ return mVisibilityStore;
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchUserInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchUserInstanceManager.java
new file mode 100644
index 0000000..cedc364
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchUserInstanceManager.java
@@ -0,0 +1,195 @@
+/*
+ * 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.server.appsearch;
+
+import android.annotation.NonNull;
+import android.app.appsearch.exceptions.AppSearchException;
+import android.content.Context;
+import android.os.Environment;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.appsearch.external.localstorage.AppSearchImpl;
+import com.android.server.appsearch.external.localstorage.FrameworkOptimizeStrategy;
+import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.stats.PlatformLogger;
+import com.android.server.appsearch.visibilitystore.VisibilityStore;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Manages the lifecycle of AppSearch classes that should only be initialized once per device-user
+ * and make up the core of the AppSearch system.
+ *
+ * @hide
+ */
+public final class AppSearchUserInstanceManager {
+ private static final String TAG = "AppSearchUserInstanceMa";
+
+ private static volatile AppSearchUserInstanceManager sAppSearchUserInstanceManager;
+
+ @GuardedBy("mInstancesLocked")
+ private final Map<UserHandle, AppSearchUserInstance> mInstancesLocked = new ArrayMap<>();
+
+ private AppSearchUserInstanceManager() {}
+
+ /**
+ * Gets an instance of AppSearchUserInstanceManager to be used.
+ *
+ * <p>If no instance has been initialized yet, a new one will be created. Otherwise, the
+ * existing instance will be returned.
+ */
+ @NonNull
+ public static AppSearchUserInstanceManager getInstance() {
+ if (sAppSearchUserInstanceManager == null) {
+ synchronized (AppSearchUserInstanceManager.class) {
+ if (sAppSearchUserInstanceManager == null) {
+ sAppSearchUserInstanceManager = new AppSearchUserInstanceManager();
+ }
+ }
+ }
+ return sAppSearchUserInstanceManager;
+ }
+
+ /**
+ * Returns AppSearch directory in the credential encrypted system directory for the given user.
+ *
+ * <p>This folder should only be accessed after unlock.
+ */
+ public static File getAppSearchDir(@NonNull UserHandle userHandle) {
+ // Duplicates the implementation of Environment#getDataSystemCeDirectory
+ // TODO(b/191059409): Unhide Environment#getDataSystemCeDirectory and switch to it.
+ File systemCeDir = new File(Environment.getDataDirectory(), "system_ce");
+ File systemCeUserDir = new File(systemCeDir, String.valueOf(userHandle.getIdentifier()));
+ return new File(systemCeUserDir, "appsearch");
+ }
+
+ /**
+ * Gets an instance of AppSearchUserInstance for the given user, or creates one if none exists.
+ *
+ * <p>If no AppSearchUserInstance exists for the unlocked user, Icing will be initialized and
+ * one will be created.
+ *
+ * @param context The context
+ * @param userHandle The multi-user handle of the device user calling AppSearch
+ * @param config Flag manager for AppSearch
+ * @return An initialized {@link AppSearchUserInstance} for this user
+ */
+ @NonNull
+ public AppSearchUserInstance getOrCreateUserInstance(
+ @NonNull Context context,
+ @NonNull UserHandle userHandle,
+ @NonNull AppSearchConfig config)
+ throws AppSearchException {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(userHandle);
+ Objects.requireNonNull(config);
+
+ synchronized (mInstancesLocked) {
+ AppSearchUserInstance instance = mInstancesLocked.get(userHandle);
+ if (instance == null) {
+ Context userContext = context.createContextAsUser(userHandle, /*flags=*/ 0);
+ instance = createUserInstance(userContext, userHandle, config);
+ mInstancesLocked.put(userHandle, instance);
+ }
+ return instance;
+ }
+ }
+
+ /**
+ * Closes and removes an {@link AppSearchUserInstance} for the given user.
+ *
+ * <p>All mutations applied to the underlying {@link AppSearchImpl} will be persisted to disk.
+ *
+ * @param userHandle The multi-user user handle of the user that need to be removed.
+ */
+ public void closeAndRemoveUserInstance(@NonNull UserHandle userHandle) {
+ Objects.requireNonNull(userHandle);
+ synchronized (mInstancesLocked) {
+ AppSearchUserInstance instance = mInstancesLocked.remove(userHandle);
+ if (instance != null) {
+ instance.getAppSearchImpl().close();
+ }
+ }
+ }
+
+ /**
+ * Gets an {@link AppSearchUserInstance} for the given user.
+ *
+ * <p>This method should only be called by an initialized SearchSession, which has already
+ * called {@link #getOrCreateUserInstance} before.
+ *
+ * @param userHandle The multi-user handle of the device user calling AppSearch
+ * @return An initialized {@link AppSearchUserInstance} for this user
+ * @throws IllegalStateException if {@link AppSearchUserInstance} haven't created for the given
+ * user.
+ */
+ @NonNull
+ public AppSearchUserInstance getUserInstance(@NonNull UserHandle userHandle) {
+ Objects.requireNonNull(userHandle);
+ synchronized (mInstancesLocked) {
+ AppSearchUserInstance instance = mInstancesLocked.get(userHandle);
+ if (instance == null) {
+ // Impossible scenario, user cannot call an uninitialized SearchSession,
+ // getInstance should always find the instance for the given user and never try to
+ // create an instance for this user again.
+ throw new IllegalStateException(
+ "AppSearchUserInstance has never been created for: " + userHandle);
+ }
+ return instance;
+ }
+ }
+
+ @NonNull
+ private AppSearchUserInstance createUserInstance(
+ @NonNull Context userContext,
+ @NonNull UserHandle userHandle,
+ @NonNull AppSearchConfig config)
+ throws AppSearchException {
+ long totalLatencyStartMillis = SystemClock.elapsedRealtime();
+ InitializeStats.Builder initStatsBuilder = new InitializeStats.Builder();
+
+ // Initialize the classes that make up AppSearchUserInstance
+ PlatformLogger logger = new PlatformLogger(userContext, userHandle, config);
+
+ File appSearchDir = getAppSearchDir(userHandle);
+ File icingDir = new File(appSearchDir, "icing");
+ Log.i(TAG, "Creating new AppSearch instance at: " + icingDir);
+ AppSearchImpl appSearchImpl =
+ AppSearchImpl.create(icingDir, initStatsBuilder, new FrameworkOptimizeStrategy());
+
+ long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime();
+ VisibilityStore visibilityStore = VisibilityStore.create(appSearchImpl, userContext);
+ long prepareVisibilityStoreLatencyEndMillis = SystemClock.elapsedRealtime();
+
+ initStatsBuilder
+ .setTotalLatencyMillis(
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
+ .setPrepareVisibilityStoreLatencyMillis(
+ (int)
+ (prepareVisibilityStoreLatencyEndMillis
+ - prepareVisibilityStoreLatencyStartMillis));
+ logger.logStats(initStatsBuilder.build());
+
+ return new AppSearchUserInstance(logger, appSearchImpl, visibilityStore);
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
deleted file mode 100644
index 2181dab..0000000
--- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
+++ /dev/null
@@ -1,170 +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.server.appsearch;
-
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.appsearch.exceptions.AppSearchException;
-import android.content.Context;
-import android.os.Environment;
-import android.os.UserHandle;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.server.appsearch.external.localstorage.AppSearchImpl;
-import com.android.server.appsearch.external.localstorage.AppSearchLogger;
-import com.android.server.appsearch.external.localstorage.FrameworkOptimizeStrategy;
-
-import java.io.File;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Manages the lifecycle of instances of {@link AppSearchImpl}.
- *
- * <p>These instances are managed per unique device-user.
- * @hide
- */
-public final class ImplInstanceManager {
- private static final String TAG = "AppSearchImplInstanceMa";
-
- private static ImplInstanceManager sImplInstanceManager;
-
- @GuardedBy("mInstancesLocked")
- private final Map<UserHandle, AppSearchImpl> mInstancesLocked = new ArrayMap<>();
-
- /**
- * Gets an instance of ImplInstanceManager to be used.
- *
- * <p>If no instance has been initialized yet, a new one will be created. Otherwise, the
- * existing instance will be returned.
- */
- @NonNull
- public static ImplInstanceManager getInstance(@NonNull Context context) {
- if (sImplInstanceManager == null) {
- synchronized (ImplInstanceManager.class) {
- if (sImplInstanceManager == null) {
- sImplInstanceManager = new ImplInstanceManager();
- }
- }
- }
- return sImplInstanceManager;
- }
-
- /**
- * Returns AppSearch directory in the credential encrypted system directory for the given user.
- *
- * <p>This folder should only be accessed after unlock.
- */
- public static File getAppSearchDir(@NonNull UserHandle userHandle) {
- // Duplicates the implementation of Environment#getDataSystemCeDirectory
- // TODO(b/191059409): Unhide Environment#getDataSystemCeDirectory and switch to it.
- File systemCeDir = new File(Environment.getDataDirectory(), "system_ce");
- File systemCeUserDir = new File(systemCeDir, String.valueOf(userHandle.getIdentifier()));
- return new File(systemCeUserDir, "appSearch");
- }
-
- /**
- * Gets an instance of AppSearchImpl for the given user, or creates one if none exists.
- *
- * <p>If no AppSearchImpl instance exists for the unlocked user, Icing will be initialized and
- * one will be created.
- *
- * @param context The system context
- * @param userHandle The multi-user handle of the device user calling AppSearch
- * @return An initialized {@link AppSearchImpl} for this user
- */
- @NonNull
- public AppSearchImpl getOrCreateAppSearchImpl(
- @NonNull Context context,
- @NonNull UserHandle userHandle,
- @Nullable AppSearchLogger logger) throws AppSearchException {
- Objects.requireNonNull(context);
- Objects.requireNonNull(userHandle);
-
- synchronized (mInstancesLocked) {
- AppSearchImpl instance = mInstancesLocked.get(userHandle);
- if (instance == null) {
- Context userContext = context.createContextAsUser(userHandle, /*flags=*/ 0);
- instance = createImpl(userContext, userHandle, logger);
- mInstancesLocked.put(userHandle, instance);
- }
- return instance;
- }
- }
-
- /**
- * Close and remove an instance of {@link AppSearchImpl} for the given user.
- *
- * <p>All mutation apply to this {@link AppSearchImpl} will be persisted to disk.
- *
- * @param userHandle The multi-user user handle of the user that need to be removed.
- */
- public void closeAndRemoveAppSearchImplForUser(@NonNull UserHandle userHandle) {
- Objects.requireNonNull(userHandle);
- synchronized (mInstancesLocked) {
- AppSearchImpl appSearchImpl = mInstancesLocked.get(userHandle);
- if (appSearchImpl != null) {
- appSearchImpl.close();
- mInstancesLocked.remove(userHandle);
- }
- }
- }
-
- /**
- * Gets an instance of AppSearchImpl for the given user.
- *
- * <p>This method should only be called by an initialized SearchSession, which has been already
- * created the AppSearchImpl instance for the given user.
- *
- * @param userHandle The multi-user handle of the device user calling AppSearch
- * @return An initialized {@link AppSearchImpl} for this user
- * @throws IllegalStateException if {@link AppSearchImpl} haven't created for the given user.
- */
- @NonNull
- public AppSearchImpl getAppSearchImpl(@NonNull UserHandle userHandle) {
- Objects.requireNonNull(userHandle);
- synchronized (mInstancesLocked) {
- AppSearchImpl instance = mInstancesLocked.get(userHandle);
- if (instance == null) {
- // Impossible scenario, user cannot call an uninitialized SearchSession,
- // getInstance should always find the instance for the given user and never try to
- // create an instance for this user again.
- throw new IllegalStateException(
- "AppSearchImpl has never been created for: " + userHandle);
- }
- return instance;
- }
- }
-
- private AppSearchImpl createImpl(
- @NonNull Context userContext,
- @NonNull UserHandle userHandle,
- @Nullable AppSearchLogger logger)
- throws AppSearchException {
- File appSearchDir = getAppSearchDir(userHandle);
- File icingDir = new File(appSearchDir, "icing");
- Log.i(TAG, "Creating new AppSearch instance at: " + icingDir);
- return AppSearchImpl.create(
- icingDir,
- userContext,
- /*logger=*/ null,
- new FrameworkOptimizeStrategy());
- }
-}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 4a1a9ae..77a1bb4 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -39,7 +39,6 @@
import android.app.appsearch.StorageInfo;
import android.app.appsearch.exceptions.AppSearchException;
import android.app.appsearch.util.LogUtil;
-import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.ArrayMap;
@@ -157,9 +156,6 @@
@VisibleForTesting
final IcingSearchEngine mIcingSearchEngineLocked;
- @GuardedBy("mReadWriteLock")
- private final VisibilityStore mVisibilityStoreLocked;
-
// This map contains schema types and SchemaTypeConfigProtos for all package-database
// prefixes. It maps each package-database prefix to an inner-map. The inner-map maps each
// prefixed schema type to its respective SchemaTypeConfigProto.
@@ -195,56 +191,27 @@
* <p>Instead, logger instance needs to be passed to each individual method, like create, query
* and putDocument.
*
- * @param logger collects stats for initialization if provided.
+ * @param initStatsBuilder collects stats for initialization if provided.
*/
@NonNull
public static AppSearchImpl create(
@NonNull File icingDir,
- @NonNull Context userContext,
- @Nullable AppSearchLogger logger,
+ @Nullable InitializeStats.Builder initStatsBuilder,
@NonNull OptimizeStrategy optimizeStrategy)
throws AppSearchException {
- Objects.requireNonNull(icingDir);
- Objects.requireNonNull(userContext);
- Objects.requireNonNull(optimizeStrategy);
-
- long totalLatencyStartMillis = SystemClock.elapsedRealtime();
- InitializeStats.Builder initStatsBuilder = null;
- if (logger != null) {
- initStatsBuilder = new InitializeStats.Builder();
- }
-
- AppSearchImpl appSearchImpl =
- new AppSearchImpl(
- icingDir, userContext, initStatsBuilder, optimizeStrategy);
-
- long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime();
- appSearchImpl.initializeVisibilityStore();
- long prepareVisibilityStoreLatencyEndMillis = SystemClock.elapsedRealtime();
-
- if (logger != null) {
- initStatsBuilder
- .setTotalLatencyMillis(
- (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
- .setPrepareVisibilityStoreLatencyMillis(
- (int)
- (prepareVisibilityStoreLatencyEndMillis
- - prepareVisibilityStoreLatencyStartMillis));
- logger.logStats(initStatsBuilder.build());
- }
-
- return appSearchImpl;
+ return new AppSearchImpl(icingDir, initStatsBuilder, optimizeStrategy);
}
/** @param initStatsBuilder collects stats for initialization if provided. */
private AppSearchImpl(
@NonNull File icingDir,
- @NonNull Context userContext,
@Nullable InitializeStats.Builder initStatsBuilder,
@NonNull OptimizeStrategy optimizeStrategy)
throws AppSearchException {
- mReadWriteLock.writeLock().lock();
+ Objects.requireNonNull(icingDir);
+ mOptimizeStrategy = Objects.requireNonNull(optimizeStrategy);
+ mReadWriteLock.writeLock().lock();
try {
// We synchronize here because we don't want to call IcingSearchEngine.initialize() more
// than once. It's unnecessary and can be a costly operation.
@@ -258,9 +225,6 @@
"Constructing IcingSearchEngine, response",
Objects.hashCode(mIcingSearchEngineLocked));
- mVisibilityStoreLocked = new VisibilityStore(this, userContext);
- mOptimizeStrategy = optimizeStrategy;
-
// The core initialization procedure. If any part of this fails, we bail into
// resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up).
try {
@@ -342,23 +306,6 @@
}
}
- /**
- * Initialize the visibility store in AppSearchImpl.
- *
- * @throws AppSearchException on IcingSearchEngine error.
- */
- void initializeVisibilityStore() throws AppSearchException {
- mReadWriteLock.writeLock().lock();
- try {
- throwIfClosedLocked();
- mLogUtil.piiTrace("Initializing VisibilityStore, request");
- mVisibilityStoreLocked.initialize();
- mLogUtil.piiTrace("Initializing VisibilityStore, response");
- } finally {
- mReadWriteLock.writeLock().unlock();
- }
- }
-
@GuardedBy("mReadWriteLock")
private void throwIfClosedLocked() {
if (mClosedLocked) {
@@ -399,6 +346,8 @@
* @param packageName The package name that owns the schemas.
* @param databaseName The name of the database where this schema lives.
* @param schemas Schemas to set for this app.
+ * @param visibilityStore If set, {@code schemasNotPlatformSurfaceable} and {@code
+ * schemasPackageAccessible} will be saved here if the schema is successfully applied.
* @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
* surfaces.
* @param schemasPackageAccessible Schema types that are visible to the specified packages.
@@ -416,6 +365,7 @@
@NonNull String packageName,
@NonNull String databaseName,
@NonNull List<AppSearchSchema> schemas,
+ @Nullable VisibilityStore visibilityStore,
@NonNull List<String> schemasNotPlatformSurfaceable,
@NonNull Map<String, List<PackageIdentifier>> schemasPackageAccessible,
boolean forceOverride,
@@ -479,25 +429,27 @@
removeFromMap(mSchemaMapLocked, prefix, schemaType);
}
- Set<String> prefixedSchemasNotPlatformSurfaceable =
- new ArraySet<>(schemasNotPlatformSurfaceable.size());
- for (int i = 0; i < schemasNotPlatformSurfaceable.size(); i++) {
- prefixedSchemasNotPlatformSurfaceable.add(
- prefix + schemasNotPlatformSurfaceable.get(i));
- }
+ if (visibilityStore != null) {
+ Set<String> prefixedSchemasNotPlatformSurfaceable =
+ new ArraySet<>(schemasNotPlatformSurfaceable.size());
+ for (int i = 0; i < schemasNotPlatformSurfaceable.size(); i++) {
+ prefixedSchemasNotPlatformSurfaceable.add(
+ prefix + schemasNotPlatformSurfaceable.get(i));
+ }
- Map<String, List<PackageIdentifier>> prefixedSchemasPackageAccessible =
- new ArrayMap<>(schemasPackageAccessible.size());
- for (Map.Entry<String, List<PackageIdentifier>> entry :
- schemasPackageAccessible.entrySet()) {
- prefixedSchemasPackageAccessible.put(prefix + entry.getKey(), entry.getValue());
- }
+ Map<String, List<PackageIdentifier>> prefixedSchemasPackageAccessible =
+ new ArrayMap<>(schemasPackageAccessible.size());
+ for (Map.Entry<String, List<PackageIdentifier>> entry :
+ schemasPackageAccessible.entrySet()) {
+ prefixedSchemasPackageAccessible.put(prefix + entry.getKey(), entry.getValue());
+ }
- mVisibilityStoreLocked.setVisibility(
- packageName,
- databaseName,
- prefixedSchemasNotPlatformSurfaceable,
- prefixedSchemasPackageAccessible);
+ visibilityStore.setVisibility(
+ packageName,
+ databaseName,
+ prefixedSchemasNotPlatformSurfaceable,
+ prefixedSchemasPackageAccessible);
+ }
return SetSchemaResponseToProtoConverter.toSetSchemaResponse(
setSchemaResultProto, prefix);
@@ -817,7 +769,11 @@
* @param searchSpec Spec for setting filters, raw query etc.
* @param callerPackageName Package name of the caller, should belong to the {@code
* userContext}.
+ * @param visibilityStore Optional visibility store to obtain system and package visibility
+ * settings from
* @param callerUid UID of the client making the globalQuery call.
+ * @param callerHasSystemAccess Whether the caller has been positively identified as having
+ * access to schemas marked system surfaceable.
* @param logger logger to collect globalQuery stats
* @return The results of performing this search. It may contain an empty list of results if no
* documents matched the query.
@@ -828,7 +784,9 @@
@NonNull String queryExpression,
@NonNull SearchSpec searchSpec,
@NonNull String callerPackageName,
+ @Nullable VisibilityStore visibilityStore,
int callerUid,
+ boolean callerHasSystemAccess,
@Nullable AppSearchLogger logger)
throws AppSearchException {
long totalLatencyStartMillis = SystemClock.elapsedRealtime();
@@ -885,15 +843,18 @@
if (packageName.equals(callerPackageName)) {
// Callers can always retrieve their own data
allow = true;
+ } else if (visibilityStore == null) {
+ // If there's no visibility store, there's no extra access
+ allow = false;
} else {
String databaseName = getDatabaseName(prefixedSchema);
allow =
- mVisibilityStoreLocked.isSchemaSearchableByCaller(
+ visibilityStore.isSchemaSearchableByCaller(
packageName,
databaseName,
prefixedSchema,
- callerPackageName,
- callerUid);
+ callerUid,
+ callerHasSystemAccess);
}
if (!allow) {
@@ -1488,9 +1449,6 @@
/**
* Clears documents and schema across all packages and databaseNames.
*
- * <p>This method also clear all data in {@link VisibilityStore}, an {@link
- * #initializeVisibilityStore()} must be called after this.
- *
* <p>This method belongs to mutate group.
*
* @throws AppSearchException on IcingSearchEngine error.
@@ -1514,9 +1472,6 @@
.setResetStatusCode(statusProtoToResultCode(resetResultProto.getStatus()));
}
- // Must be called after everything else since VisibilityStore may repopulate
- // IcingSearchEngine with an initial schema.
- mVisibilityStoreLocked.handleReset();
checkSuccess(resetResultProto.getStatus());
}
@@ -2075,13 +2030,6 @@
return result;
}
- @GuardedBy("mReadWriteLock")
- @NonNull
- @VisibleForTesting
- VisibilityStore getVisibilityStoreLocked() {
- return mVisibilityStoreLocked;
- }
-
/**
* Converts an erroneous status code from the Icing status enums to the AppSearchResult enums.
*
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/stats/LoggerInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/stats/LoggerInstanceManager.java
deleted file mode 100644
index ea00f50..0000000
--- a/apex/appsearch/service/java/com/android/server/appsearch/stats/LoggerInstanceManager.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.appsearch.stats;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.os.UserHandle;
-import android.util.ArrayMap;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.server.appsearch.AppSearchConfig;
-import com.android.server.appsearch.AppSearchManagerService;
-
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Manages the lifecycle of instances of {@link PlatformLogger}.
- *
- * <p>These instances are managed per unique device-user.
- */
-public final class LoggerInstanceManager {
- private static volatile LoggerInstanceManager sLoggerInstanceManager;
-
- @GuardedBy("mInstancesLocked")
- private final Map<UserHandle, PlatformLogger> mInstancesLocked = new ArrayMap<>();
-
- private LoggerInstanceManager() {
- }
-
- /**
- * Gets an instance of {@link LoggerInstanceManager} to be used.
- *
- * <p>If no instance has been initialized yet, a new one will be created. Otherwise, the
- * existing instance will be returned.
- */
- @NonNull
- public static LoggerInstanceManager getInstance() {
- if (sLoggerInstanceManager == null) {
- synchronized (LoggerInstanceManager.class) {
- if (sLoggerInstanceManager == null) {
- sLoggerInstanceManager =
- new LoggerInstanceManager();
- }
- }
- }
- return sLoggerInstanceManager;
- }
-
- /**
- * Gets an instance of PlatformLogger for the given user, or creates one if none exists.
- *
- * @param context The context
- * @param userHandle The multi-user handle of the device user calling AppSearch
- * @return An initialized {@link PlatformLogger} for this user
- */
- @NonNull
- public PlatformLogger getOrCreatePlatformLogger(
- @NonNull Context context, @NonNull UserHandle userHandle,
- @NonNull AppSearchConfig config) {
- Objects.requireNonNull(userHandle);
- synchronized (mInstancesLocked) {
- PlatformLogger instance = mInstancesLocked.get(userHandle);
- if (instance == null) {
- instance = new PlatformLogger(context, userHandle, config);
- mInstancesLocked.put(userHandle, instance);
- }
- return instance;
- }
- }
-
- /**
- * Gets an instance of PlatformLogger for the given user.
- *
- * <p>This method should only be called by an initialized SearchSession, which has been already
- * created the PlatformLogger instance for the given user.
- *
- * @param userHandle The multi-user handle of the device user calling AppSearch
- * @return An initialized {@link PlatformLogger} for this user
- * @throws IllegalStateException if {@link PlatformLogger} haven't created for the given user.
- */
- @NonNull
- public PlatformLogger getPlatformLogger(@NonNull UserHandle userHandle) {
- Objects.requireNonNull(userHandle);
- synchronized (mInstancesLocked) {
- PlatformLogger instance = mInstancesLocked.get(userHandle);
- if (instance == null) {
- // Impossible scenario, user cannot call an uninitialized SearchSession,
- // getInstance should always find the instance for the given user and never try to
- // create an instance for this user again.
- throw new IllegalStateException(
- "PlatformLogger has never been created for: " + userHandle);
- }
- return instance;
- }
- }
-
- /**
- * Remove an instance of {@link PlatformLogger} for the given user.
- *
- * <p>This method should only be called if {@link AppSearchManagerService} receives an
- * ACTION_USER_REMOVED, which the logger instance of given user should be removed.
- *
- * @param userHandle The multi-user handle of the user that need to be removed.
- */
- public void removePlatformLoggerForUser(@NonNull UserHandle userHandle) {
- Objects.requireNonNull(userHandle);
- synchronized (mInstancesLocked) {
- mInstancesLocked.remove(userHandle);
- }
- }
-}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/NotPlatformSurfaceableMap.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/NotPlatformSurfaceableMap.java
index 5ad4276..9e36fd0 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/NotPlatformSurfaceableMap.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/NotPlatformSurfaceableMap.java
@@ -73,9 +73,4 @@
// isn't one of those opt-outs, it's surfaceable.
return !schemaTypes.contains(prefixedSchema);
}
-
- /** Discards all data in the map. */
- public void clear() {
- mMap.clear();
- }
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleMap.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleMap.java
index 2b39347..cff729a 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleMap.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleMap.java
@@ -82,9 +82,4 @@
}
return accessiblePackages;
}
-
- /** Discards all data in the map. */
- public void clear() {
- mMap.clear();
- }
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
index af09210..ae1ec56 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
@@ -76,7 +76,7 @@
* These cannot have any of the special characters used by AppSearchImpl (e.g. {@code
* AppSearchImpl#PACKAGE_DELIMITER} or {@code AppSearchImpl#DATABASE_DELIMITER}.
*/
- @VisibleForTesting public static final String PACKAGE_NAME = "VS#Pkg";
+ public static final String PACKAGE_NAME = "VS#Pkg";
@VisibleForTesting public static final String DATABASE_NAME = "VS#Db";
@@ -99,28 +99,23 @@
private final PackageAccessibleMap mPackageAccessibleMap = new PackageAccessibleMap();
/**
- * Creates an uninitialized VisibilityStore object. Callers must also call {@link #initialize()}
- * before using the object.
+ * Creates and initializes VisibilityStore.
*
* @param appSearchImpl AppSearchImpl instance
* @param userContext Context of the user that the call is being made as
*/
- public VisibilityStore(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext) {
- mAppSearchImpl = Objects.requireNonNull(appSearchImpl);
- mUserContext = Objects.requireNonNull(userContext);
+ @NonNull
+ public static VisibilityStore create(
+ @NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext)
+ throws AppSearchException {
+ return new VisibilityStore(appSearchImpl, userContext);
}
- /**
- * Initializes schemas and member variables to track visibility settings.
- *
- * <p>This is kept separate from the constructor because this will call methods on
- * AppSearchImpl. Some may even then recursively call back into VisibilityStore (for example,
- * {@link AppSearchImpl#setSchema} will call {@link #setVisibility}. We need to have both
- * AppSearchImpl and VisibilityStore fully initialized for this call flow to work.
- *
- * @throws AppSearchException AppSearchException on AppSearchImpl error.
- */
- public void initialize() throws AppSearchException {
+ private VisibilityStore(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext)
+ throws AppSearchException {
+ mAppSearchImpl = Objects.requireNonNull(appSearchImpl);
+ mUserContext = Objects.requireNonNull(userContext);
+
GetSchemaResponse getSchemaResponse = mAppSearchImpl.getSchema(PACKAGE_NAME, DATABASE_NAME);
boolean hasVisibilityType = false;
boolean hasPackageAccessibleType = false;
@@ -142,6 +137,7 @@
PACKAGE_NAME,
DATABASE_NAME,
Arrays.asList(VisibilityDocument.SCHEMA, PackageAccessibleDocument.SCHEMA),
+ /*visibilityStore=*/ null, // Avoid recursive calls
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -149,7 +145,6 @@
}
// Populate visibility settings set
- mNotPlatformSurfaceableMap.clear();
for (Map.Entry<String, Set<String>> entry :
mAppSearchImpl.getPackageToDatabases().entrySet()) {
String packageName = entry.getKey();
@@ -281,38 +276,45 @@
}
/**
+ * Checks whether the given package has access to system-surfaceable schemas.
+ *
+ * @param callerPackageName Package name of the caller.
+ */
+ public boolean doesCallerHaveSystemAccess(@NonNull String callerPackageName) {
+ Objects.requireNonNull(callerPackageName);
+ return mUserContext.getPackageManager()
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, callerPackageName)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ /**
* Checks whether {@code prefixedSchema} can be searched over by the {@code callerUid}.
*
* @param packageName Package that owns the schema.
* @param databaseName Database within the package that owns the schema.
* @param prefixedSchema Prefixed schema type the caller is trying to access.
- * @param callerPackageName Package name of the caller.
- * @param callerUid Uid of the caller.
+ * @param callerUid UID of the client making the globalQuery call.
+ * @param callerHasSystemAccess Whether the caller has been identified as having
+ * access to schemas marked system surfaceable by {@link
+ * #doesCallerHaveSystemAccess}.
*/
public boolean isSchemaSearchableByCaller(
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String prefixedSchema,
- @NonNull String callerPackageName,
- int callerUid) {
+ int callerUid,
+ boolean callerHasSystemAccess) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(prefixedSchema);
- Objects.requireNonNull(callerPackageName);
if (packageName.equals(PACKAGE_NAME)) {
return false; // VisibilityStore schemas are for internal bookkeeping.
}
- // TODO(b/180058203): If we can cache or pass in that a caller has the
- // READ_GLOBAL_SEARCH_DATA permission, then we can save this package manager lookup for
- // each schema we may check in the loop.
- if (mNotPlatformSurfaceableMap.isSchemaPlatformSurfaceable(
- packageName, databaseName, prefixedSchema)
- && mUserContext
- .getPackageManager()
- .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, callerPackageName)
- == PackageManager.PERMISSION_GRANTED) {
+ if (callerHasSystemAccess
+ && mNotPlatformSurfaceableMap.isSchemaPlatformSurfaceable(
+ packageName, databaseName, prefixedSchema)) {
return true;
}
@@ -373,16 +375,6 @@
}
/**
- * Handles an {@code AppSearchImpl#reset()} by clearing any cached state.
- *
- * <p>{@link #initialize()} must be called after this.
- */
- public void handleReset() {
- mNotPlatformSurfaceableMap.clear();
- mPackageAccessibleMap.clear();
- }
-
- /**
* Adds a prefix to create a visibility store document's id.
*
* @param packageName Package to which the visibility doc refers
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 fe0c7f7..fb5129f 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -2006,16 +2006,12 @@
windowLength = INTERVAL_DAY;
} else if ((flags & FLAG_PRIORITIZE) == 0 && windowLength < minAllowedWindow) {
// Prioritized alarms are exempt from minimum window limits.
- if (CompatChanges.isChangeEnabled(
+ if (!isExemptFromMinWindowRestrictions(callingUid) && CompatChanges.isChangeEnabled(
AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, callingPackage,
UserHandle.getUserHandleForUid(callingUid))) {
Slog.w(TAG, "Window length " + windowLength + "ms too short; expanding to "
+ minAllowedWindow + "ms.");
windowLength = minAllowedWindow;
- } else {
- // TODO (b/185199076): Remove temporary log to catch breaking apps.
- Slog.wtf(TAG, "Short window " + windowLength + "ms specified by "
- + callingPackage);
}
}
maxElapsed = triggerElapsed + windowLength;
@@ -2409,6 +2405,13 @@
}
/**
+ * Returns true if the given uid can set window to be as small as it wants.
+ */
+ boolean isExemptFromMinWindowRestrictions(int uid) {
+ return isExemptFromExactAlarmPermission(uid);
+ }
+
+ /**
* Returns true if the given uid does not require SCHEDULE_EXACT_ALARM to set exact,
* allow-while-idle alarms.
*/
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index f741596..7a28407 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -16,6 +16,9 @@
package com.android.server.job;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
+
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import static com.android.server.job.JobSchedulerService.sSystemClock;
@@ -30,6 +33,7 @@
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -63,6 +67,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.StringJoiner;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -387,6 +392,36 @@
}
/**
+ * Returns a single string representation of the contents of the specified intArray.
+ * If the intArray is [1, 2, 4] as the input, the return result will be the string "1,2,4".
+ */
+ @VisibleForTesting
+ static String intArrayToString(int[] values) {
+ final StringJoiner sj = new StringJoiner(",");
+ for (final int value : values) {
+ sj.add(String.valueOf(value));
+ }
+ return sj.toString();
+ }
+
+
+ /**
+ * Converts a string containing a comma-separated list of decimal representations
+ * of ints into an array of int. If the string is not correctly formatted,
+ * or if any value doesn't fit into an int, NumberFormatException is thrown.
+ */
+ @VisibleForTesting
+ static int[] stringToIntArray(String str) {
+ if (TextUtils.isEmpty(str)) return new int[0];
+ final String[] arr = str.split(",");
+ final int[] values = new int[arr.length];
+ for (int i = 0; i < arr.length; i++) {
+ values[i] = Integer.parseInt(arr[i]);
+ }
+ return values;
+ }
+
+ /**
* Runnable that writes {@link #mJobSet} out to xml.
* NOTE: This Runnable locks on mLock
*/
@@ -549,15 +584,12 @@
out.startTag(null, XML_TAG_PARAMS_CONSTRAINTS);
if (jobStatus.hasConnectivityConstraint()) {
final NetworkRequest network = jobStatus.getJob().getRequiredNetwork();
- // STOPSHIP b/183071974: improve the scheme for backward compatibility and
- // mainline cleanliness.
- out.attribute(null, "net-capabilities", Long.toString(
- BitUtils.packBits(network.getCapabilities())));
- out.attribute(null, "net-unwanted-capabilities", Long.toString(
- BitUtils.packBits(network.getForbiddenCapabilities())));
-
- out.attribute(null, "net-transport-types", Long.toString(
- BitUtils.packBits(network.getTransportTypes())));
+ out.attribute(null, "net-capabilities-csv", intArrayToString(
+ network.getCapabilities()));
+ out.attribute(null, "net-forbidden-capabilities-csv", intArrayToString(
+ network.getForbiddenCapabilities()));
+ out.attribute(null, "net-transport-types-csv", intArrayToString(
+ network.getTransportTypes()));
}
if (jobStatus.hasIdleConstraint()) {
out.attribute(null, "idle", Boolean.toString(true));
@@ -831,7 +863,14 @@
} catch (NumberFormatException e) {
Slog.d(TAG, "Error reading constraints, skipping.");
return null;
+ } catch (XmlPullParserException e) {
+ Slog.d(TAG, "Error Parser Exception.", e);
+ return null;
+ } catch (IOException e) {
+ Slog.d(TAG, "Error I/O Exception.", e);
+ return null;
}
+
parser.next(); // Consume </constraints>
// Read out execution parameters tag.
@@ -973,31 +1012,79 @@
return new JobInfo.Builder(jobId, cname);
}
- private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) {
+ /**
+ * In S, there has been a change in format to make the code more robust and more
+ * maintainable.
+ * If the capabities are bits 4, 14, 15, the format in R, it is a long string as
+ * netCapabilitiesLong = '49168' from the old XML file attribute "net-capabilities".
+ * The format in S is the int array string as netCapabilitiesIntArray = '4,14,15'
+ * from the new XML file attribute "net-capabilities-array".
+ * For backward compatibility, when reading old XML the old format is still supported in
+ * reading, but in order to avoid issues with OEM-defined flags, the accepted capabilities
+ * are limited to that(maxNetCapabilityInR & maxTransportInR) defined in R.
+ */
+ private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser)
+ throws XmlPullParserException, IOException {
String val;
+ String netCapabilitiesLong = null;
+ String netForbiddenCapabilitiesLong = null;
+ String netTransportTypesLong = null;
- final String netCapabilities = parser.getAttributeValue(null, "net-capabilities");
- final String netforbiddenCapabilities = parser.getAttributeValue(
- null, "net-unwanted-capabilities");
- final String netTransportTypes = parser.getAttributeValue(null, "net-transport-types");
- if (netCapabilities != null && netTransportTypes != null) {
+ final String netCapabilitiesIntArray = parser.getAttributeValue(
+ null, "net-capabilities-csv");
+ final String netForbiddenCapabilitiesIntArray = parser.getAttributeValue(
+ null, "net-forbidden-capabilities-csv");
+ final String netTransportTypesIntArray = parser.getAttributeValue(
+ null, "net-transport-types-csv");
+ if (netCapabilitiesIntArray == null || netTransportTypesIntArray == null) {
+ netCapabilitiesLong = parser.getAttributeValue(null, "net-capabilities");
+ netForbiddenCapabilitiesLong = parser.getAttributeValue(
+ null, "net-unwanted-capabilities");
+ netTransportTypesLong = parser.getAttributeValue(null, "net-transport-types");
+ }
+
+ if ((netCapabilitiesIntArray != null) && (netTransportTypesIntArray != null)) {
final NetworkRequest.Builder builder = new NetworkRequest.Builder()
.clearCapabilities();
- final long forbiddenCapabilities = netforbiddenCapabilities != null
- ? Long.parseLong(netforbiddenCapabilities)
- : BitUtils.packBits(builder.build().getForbiddenCapabilities());
- // We're okay throwing NFE here; caught by caller
- for (int capability : BitUtils.unpackBits(Long.parseLong(netCapabilities))) {
+
+ for (int capability : stringToIntArray(netCapabilitiesIntArray)) {
builder.addCapability(capability);
}
- for (int forbiddenCapability : BitUtils.unpackBits(
- Long.parseLong(netforbiddenCapabilities))) {
+
+ for (int forbiddenCapability : stringToIntArray(netForbiddenCapabilitiesIntArray)) {
builder.addForbiddenCapability(forbiddenCapability);
}
- for (int transport : BitUtils.unpackBits(Long.parseLong(netTransportTypes))) {
+
+ for (int transport : stringToIntArray(netTransportTypesIntArray)) {
builder.addTransportType(transport);
}
jobBuilder.setRequiredNetwork(builder.build());
+ } else if (netCapabilitiesLong != null && netTransportTypesLong != null) {
+ final NetworkRequest.Builder builder = new NetworkRequest.Builder()
+ .clearCapabilities();
+ final int maxNetCapabilityInR = NET_CAPABILITY_TEMPORARILY_NOT_METERED;
+ // We're okay throwing NFE here; caught by caller
+ for (int capability : BitUtils.unpackBits(Long.parseLong(
+ netCapabilitiesLong))) {
+ if (capability <= maxNetCapabilityInR) {
+ builder.addCapability(capability);
+ }
+ }
+ for (int forbiddenCapability : BitUtils.unpackBits(Long.parseLong(
+ netForbiddenCapabilitiesLong))) {
+ if (forbiddenCapability <= maxNetCapabilityInR) {
+ builder.addForbiddenCapability(forbiddenCapability);
+ }
+ }
+
+ final int maxTransportInR = TRANSPORT_TEST;
+ for (int transport : BitUtils.unpackBits(Long.parseLong(
+ netTransportTypesLong))) {
+ if (transport <= maxTransportInR) {
+ builder.addTransportType(transport);
+ }
+ }
+ jobBuilder.setRequiredNetwork(builder.build());
} else {
// Read legacy values
val = parser.getAttributeValue(null, "connectivity");
diff --git a/api/Android.bp b/api/Android.bp
index db1f64c..a84e6a6 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -69,7 +69,10 @@
dest: "current.txt",
},
{
- targets: ["sdk", "win_sdk"],
+ targets: [
+ "sdk",
+ "win_sdk",
+ ],
dir: "apistubs/android/public/api",
dest: "android.txt",
},
@@ -151,7 +154,10 @@
dest: "removed.txt",
},
{
- targets: ["sdk", "win_sdk"],
+ targets: [
+ "sdk",
+ "win_sdk",
+ ],
dir: "apistubs/android/public/api",
dest: "removed.txt",
},
@@ -187,7 +193,10 @@
dest: "system-current.txt",
},
{
- targets: ["sdk", "win_sdk"],
+ targets: [
+ "sdk",
+ "win_sdk",
+ ],
dir: "apistubs/android/system/api",
dest: "android.txt",
},
@@ -242,7 +251,10 @@
dest: "system-removed.txt",
},
{
- targets: ["sdk", "win_sdk"],
+ targets: [
+ "sdk",
+ "win_sdk",
+ ],
dir: "apistubs/android/system/api",
dest: "removed.txt",
},
@@ -279,7 +291,10 @@
dest: "module-lib-current.txt",
},
{
- targets: ["sdk", "win_sdk"],
+ targets: [
+ "sdk",
+ "win_sdk",
+ ],
dir: "apistubs/android/module-lib/api",
dest: "android.txt",
},
@@ -336,7 +351,10 @@
dest: "module-lib-removed.txt",
},
{
- targets: ["sdk", "win_sdk"],
+ targets: [
+ "sdk",
+ "win_sdk",
+ ],
dir: "apistubs/android/module-lib/api",
dest: "removed.txt",
},
@@ -377,7 +395,10 @@
dest: "system-server-current.txt",
},
{
- targets: ["sdk", "win_sdk"],
+ targets: [
+ "sdk",
+ "win_sdk",
+ ],
dir: "apistubs/android/system-server/api",
dest: "android.txt",
},
@@ -401,7 +422,10 @@
dest: "system-server-removed.txt",
},
{
- targets: ["sdk", "win_sdk"],
+ targets: [
+ "sdk",
+ "win_sdk",
+ ],
dir: "apistubs/android/system-server/api",
dest: "removed.txt",
},
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index 0eff83c..a157517 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -29,7 +29,16 @@
},
},
- ldflags: ["-Wl,--export-dynamic"],
+ // Symbols exported from the executable in .dynsym interpose symbols in every
+ // linker namespace, including an app's classloader namespace. Provide this
+ // version script to prevent unwanted interposition.
+ //
+ // By default, the static linker doesn't export most of an executable's symbols,
+ // but it will export a symbol that appears to override a symbol in a needed DSO.
+ // This commonly happens with C++ vaguely-linked entities, such as template
+ // functions or type_info variables. Hence, a version script is needed even for
+ // an executable.
+ version_script: "version-script.txt",
shared_libs: [
"libandroid_runtime",
diff --git a/cmds/app_process/version-script.txt b/cmds/app_process/version-script.txt
new file mode 100644
index 0000000..a98066a
--- /dev/null
+++ b/cmds/app_process/version-script.txt
@@ -0,0 +1,4 @@
+{
+ local:
+ *;
+};
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 80664ed..a4ac61b 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1769,6 +1769,7 @@
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createProfileForUser(@Nullable String, @NonNull String, int, int, @Nullable String[]);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createRestrictedProfile(@Nullable String);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createUser(@Nullable String, @NonNull String, int);
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.Set<java.lang.String> getPreInstallableSystemPackages(@NonNull String);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public String getUserType();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getUsers(boolean, boolean, boolean);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean hasBaseUserRestriction(@NonNull String, @NonNull android.os.UserHandle);
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index c3272c1..7a806bd 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -45,6 +45,7 @@
private long creationTime;
private ZenPolicy mZenPolicy;
private boolean mModified = false;
+ private String mPkg;
/**
* Creates an automatic zen rule.
@@ -123,6 +124,7 @@
creationTime = source.readLong();
mZenPolicy = source.readParcelable(null);
mModified = source.readInt() == ENABLED;
+ mPkg = source.readString();
}
/**
@@ -244,6 +246,20 @@
this.configurationActivity = componentName;
}
+ /**
+ * @hide
+ */
+ public void setPackageName(String pkgName) {
+ mPkg = pkgName;
+ }
+
+ /**
+ * @hide
+ */
+ public String getPackageName() {
+ return mPkg;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -265,6 +281,7 @@
dest.writeLong(creationTime);
dest.writeParcelable(mZenPolicy, 0);
dest.writeInt(mModified ? ENABLED : DISABLED);
+ dest.writeString(mPkg);
}
@Override
@@ -273,6 +290,7 @@
.append("enabled=").append(enabled)
.append(",name=").append(name)
.append(",interruptionFilter=").append(interruptionFilter)
+ .append(",pkg=").append(mPkg)
.append(",conditionId=").append(conditionId)
.append(",owner=").append(owner)
.append(",configActivity=").append(configurationActivity)
@@ -294,13 +312,14 @@
&& Objects.equals(other.owner, owner)
&& Objects.equals(other.mZenPolicy, mZenPolicy)
&& Objects.equals(other.configurationActivity, configurationActivity)
+ && Objects.equals(other.mPkg, mPkg)
&& other.creationTime == creationTime;
}
@Override
public int hashCode() {
return Objects.hash(enabled, name, interruptionFilter, conditionId, owner,
- configurationActivity, mZenPolicy, mModified, creationTime);
+ configurationActivity, mZenPolicy, mModified, creationTime, mPkg);
}
public static final @android.annotation.NonNull Parcelable.Creator<AutomaticZenRule> CREATOR
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index f33adb3..098492c 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -207,7 +207,7 @@
void setNotificationPolicyAccessGrantedForUser(String pkg, int userId, boolean granted);
AutomaticZenRule getAutomaticZenRule(String id);
List<ZenModeConfig.ZenRule> getZenRules();
- String addAutomaticZenRule(in AutomaticZenRule automaticZenRule);
+ String addAutomaticZenRule(in AutomaticZenRule automaticZenRule, String pkg);
boolean updateAutomaticZenRule(String id, in AutomaticZenRule automaticZenRule);
boolean removeAutomaticZenRule(String id);
boolean removeAutomaticZenRules(String packageName);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index da03a3d..ccf1edb 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1182,10 +1182,12 @@
List<ZenModeConfig.ZenRule> rules = service.getZenRules();
Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
for (ZenModeConfig.ZenRule rule : rules) {
- ruleMap.put(rule.id, new AutomaticZenRule(rule.name, rule.component,
+ AutomaticZenRule azr = new AutomaticZenRule(rule.name, rule.component,
rule.configurationActivity, rule.conditionId, rule.zenPolicy,
zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
- rule.creationTime));
+ rule.creationTime);
+ azr.setPackageName(rule.pkg);
+ ruleMap.put(rule.id, azr);
}
return ruleMap;
} catch (RemoteException e) {
@@ -1226,7 +1228,7 @@
public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
INotificationManager service = getService();
try {
- return service.addAutomaticZenRule(automaticZenRule);
+ return service.addAutomaticZenRule(automaticZenRule, mContext.getPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index e68eb74..0136a35 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -365,7 +365,6 @@
}
if (Compatibility.isChangeEnabled(PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED)
- && !"com.google.android.apps.gcs".equals(packageName)
&& !flagImmutableSet && !flagMutableSet) {
String msg = packageName + ": Targeting S+ (version " + Build.VERSION_CODES.S
+ " and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE"
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 52c58e1..b5b7dbd 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -11871,7 +11871,19 @@
public boolean isAffiliatedUser() {
throwIfParentInstance("isAffiliatedUser");
try {
- return mService.isAffiliatedUser();
+ return mService.isCallingUserAffiliated();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * Returns whether target user is affiliated with the device.
+ */
+ public boolean isAffiliatedUser(@UserIdInt int userId) {
+ try {
+ return mService.isAffiliatedUser(userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index a9bec98..a0d2977 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -18,7 +18,6 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
-import android.app.admin.DevicePolicyManager.OperationSafetyReason;
import android.content.ComponentName;
import android.content.Intent;
import android.os.UserHandle;
@@ -256,13 +255,4 @@
* {@link #supportsResetOp(int)} is true.
*/
public abstract void resetOp(int op, String packageName, @UserIdInt int userId);
-
- /**
- * Notifies the system that an unsafe operation reason has changed.
- *
- * @throws IllegalArgumentException if {@code checker} is not the same as set on
- * {@code DevicePolicyManagerService}.
- */
- public abstract void notifyUnsafeOperationStateChanged(DevicePolicySafetyChecker checker,
- @OperationSafetyReason int reason, boolean isSafe);
}
diff --git a/core/java/android/app/admin/DevicePolicyManagerLiteInternal.java b/core/java/android/app/admin/DevicePolicyManagerLiteInternal.java
new file mode 100644
index 0000000..ccb9947
--- /dev/null
+++ b/core/java/android/app/admin/DevicePolicyManagerLiteInternal.java
@@ -0,0 +1,41 @@
+/*
+ * 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.app.admin;
+
+import android.app.admin.DevicePolicyManager.OperationSafetyReason;
+
+/**
+ * Device policy manager local system service interface for methods that don't require the
+ * {@code device_admin} feature.
+ *
+ * Maintenance note: if you need to expose information from DPMS to lower level services such as
+ * PM/UM/AM/etc, then exposing it from DevicePolicyManagerInternal is not safe because it may cause
+ * lock order inversion. Consider using {@link DevicePolicyCache} instead.
+ *
+ * @hide Only for use within the system server.
+ */
+public interface DevicePolicyManagerLiteInternal {
+
+ /**
+ * Notifies the system that an unsafe operation reason has changed.
+ *
+ * @throws IllegalArgumentException if {@code checker} is not the same as set on
+ * {@code DevicePolicyManagerService.setDevicePolicySafetyChecker()}.
+ */
+ void notifyUnsafeOperationStateChanged(DevicePolicySafetyChecker checker,
+ @OperationSafetyReason int reason, boolean isSafe);
+}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index db2fc0d..b6c48a1 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -390,7 +390,8 @@
void setAffiliationIds(in ComponentName admin, in List<String> ids);
List<String> getAffiliationIds(in ComponentName admin);
- boolean isAffiliatedUser();
+ boolean isCallingUserAffiliated();
+ boolean isAffiliatedUser(int userId);
void setSecurityLoggingEnabled(in ComponentName admin, String packageName, boolean enabled);
boolean isSecurityLoggingEnabled(in ComponentName admin, String packageName);
diff --git a/core/java/android/bluetooth/OWNERS b/core/java/android/bluetooth/OWNERS
index 3523ee0..2239100 100644
--- a/core/java/android/bluetooth/OWNERS
+++ b/core/java/android/bluetooth/OWNERS
@@ -2,3 +2,4 @@
zachoverflow@google.com
siyuanh@google.com
+rahulsabnis@google.com
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index af5f9ce..60ab83a 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -524,8 +524,12 @@
* owned ActivityContainer such as that within an ActivityView. If not set and
* this activity is launched into such a container a SecurityException will be
* thrown. Set from the {@link android.R.attr#allowEmbedded} attribute.
+ *
+ * @deprecated this flag is no longer needed since ActivityView is now fully removed
+ * TODO(b/191165536): delete this flag since is no longer used
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @Deprecated
public static final int FLAG_ALLOW_EMBEDDED = 0x80000000;
/**
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index ec6c233..37469e9 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -952,7 +952,8 @@
}
/**
- * @return name string of the sensor.
+ * @return name string of the sensor. The name is guaranteed to be unique
+ * for a particular sensor type.
*/
public String getName() {
return mName;
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 0a76a9c..713b66a 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -399,7 +399,9 @@
* Use this method to get the list of available sensors of a certain type.
* Make multiple calls to get sensors of different types or use
* {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
- * sensors.
+ * sensors. Note that the {@link android.hardware.Sensor#getName()} is
+ * expected to yield a value that is unique across any sensors that return
+ * the same value for {@link android.hardware.Sensor#getType()}.
*
* <p class="note">
* NOTE: Both wake-up and non wake-up sensors matching the given type are
diff --git a/core/java/android/hardware/biometrics/BiometricAuthenticator.java b/core/java/android/hardware/biometrics/BiometricAuthenticator.java
index a002707..60a36583 100644
--- a/core/java/android/hardware/biometrics/BiometricAuthenticator.java
+++ b/core/java/android/hardware/biometrics/BiometricAuthenticator.java
@@ -63,6 +63,11 @@
*/
int TYPE_FACE = 1 << 3;
+ /**
+ * @hide
+ */
+ int TYPE_ANY_BIOMETRIC = TYPE_FINGERPRINT | TYPE_IRIS | TYPE_FACE;
+
@IntDef(flag = true, value = {
TYPE_NONE,
TYPE_CREDENTIAL,
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 0a12470..e0138c5 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2511,9 +2511,9 @@
* <p>Not all output formats may be supported in a configuration with
* an input stream of a particular format. For more details, see
* android.scaler.availableInputOutputFormatsMap.</p>
- * <p>The following table describes the minimum required output stream
- * configurations based on the hardware level
- * ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel}), prior to Android 12:</p>
+ * <p>For applications targeting SDK version older than 31, the following table
+ * describes the minimum required output stream configurations based on the hardware level
+ * ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel}):</p>
* <table>
* <thead>
* <tr>
@@ -2574,10 +2574,13 @@
* </tr>
* </tbody>
* </table>
- * <p>Starting from Android 12, the camera device may not support JPEG sizes smaller than the
- * minimum of 1080p and the camera sensor active array size. The requirements for
- * IMPLEMENTATION_DEFINED and YUV_420_888 stay the same. This new minimum required output
- * stream configurations are illustrated by the table below:</p>
+ * <p>For applications targeting SDK version 31 or newer, if the mobile device declares to be
+ * {@link android.os.Build.VERSION_CDOES.MEDIA_PERFORMANCE_CLASS media performance class} S,
+ * the primary camera devices (first rear/front camera in the camera ID list) will not
+ * support JPEG sizes smaller than 1080p. If the application configures a JPEG stream
+ * smaller than 1080p, the camera device will round up the JPEG image size to at least
+ * 1080p. The requirements for IMPLEMENTATION_DEFINED and YUV_420_888 stay the same.
+ * This new minimum required output stream configurations are illustrated by the table below:</p>
* <table>
* <thead>
* <tr>
@@ -2644,6 +2647,10 @@
* </tr>
* </tbody>
* </table>
+ * <p>For applications targeting SDK version 31 or newer, if the mobile device doesn't declare
+ * to be media performance class S, or if the camera device isn't a primary rear/front
+ * camera, the minimum required output stream configurations are the same as for applications
+ * targeting SDK version older than 31.</p>
* <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} for additional
* mandatory stream configurations on a per-capability basis.</p>
* <p>Exception on 176x144 (QCIF) resolution: camera devices usually have a fixed capability for
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index 4127243..e24332a 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.camera2.extension.IAdvancedExtenderImpl;
import android.hardware.camera2.extension.ICameraExtensionsProxyService;
@@ -32,6 +33,7 @@
import android.os.ConditionVariable;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.util.Log;
@@ -235,6 +237,19 @@
if (mConnection == null) {
Intent intent = new Intent();
intent.setClassName(PROXY_PACKAGE_NAME, PROXY_SERVICE_NAME);
+ String vendorProxyPackage = SystemProperties.get(
+ "ro.vendor.camera.extensions.package");
+ String vendorProxyService = SystemProperties.get(
+ "ro.vendor.camera.extensions.service");
+ if (!vendorProxyPackage.isEmpty() && !vendorProxyService.isEmpty()) {
+ Log.v(TAG,
+ "Choosing the vendor camera extensions proxy package: "
+ + vendorProxyPackage);
+ Log.v(TAG,
+ "Choosing the vendor camera extensions proxy service: "
+ + vendorProxyService);
+ intent.setClassName(vendorProxyPackage, vendorProxyService);
+ }
mInitFuture = new InitializerFuture();
mConnection = new ServiceConnection() {
@Override
@@ -255,9 +270,9 @@
}
}
};
- ctx.bindService(intent, mConnection, Context.BIND_AUTO_CREATE |
- Context.BIND_IMPORTANT | Context.BIND_ABOVE_CLIENT |
- Context.BIND_NOT_VISIBLE);
+ ctx.bindService(intent, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT |
+ Context.BIND_ABOVE_CLIENT | Context.BIND_NOT_VISIBLE,
+ android.os.AsyncTask.THREAD_POOL_EXECUTOR, mConnection);
try {
mInitFuture.get(PROXY_SERVICE_DELAY_MS, TimeUnit.MILLISECONDS);
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index c1af99a..a1c8d29 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -217,7 +217,7 @@
@NonNull Map<String, SessionConfiguration> cameraIdAndSessionConfig)
throws CameraAccessException {
return CameraManagerGlobal.get().isConcurrentSessionConfigurationSupported(
- cameraIdAndSessionConfig);
+ cameraIdAndSessionConfig, mContext.getApplicationInfo().targetSdkVersion);
}
/**
@@ -413,7 +413,8 @@
try {
for (String physicalCameraId : physicalCameraIds) {
CameraMetadataNative physicalCameraInfo =
- cameraService.getCameraCharacteristics(physicalCameraId);
+ cameraService.getCameraCharacteristics(physicalCameraId,
+ mContext.getApplicationInfo().targetSdkVersion);
StreamConfiguration[] configs = physicalCameraInfo.get(
CameraCharacteristics.
SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS);
@@ -472,7 +473,8 @@
try {
Size displaySize = getDisplaySize();
- CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId);
+ CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId,
+ mContext.getApplicationInfo().targetSdkVersion);
try {
info.setCameraId(Integer.parseInt(cameraId));
} catch (NumberFormatException e) {
@@ -590,7 +592,7 @@
}
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
- oomScoreOffset);
+ oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion);
} catch (ServiceSpecificException e) {
if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
throw new AssertionError("Should've gone down the shim path");
@@ -1613,8 +1615,8 @@
}
public boolean isConcurrentSessionConfigurationSupported(
- @NonNull Map<String, SessionConfiguration> cameraIdsAndSessionConfigurations)
- throws CameraAccessException {
+ @NonNull Map<String, SessionConfiguration> cameraIdsAndSessionConfigurations,
+ int targetSdkVersion) throws CameraAccessException {
if (cameraIdsAndSessionConfigurations == null) {
throw new IllegalArgumentException("cameraIdsAndSessionConfigurations was null");
@@ -1650,7 +1652,7 @@
}
try {
return mCameraService.isConcurrentSessionConfigurationSupported(
- cameraIdsAndConfigs);
+ cameraIdsAndConfigs, targetSdkVersion);
} catch (ServiceSpecificException e) {
throwAsPublicException(e);
} catch (RemoteException e) {
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index c739c6a..a39bc4e 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -22,12 +22,15 @@
import android.os.Handler;
import android.os.PowerManager;
import android.util.IntArray;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import java.util.Objects;
+
/**
* Display manager local system service interface.
*
@@ -293,6 +296,23 @@
public abstract int getRefreshRateSwitchingType();
/**
+ * Return the refresh rate restriction for the specified display and sensor pairing. If the
+ * specified sensor is identified as an associated sensor in the specified display's
+ * display-device-config file, then return any refresh rate restrictions that it might specify.
+ * If no restriction is specified, or the sensor is not associated with the display, then null
+ * will be returned.
+ *
+ * @param displayId The display to check against.
+ * @param name The name of the sensor.
+ * @param type The type of sensor.
+ *
+ * @return The min/max refresh-rate restriction as a {@link Pair} of floats, or null if not
+ * restricted.
+ */
+ public abstract RefreshRateRange getRefreshRateForDisplayAndSensor(
+ int displayId, String name, String type);
+
+ /**
* Describes the requested power state of the display.
*
* This object is intended to describe the general characteristics of the
@@ -527,4 +547,70 @@
*/
void onDisplayGroupChanged(int groupId);
}
+
+ /**
+ * Information about the min and max refresh rate DM would like to set the display to.
+ */
+ public static final class RefreshRateRange {
+ public static final String TAG = "RefreshRateRange";
+
+ // The tolerance within which we consider something approximately equals.
+ public static final float FLOAT_TOLERANCE = 0.01f;
+
+ /**
+ * The lowest desired refresh rate.
+ */
+ public float min;
+
+ /**
+ * The highest desired refresh rate.
+ */
+ public float max;
+
+ public RefreshRateRange() {}
+
+ public RefreshRateRange(float min, float max) {
+ if (min < 0 || max < 0 || min > max + FLOAT_TOLERANCE) {
+ Slog.e(TAG, "Wrong values for min and max when initializing RefreshRateRange : "
+ + min + " " + max);
+ this.min = this.max = 0;
+ return;
+ }
+ if (min > max) {
+ // Min and max are within epsilon of each other, but in the wrong order.
+ float t = min;
+ min = max;
+ max = t;
+ }
+ this.min = min;
+ this.max = max;
+ }
+
+ /**
+ * Checks whether the two objects have the same values.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof RefreshRateRange)) {
+ return false;
+ }
+
+ RefreshRateRange refreshRateRange = (RefreshRateRange) other;
+ return (min == refreshRateRange.min && max == refreshRateRange.max);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(min, max);
+ }
+
+ @Override
+ public String toString() {
+ return "(" + min + " " + max + ")";
+ }
+ }
}
diff --git a/core/java/android/os/AggregateBatteryConsumer.java b/core/java/android/os/AggregateBatteryConsumer.java
index ee86265..802387c 100644
--- a/core/java/android/os/AggregateBatteryConsumer.java
+++ b/core/java/android/os/AggregateBatteryConsumer.java
@@ -17,7 +17,13 @@
package android.os;
import android.annotation.NonNull;
+import android.util.TypedXmlPullParser;
+import android.util.TypedXmlSerializer;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
import java.io.PrintWriter;
/**
@@ -72,6 +78,43 @@
return mConsumedPowerMah;
}
+ /** Serializes this object to XML */
+ void writeToXml(TypedXmlSerializer serializer,
+ @BatteryUsageStats.AggregateBatteryConsumerScope int scope) throws IOException {
+ serializer.startTag(null, BatteryUsageStats.XML_TAG_AGGREGATE);
+ serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_SCOPE, scope);
+ serializer.attributeDouble(null, BatteryUsageStats.XML_ATTR_POWER, mConsumedPowerMah);
+ mPowerComponents.writeToXml(serializer);
+ serializer.endTag(null, BatteryUsageStats.XML_TAG_AGGREGATE);
+ }
+
+ /** Parses an XML representation and populates the BatteryUsageStats builder */
+ static void parseXml(TypedXmlPullParser parser, BatteryUsageStats.Builder builder)
+ throws XmlPullParserException, IOException {
+ final int scope = parser.getAttributeInt(null, BatteryUsageStats.XML_ATTR_SCOPE);
+ final Builder consumerBuilder = builder.getAggregateBatteryConsumerBuilder(scope);
+
+ int eventType = parser.getEventType();
+ if (eventType != XmlPullParser.START_TAG || !parser.getName().equals(
+ BatteryUsageStats.XML_TAG_AGGREGATE)) {
+ throw new XmlPullParserException("Invalid XML parser state");
+ }
+
+ consumerBuilder.setConsumedPower(
+ parser.getAttributeDouble(null, BatteryUsageStats.XML_ATTR_POWER));
+
+ while (!(eventType == XmlPullParser.END_TAG && parser.getName().equals(
+ BatteryUsageStats.XML_TAG_AGGREGATE))
+ && eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ if (parser.getName().equals(BatteryUsageStats.XML_TAG_POWER_COMPONENTS)) {
+ PowerComponents.parseXml(parser, consumerBuilder.mPowerComponentsBuilder);
+ }
+ }
+ eventType = parser.next();
+ }
+ }
+
/**
* Builder for DeviceBatteryConsumer.
*/
@@ -91,6 +134,14 @@
}
/**
+ * Adds power and usage duration from the supplied AggregateBatteryConsumer.
+ */
+ public void add(AggregateBatteryConsumer aggregateBatteryConsumer) {
+ mConsumedPowerMah += aggregateBatteryConsumer.mConsumedPowerMah;
+ mPowerComponentsBuilder.addPowerAndDuration(aggregateBatteryConsumer.mPowerComponents);
+ }
+
+ /**
* Creates a read-only object out of the Builder values.
*/
@NonNull
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index 6c9f0f67..77f8a87 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -20,16 +20,23 @@
import android.annotation.NonNull;
import android.util.Range;
import android.util.SparseArray;
+import android.util.TypedXmlPullParser;
+import android.util.TypedXmlSerializer;
import android.util.proto.ProtoOutputStream;
import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.internal.os.PowerCalculator;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
@@ -77,6 +84,34 @@
private static final int STATSD_PULL_ATOM_MAX_BYTES = 45000;
+ // XML tags and attributes for BatteryUsageStats persistence
+ static final String XML_TAG_BATTERY_USAGE_STATS = "battery_usage_stats";
+ static final String XML_TAG_AGGREGATE = "aggregate";
+ static final String XML_TAG_UID = "uid";
+ static final String XML_TAG_USER = "user";
+ static final String XML_TAG_POWER_COMPONENTS = "power_components";
+ static final String XML_TAG_COMPONENT = "component";
+ static final String XML_TAG_CUSTOM_COMPONENT = "custom_component";
+ static final String XML_ATTR_ID = "id";
+ static final String XML_ATTR_UID = "uid";
+ static final String XML_ATTR_USER_ID = "user_id";
+ static final String XML_ATTR_SCOPE = "scope";
+ static final String XML_ATTR_PREFIX_CUSTOM_COMPONENT = "custom_component_";
+ static final String XML_ATTR_START_TIMESTAMP = "start_timestamp";
+ static final String XML_ATTR_END_TIMESTAMP = "end_timestamp";
+ static final String XML_ATTR_POWER = "power";
+ static final String XML_ATTR_DURATION = "duration";
+ static final String XML_ATTR_MODEL = "model";
+ static final String XML_ATTR_BATTERY_CAPACITY = "battery_capacity";
+ static final String XML_ATTR_DISCHARGE_PERCENT = "discharge_pct";
+ static final String XML_ATTR_DISCHARGE_LOWER = "discharge_lower";
+ static final String XML_ATTR_DISCHARGE_UPPER = "discharge_upper";
+ static final String XML_ATTR_BATTERY_REMAINING = "battery_remaining";
+ static final String XML_ATTR_CHARGE_REMAINING = "charge_remaining";
+ static final String XML_ATTR_HIGHEST_DRAIN_PACKAGE = "highest_drain_package";
+ static final String XML_ATTR_TIME_IN_FOREGROUND = "time_in_foreground";
+ static final String XML_ATTR_TIME_IN_BACKGROUND = "time_in_background";
+
private final int mDischargePercentage;
private final double mBatteryCapacityMah;
private final long mStatsStartTimestampMs;
@@ -96,11 +131,7 @@
private BatteryUsageStats(@NonNull Builder builder) {
mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
mStatsEndTimestampMs = builder.mStatsEndTimestampMs;
- if (builder.mStatsDurationMs != -1) {
- mStatsDurationMs = builder.mStatsDurationMs;
- } else {
- mStatsDurationMs = mStatsEndTimestampMs - mStatsStartTimestampMs;
- }
+ mStatsDurationMs = builder.getStatsDuration();
mBatteryCapacityMah = builder.mBatteryCapacityMah;
mDischargePercentage = builder.mDischargePercentage;
mDischargedPowerLowerBound = builder.mDischargedPowerLowerBoundMah;
@@ -579,6 +610,109 @@
}
}
+ /** Serializes this object to XML */
+ public void writeXml(TypedXmlSerializer serializer) throws IOException {
+ serializer.startTag(null, XML_TAG_BATTERY_USAGE_STATS);
+
+ for (int i = 0; i < mCustomPowerComponentNames.length; i++) {
+ serializer.attribute(null, XML_ATTR_PREFIX_CUSTOM_COMPONENT + i,
+ mCustomPowerComponentNames[i]);
+ }
+
+ serializer.attributeLong(null, XML_ATTR_START_TIMESTAMP, mStatsStartTimestampMs);
+ serializer.attributeLong(null, XML_ATTR_END_TIMESTAMP, mStatsEndTimestampMs);
+ serializer.attributeLong(null, XML_ATTR_DURATION, mStatsDurationMs);
+ serializer.attributeDouble(null, XML_ATTR_BATTERY_CAPACITY, mBatteryCapacityMah);
+ serializer.attributeInt(null, XML_ATTR_DISCHARGE_PERCENT, mDischargePercentage);
+ serializer.attributeDouble(null, XML_ATTR_DISCHARGE_LOWER, mDischargedPowerLowerBound);
+ serializer.attributeDouble(null, XML_ATTR_DISCHARGE_UPPER, mDischargedPowerUpperBound);
+ serializer.attributeLong(null, XML_ATTR_BATTERY_REMAINING, mBatteryTimeRemainingMs);
+ serializer.attributeLong(null, XML_ATTR_CHARGE_REMAINING, mChargeTimeRemainingMs);
+
+ for (int scope = 0; scope < BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT;
+ scope++) {
+ mAggregateBatteryConsumers[scope].writeToXml(serializer, scope);
+ }
+ for (UidBatteryConsumer consumer : mUidBatteryConsumers) {
+ consumer.writeToXml(serializer);
+ }
+ for (UserBatteryConsumer consumer : mUserBatteryConsumers) {
+ consumer.writeToXml(serializer);
+ }
+ serializer.endTag(null, XML_TAG_BATTERY_USAGE_STATS);
+ }
+
+ /** Parses an XML representation of BatteryUsageStats */
+ public static BatteryUsageStats createFromXml(TypedXmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ Builder builder = null;
+ int eventType = parser.getEventType();
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG
+ && parser.getName().equals(XML_TAG_BATTERY_USAGE_STATS)) {
+ List<String> customComponentNames = new ArrayList<>();
+ int i = 0;
+ while (true) {
+ int index = parser.getAttributeIndex(null,
+ XML_ATTR_PREFIX_CUSTOM_COMPONENT + i);
+ if (index == -1) {
+ break;
+ }
+ customComponentNames.add(parser.getAttributeValue(index));
+ i++;
+ }
+
+ builder = new Builder(
+ customComponentNames.toArray(new String[0]), true);
+
+ builder.setStatsStartTimestamp(
+ parser.getAttributeLong(null, XML_ATTR_START_TIMESTAMP));
+ builder.setStatsEndTimestamp(
+ parser.getAttributeLong(null, XML_ATTR_END_TIMESTAMP));
+ builder.setStatsDuration(
+ parser.getAttributeLong(null, XML_ATTR_DURATION));
+ builder.setBatteryCapacity(
+ parser.getAttributeDouble(null, XML_ATTR_BATTERY_CAPACITY));
+ builder.setDischargePercentage(
+ parser.getAttributeInt(null, XML_ATTR_DISCHARGE_PERCENT));
+ builder.setDischargedPowerRange(
+ parser.getAttributeDouble(null, XML_ATTR_DISCHARGE_LOWER),
+ parser.getAttributeDouble(null, XML_ATTR_DISCHARGE_UPPER));
+ builder.setBatteryTimeRemainingMs(
+ parser.getAttributeLong(null, XML_ATTR_BATTERY_REMAINING));
+ builder.setChargeTimeRemainingMs(
+ parser.getAttributeLong(null, XML_ATTR_CHARGE_REMAINING));
+
+ eventType = parser.next();
+ break;
+ }
+ eventType = parser.next();
+ }
+
+ if (builder == null) {
+ throw new XmlPullParserException("No root element");
+ }
+
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ switch (parser.getName()) {
+ case XML_TAG_AGGREGATE:
+ AggregateBatteryConsumer.parseXml(parser, builder);
+ break;
+ case XML_TAG_UID:
+ UidBatteryConsumer.createFromXml(parser, builder);
+ break;
+ case XML_TAG_USER:
+ UserBatteryConsumer.createFromXml(parser, builder);
+ break;
+ }
+ }
+ eventType = parser.next();
+ }
+
+ return builder.build();
+ }
+
/**
* Builder for BatteryUsageStats.
*/
@@ -658,6 +792,14 @@
return this;
}
+ private long getStatsDuration() {
+ if (mStatsDurationMs != -1) {
+ return mStatsDurationMs;
+ } else {
+ return mStatsEndTimestampMs - mStatsStartTimestampMs;
+ }
+ }
+
/**
* Sets the battery discharge amount since BatteryStats reset as percentage of the full
* charge.
@@ -738,6 +880,22 @@
}
/**
+ * Creates or returns a UidBatteryConsumer, which represents battery attribution
+ * data for an individual UID. This version of the method is not suitable for use
+ * with PowerCalculators.
+ */
+ @NonNull
+ public UidBatteryConsumer.Builder getOrCreateUidBatteryConsumerBuilder(int uid) {
+ UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid);
+ if (builder == null) {
+ builder = new UidBatteryConsumer.Builder(mCustomPowerComponentNames,
+ mIncludePowerModels, uid);
+ mUidBatteryConsumerBuilders.put(uid, builder);
+ }
+ return builder;
+ }
+
+ /**
* Creates or returns a UserBatteryConsumer, which represents battery attribution
* data for an individual {@link UserHandle}.
*/
@@ -756,5 +914,59 @@
public SparseArray<UidBatteryConsumer.Builder> getUidBatteryConsumerBuilders() {
return mUidBatteryConsumerBuilders;
}
+
+ /**
+ * Adds battery usage stats from another snapshots. The two snapshots are assumed to be
+ * non-overlapping, meaning that the power consumption estimates and session durations
+ * can be simply summed across the two snapshots. This remains true even if the timestamps
+ * seem to indicate that the sessions are in fact overlapping: timestamps may be off as a
+ * result of realtime clock adjustments by the user or the system.
+ */
+ @NonNull
+ public Builder add(BatteryUsageStats stats) {
+ if (!Arrays.equals(mCustomPowerComponentNames, stats.mCustomPowerComponentNames)) {
+ throw new IllegalArgumentException(
+ "BatteryUsageStats have different custom power components");
+ }
+
+ if (mUserBatteryConsumerBuilders.size() != 0
+ || !stats.getUserBatteryConsumers().isEmpty()) {
+ throw new UnsupportedOperationException(
+ "Combining UserBatteryConsumers is not supported");
+ }
+
+ mDischargedPowerLowerBoundMah += stats.mDischargedPowerLowerBound;
+ mDischargedPowerUpperBoundMah += stats.mDischargedPowerUpperBound;
+ mDischargePercentage += stats.mDischargePercentage;
+
+ mStatsDurationMs = getStatsDuration() + stats.getStatsDuration();
+
+ if (mStatsStartTimestampMs == 0
+ || stats.mStatsStartTimestampMs < mStatsStartTimestampMs) {
+ mStatsStartTimestampMs = stats.mStatsStartTimestampMs;
+ }
+
+ final boolean addingLaterSnapshot = stats.mStatsEndTimestampMs > mStatsEndTimestampMs;
+ if (addingLaterSnapshot) {
+ mStatsEndTimestampMs = stats.mStatsEndTimestampMs;
+ }
+
+ for (int scope = 0; scope < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; scope++) {
+ getAggregateBatteryConsumerBuilder(scope)
+ .add(stats.mAggregateBatteryConsumers[scope]);
+ }
+
+ for (UidBatteryConsumer consumer : stats.getUidBatteryConsumers()) {
+ getOrCreateUidBatteryConsumerBuilder(consumer.getUid()).add(consumer);
+ }
+
+ if (addingLaterSnapshot) {
+ mBatteryCapacityMah = stats.mBatteryCapacityMah;
+ mBatteryTimeRemainingMs = stats.mBatteryTimeRemainingMs;
+ mChargeTimeRemainingMs = stats.mChargeTimeRemainingMs;
+ }
+
+ return this;
+ }
}
}
diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java
index 5080442..97f24cc 100644
--- a/core/java/android/os/BatteryUsageStatsQuery.java
+++ b/core/java/android/os/BatteryUsageStatsQuery.java
@@ -72,12 +72,16 @@
@NonNull
private final int[] mUserIds;
private final long mMaxStatsAgeMs;
+ private long mFromTimestamp;
+ private long mToTimestamp;
private BatteryUsageStatsQuery(@NonNull Builder builder) {
mFlags = builder.mFlags;
mUserIds = builder.mUserIds != null ? builder.mUserIds.toArray()
: new int[]{UserHandle.USER_ALL};
mMaxStatsAgeMs = builder.mMaxStatsAgeMs;
+ mFromTimestamp = builder.mFromTimestamp;
+ mToTimestamp = builder.mToTimestamp;
}
@BatteryUsageStatsFlags
@@ -112,11 +116,30 @@
return mMaxStatsAgeMs;
}
+ /**
+ * Returns the exclusive lower bound of the stored snapshot timestamps that should be included
+ * in the aggregation. Ignored if {@link #getToTimestamp()} is zero.
+ */
+ public long getFromTimestamp() {
+ return mFromTimestamp;
+ }
+
+ /**
+ * Returns the inclusive upper bound of the stored snapshot timestamps that should
+ * be included in the aggregation. The default is to include only the current stats
+ * accumulated since the latest battery reset.
+ */
+ public long getToTimestamp() {
+ return mToTimestamp;
+ }
+
private BatteryUsageStatsQuery(Parcel in) {
mFlags = in.readInt();
mUserIds = new int[in.readInt()];
in.readIntArray(mUserIds);
mMaxStatsAgeMs = in.readLong();
+ mFromTimestamp = in.readLong();
+ mToTimestamp = in.readLong();
}
@Override
@@ -125,6 +148,8 @@
dest.writeInt(mUserIds.length);
dest.writeIntArray(mUserIds);
dest.writeLong(mMaxStatsAgeMs);
+ dest.writeLong(mFromTimestamp);
+ dest.writeLong(mToTimestamp);
}
@Override
@@ -153,6 +178,8 @@
private int mFlags;
private IntArray mUserIds;
private long mMaxStatsAgeMs = DEFAULT_MAX_STATS_AGE_MS;
+ private long mFromTimestamp;
+ private long mToTimestamp;
/**
* Builds a read-only BatteryUsageStatsQuery object.
@@ -204,6 +231,17 @@
}
/**
+ * Requests to aggregate stored snapshots between the two supplied timestamps
+ * @param fromTimestamp Exclusive starting timestamp, as per System.currentTimeMillis()
+ * @param toTimestamp Inclusive ending timestamp, as per System.currentTimeMillis()
+ */
+ public Builder aggregateSnapshots(long fromTimestamp, long toTimestamp) {
+ mFromTimestamp = fromTimestamp;
+ mToTimestamp = toTimestamp;
+ return this;
+ }
+
+ /**
* Set the client's tolerance for stale battery stats. The data may be up to
* this many milliseconds out-of-date.
*/
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 9a81942..3bee4b7 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -46,6 +46,7 @@
UserInfo createProfileForUserWithThrow(in String name, in String userType, int flags, int userId,
in String[] disallowedPackages);
UserInfo createRestrictedProfileWithThrow(String name, int parentUserHandle);
+ String[] getPreInstallableSystemPackages(in String userType);
void setUserEnabled(int userId);
void setUserAdmin(int userId);
void evictCredentialEncryptionKey(int userId);
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index a90ed20..db3d13b 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -19,11 +19,18 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.util.TypedXmlPullParser;
+import android.util.TypedXmlSerializer;
import android.util.proto.ProtoOutputStream;
import com.android.internal.os.PowerCalculator;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Arrays;
/**
* Contains details of battery attribution data broken down to individual power drain types
@@ -36,9 +43,12 @@
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
private final double mConsumedPowerMah;
+ @NonNull
private final double[] mPowerComponentsMah;
+ @NonNull
private final long[] mUsageDurationsMs;
private final int mCustomPowerComponentCount;
+ @Nullable
private final byte[] mPowerModels;
// Not written to Parcel and must be explicitly restored during the parent object's unparceling
private String[] mCustomPowerComponentNames;
@@ -49,7 +59,7 @@
mPowerComponentsMah = builder.mPowerComponentsMah;
mUsageDurationsMs = builder.mUsageDurationsMs;
mConsumedPowerMah = builder.getTotalPower();
- mPowerModels = builder.mPowerModels;
+ mPowerModels = builder.getPowerModels();
}
PowerComponents(@NonNull Parcel source) {
@@ -146,9 +156,13 @@
}
}
+ public boolean hasPowerModels() {
+ return mPowerModels != null;
+ }
+
@BatteryConsumer.PowerModel
int getPowerModel(@BatteryConsumer.PowerComponent int component) {
- if (mPowerModels == null) {
+ if (!hasPowerModels()) {
throw new IllegalStateException(
"Power model IDs were not requested in the BatteryUsageStatsQuery");
}
@@ -294,10 +308,128 @@
return interestingData;
}
+ void writeToXml(TypedXmlSerializer serializer) throws IOException {
+ serializer.startTag(null, BatteryUsageStats.XML_TAG_POWER_COMPONENTS);
+ for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
+ componentId++) {
+ final double powerMah = getConsumedPower(componentId);
+ final long durationMs = getUsageDurationMillis(componentId);
+ if (powerMah == 0 && durationMs == 0) {
+ continue;
+ }
+
+ serializer.startTag(null, BatteryUsageStats.XML_TAG_COMPONENT);
+ serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_ID, componentId);
+ if (powerMah != 0) {
+ serializer.attributeDouble(null, BatteryUsageStats.XML_ATTR_POWER, powerMah);
+ }
+ if (durationMs != 0) {
+ serializer.attributeLong(null, BatteryUsageStats.XML_ATTR_DURATION, durationMs);
+ }
+ if (mPowerModels != null) {
+ serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_MODEL,
+ mPowerModels[componentId]);
+ }
+ serializer.endTag(null, BatteryUsageStats.XML_TAG_COMPONENT);
+ }
+
+ final int customComponentEnd =
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + mCustomPowerComponentCount;
+ for (int componentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+ componentId < customComponentEnd;
+ componentId++) {
+ final double powerMah = getConsumedPowerForCustomComponent(componentId);
+ final long durationMs = getUsageDurationForCustomComponentMillis(componentId);
+ if (powerMah == 0 && durationMs == 0) {
+ continue;
+ }
+
+ serializer.startTag(null, BatteryUsageStats.XML_TAG_CUSTOM_COMPONENT);
+ serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_ID, componentId);
+ if (powerMah != 0) {
+ serializer.attributeDouble(null, BatteryUsageStats.XML_ATTR_POWER, powerMah);
+ }
+ if (durationMs != 0) {
+ serializer.attributeLong(null, BatteryUsageStats.XML_ATTR_DURATION, durationMs);
+ }
+ serializer.endTag(null, BatteryUsageStats.XML_TAG_CUSTOM_COMPONENT);
+ }
+
+ serializer.endTag(null, BatteryUsageStats.XML_TAG_POWER_COMPONENTS);
+ }
+
+
+ static void parseXml(TypedXmlPullParser parser, PowerComponents.Builder builder)
+ throws XmlPullParserException, IOException {
+ int eventType = parser.getEventType();
+ if (eventType != XmlPullParser.START_TAG || !parser.getName().equals(
+ BatteryUsageStats.XML_TAG_POWER_COMPONENTS)) {
+ throw new XmlPullParserException("Invalid XML parser state");
+ }
+
+ while (!(eventType == XmlPullParser.END_TAG && parser.getName().equals(
+ BatteryUsageStats.XML_TAG_POWER_COMPONENTS))
+ && eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ switch (parser.getName()) {
+ case BatteryUsageStats.XML_TAG_COMPONENT: {
+ int componentId = -1;
+ double powerMah = 0;
+ long durationMs = 0;
+ int model = BatteryConsumer.POWER_MODEL_UNDEFINED;
+ for (int i = 0; i < parser.getAttributeCount(); i++) {
+ switch (parser.getAttributeName(i)) {
+ case BatteryUsageStats.XML_ATTR_ID:
+ componentId = parser.getAttributeInt(i);
+ break;
+ case BatteryUsageStats.XML_ATTR_POWER:
+ powerMah = parser.getAttributeDouble(i);
+ break;
+ case BatteryUsageStats.XML_ATTR_DURATION:
+ durationMs = parser.getAttributeLong(i);
+ break;
+ case BatteryUsageStats.XML_ATTR_MODEL:
+ model = parser.getAttributeInt(i);
+ break;
+ }
+ }
+ builder.setConsumedPower(componentId, powerMah, model);
+ builder.setUsageDurationMillis(componentId, durationMs);
+ break;
+ }
+ case BatteryUsageStats.XML_TAG_CUSTOM_COMPONENT: {
+ int componentId = -1;
+ double powerMah = 0;
+ long durationMs = 0;
+ for (int i = 0; i < parser.getAttributeCount(); i++) {
+ switch (parser.getAttributeName(i)) {
+ case BatteryUsageStats.XML_ATTR_ID:
+ componentId = parser.getAttributeInt(i);
+ break;
+ case BatteryUsageStats.XML_ATTR_POWER:
+ powerMah = parser.getAttributeDouble(i);
+ break;
+ case BatteryUsageStats.XML_ATTR_DURATION:
+ durationMs = parser.getAttributeLong(i);
+ break;
+ }
+ }
+ builder.setConsumedPowerForCustomComponent(componentId, powerMah);
+ builder.setUsageDurationForCustomComponentMillis(componentId, durationMs);
+ break;
+ }
+ }
+ }
+ eventType = parser.next();
+ }
+ }
+
/**
* Builder for PowerComponents.
*/
static final class Builder {
+ private static final byte POWER_MODEL_UNINITIALIZED = -1;
+
private final double[] mPowerComponentsMah;
private final String[] mCustomPowerComponentNames;
private final long[] mUsageDurationsMs;
@@ -311,6 +443,7 @@
mUsageDurationsMs = new long[powerComponentCount];
if (includePowerModels) {
mPowerModels = new byte[BatteryConsumer.POWER_COMPONENT_COUNT];
+ Arrays.fill(mPowerModels, POWER_MODEL_UNINITIALIZED);
} else {
mPowerModels = null;
}
@@ -412,12 +545,39 @@
return this;
}
- public void addPowerAndDuration(Builder other) {
+ public void addPowerAndDuration(PowerComponents.Builder other) {
+ addPowerAndDuration(other.mPowerComponentsMah, other.mUsageDurationsMs,
+ other.mPowerModels);
+ }
+
+ public void addPowerAndDuration(PowerComponents other) {
+ addPowerAndDuration(other.mPowerComponentsMah, other.mUsageDurationsMs,
+ other.mPowerModels);
+ }
+
+ private void addPowerAndDuration(double[] powerComponentsMah,
+ long[] usageDurationsMs, byte[] powerModels) {
+ if (mPowerComponentsMah.length != powerComponentsMah.length) {
+ throw new IllegalArgumentException(
+ "Number of power components does not match: " + powerComponentsMah.length
+ + ", expected: " + mPowerComponentsMah.length);
+ }
+
for (int i = mPowerComponentsMah.length - 1; i >= 0; i--) {
- mPowerComponentsMah[i] += other.mPowerComponentsMah[i];
+ mPowerComponentsMah[i] += powerComponentsMah[i];
}
for (int i = mUsageDurationsMs.length - 1; i >= 0; i--) {
- mUsageDurationsMs[i] += other.mUsageDurationsMs[i];
+ mUsageDurationsMs[i] += usageDurationsMs[i];
+ }
+ if (mPowerModels != null && powerModels != null) {
+ for (int i = mPowerModels.length - 1; i >= 0; i--) {
+ if (mPowerModels[i] == POWER_MODEL_UNINITIALIZED) {
+ mPowerModels[i] = powerModels[i];
+ } else if (mPowerModels[i] != powerModels[i]
+ && powerModels[i] != POWER_MODEL_UNINITIALIZED) {
+ mPowerModels[i] = BatteryConsumer.POWER_MODEL_UNDEFINED;
+ }
+ }
}
}
@@ -433,6 +593,19 @@
return totalPowerMah;
}
+ private byte[] getPowerModels() {
+ if (mPowerModels == null) {
+ return null;
+ }
+
+ byte[] powerModels = new byte[mPowerModels.length];
+ for (int i = mPowerModels.length - 1; i >= 0; i--) {
+ powerModels[i] = mPowerModels[i] != POWER_MODEL_UNINITIALIZED ? mPowerModels[i]
+ : BatteryConsumer.POWER_MODEL_UNDEFINED;
+ }
+ return powerModels;
+ }
+
/**
* Creates a read-only object out of the Builder values.
*/
diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java
index c33603d..0416556 100644
--- a/core/java/android/os/SystemVibratorManager.java
+++ b/core/java/android/os/SystemVibratorManager.java
@@ -146,7 +146,7 @@
@Override
public void cancel() {
- cancelVibration(/* usageFilter= */ -1);
+ cancelVibration(VibrationAttributes.USAGE_FILTER_MATCH_ALL);
}
@Override
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index 16a6c76..bfc4f73 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -19,9 +19,16 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.text.TextUtils;
+import android.util.TypedXmlPullParser;
+import android.util.TypedXmlSerializer;
import com.android.internal.os.PowerCalculator;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -143,13 +150,65 @@
return 0;
}
+ /** Serializes this object to XML */
+ void writeToXml(TypedXmlSerializer serializer) throws IOException {
+ if (getConsumedPower() == 0) {
+ return;
+ }
+
+ serializer.startTag(null, BatteryUsageStats.XML_TAG_UID);
+ serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_UID, getUid());
+ if (!TextUtils.isEmpty(mPackageWithHighestDrain)) {
+ serializer.attribute(null, BatteryUsageStats.XML_ATTR_HIGHEST_DRAIN_PACKAGE,
+ mPackageWithHighestDrain);
+ }
+ serializer.attributeLong(null, BatteryUsageStats.XML_ATTR_TIME_IN_FOREGROUND,
+ mTimeInForegroundMs);
+ serializer.attributeLong(null, BatteryUsageStats.XML_ATTR_TIME_IN_BACKGROUND,
+ mTimeInBackgroundMs);
+ mPowerComponents.writeToXml(serializer);
+ serializer.endTag(null, BatteryUsageStats.XML_TAG_UID);
+ }
+
+ /** Parses an XML representation and populates the BatteryUsageStats builder */
+ static void createFromXml(TypedXmlPullParser parser, BatteryUsageStats.Builder builder)
+ throws XmlPullParserException, IOException {
+ final int uid = parser.getAttributeInt(null, BatteryUsageStats.XML_ATTR_UID);
+ final UidBatteryConsumer.Builder consumerBuilder =
+ builder.getOrCreateUidBatteryConsumerBuilder(uid);
+
+ int eventType = parser.getEventType();
+ if (eventType != XmlPullParser.START_TAG
+ || !parser.getName().equals(BatteryUsageStats.XML_TAG_UID)) {
+ throw new XmlPullParserException("Invalid XML parser state");
+ }
+
+ consumerBuilder.setPackageWithHighestDrain(
+ parser.getAttributeValue(null, BatteryUsageStats.XML_ATTR_HIGHEST_DRAIN_PACKAGE));
+ consumerBuilder.setTimeInStateMs(STATE_FOREGROUND,
+ parser.getAttributeLong(null, BatteryUsageStats.XML_ATTR_TIME_IN_FOREGROUND));
+ consumerBuilder.setTimeInStateMs(STATE_BACKGROUND,
+ parser.getAttributeLong(null, BatteryUsageStats.XML_ATTR_TIME_IN_BACKGROUND));
+ while (!(eventType == XmlPullParser.END_TAG
+ && parser.getName().equals(BatteryUsageStats.XML_TAG_UID))
+ && eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ if (parser.getName().equals(BatteryUsageStats.XML_TAG_POWER_COMPONENTS)) {
+ PowerComponents.parseXml(parser, consumerBuilder.mPowerComponentsBuilder);
+ }
+ }
+ eventType = parser.next();
+ }
+ }
+
/**
* Builder for UidBatteryConsumer.
*/
public static final class Builder extends BaseBuilder<Builder> {
+ private static final String PACKAGE_NAME_UNINITIALIZED = "";
private final BatteryStats.Uid mBatteryStatsUid;
private final int mUid;
- private String mPackageWithHighestDrain;
+ private String mPackageWithHighestDrain = PACKAGE_NAME_UNINITIALIZED;
public long mTimeInForegroundMs;
public long mTimeInBackgroundMs;
private boolean mExcludeFromBatteryUsageStats;
@@ -161,8 +220,19 @@
mUid = batteryStatsUid.getUid();
}
+ public Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels,
+ int uid) {
+ super(customPowerComponentNames, includePowerModels);
+ mBatteryStatsUid = null;
+ mUid = uid;
+ }
+
@NonNull
public BatteryStats.Uid getBatteryStatsUid() {
+ if (mBatteryStatsUid == null) {
+ throw new IllegalStateException(
+ "UidBatteryConsumer.Builder was initialized without a BatteryStats.Uid");
+ }
return mBatteryStatsUid;
}
@@ -176,7 +246,7 @@
*/
@NonNull
public Builder setPackageWithHighestDrain(@Nullable String packageName) {
- mPackageWithHighestDrain = packageName;
+ mPackageWithHighestDrain = TextUtils.nullIfEmpty(packageName);
return this;
}
@@ -208,6 +278,30 @@
}
/**
+ * Adds power and usage duration from the supplied UidBatteryConsumer.
+ */
+ public Builder add(UidBatteryConsumer consumer) {
+ mPowerComponentsBuilder.addPowerAndDuration(consumer.mPowerComponents);
+ mTimeInBackgroundMs += consumer.mTimeInBackgroundMs;
+ mTimeInForegroundMs += consumer.mTimeInForegroundMs;
+
+ if (mPackageWithHighestDrain == PACKAGE_NAME_UNINITIALIZED) {
+ mPackageWithHighestDrain = consumer.mPackageWithHighestDrain;
+ } else if (!TextUtils.equals(mPackageWithHighestDrain,
+ consumer.mPackageWithHighestDrain)) {
+ // Consider combining two UidBatteryConsumers with this distribution
+ // of power drain between packages:
+ // (package1=100, package2=10) and (package1=100, package2=101).
+ // Since we don't know the actual power distribution between packages at this
+ // point, we have no way to correctly declare package1 as the winner.
+ // The naive logic of picking the consumer with the higher total consumed
+ // power would produce an incorrect result.
+ mPackageWithHighestDrain = null;
+ }
+ return this;
+ }
+
+ /**
* Returns true if this UidBatteryConsumer must be excluded from the
* BatteryUsageStats.
*/
@@ -220,6 +314,9 @@
*/
@NonNull
public UidBatteryConsumer build() {
+ if (mPackageWithHighestDrain == PACKAGE_NAME_UNINITIALIZED) {
+ mPackageWithHighestDrain = null;
+ }
return new UidBatteryConsumer(this);
}
}
diff --git a/core/java/android/os/UserBatteryConsumer.java b/core/java/android/os/UserBatteryConsumer.java
index 429d2c5..b508a8c 100644
--- a/core/java/android/os/UserBatteryConsumer.java
+++ b/core/java/android/os/UserBatteryConsumer.java
@@ -17,9 +17,15 @@
package android.os;
import android.annotation.NonNull;
+import android.util.TypedXmlPullParser;
+import android.util.TypedXmlSerializer;
import com.android.internal.os.PowerCalculator;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -85,6 +91,42 @@
return 0;
}
+ /** Serializes this object to XML */
+ void writeToXml(TypedXmlSerializer serializer) throws IOException {
+ if (getConsumedPower() == 0) {
+ return;
+ }
+
+ serializer.startTag(null, BatteryUsageStats.XML_TAG_USER);
+ serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_USER_ID, getUserId());
+ mPowerComponents.writeToXml(serializer);
+ serializer.endTag(null, BatteryUsageStats.XML_TAG_USER);
+ }
+
+ /** Parses an XML representation and populates the BatteryUsageStats builder */
+ static void createFromXml(TypedXmlPullParser parser, BatteryUsageStats.Builder builder)
+ throws XmlPullParserException, IOException {
+ final int userId = parser.getAttributeInt(null, BatteryUsageStats.XML_ATTR_USER_ID);
+ final UserBatteryConsumer.Builder consumerBuilder =
+ builder.getOrCreateUserBatteryConsumerBuilder(userId);
+
+ int eventType = parser.getEventType();
+ if (eventType != XmlPullParser.START_TAG
+ || !parser.getName().equals(BatteryUsageStats.XML_TAG_USER)) {
+ throw new XmlPullParserException("Invalid XML parser state");
+ }
+ while (!(eventType == XmlPullParser.END_TAG
+ && parser.getName().equals(BatteryUsageStats.XML_TAG_USER))
+ && eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ if (parser.getName().equals(BatteryUsageStats.XML_TAG_POWER_COMPONENTS)) {
+ PowerComponents.parseXml(parser, consumerBuilder.mPowerComponentsBuilder);
+ }
+ }
+ eventType = parser.next();
+ }
+ }
+
/**
* Builder for UserBatteryConsumer.
*/
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index c22224d..8709f07 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -26,6 +26,7 @@
import android.annotation.RequiresPermission;
import android.annotation.StringDef;
import android.annotation.SuppressAutoDoc;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
@@ -53,6 +54,7 @@
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.AndroidException;
+import android.util.ArraySet;
import android.view.WindowManager.LayoutParams;
import com.android.internal.R;
@@ -1322,6 +1324,24 @@
"disallow_camera_toggle";
/**
+ * This is really not a user restriction in the normal sense. This can't be set to a user,
+ * via UserManager nor via DevicePolicyManager. This is not even set in UserSettingsUtils.
+ * This is defined here purely for convenience within the settings app.
+ *
+ * TODO(b/191306258): Refactor the Settings app to remove the need for this field, and delete it
+ *
+ * Specifies whether biometrics are available to the user. This is used internally only,
+ * as a means of communications between biometric settings and
+ * {@link com.android.settingslib.enterprise.ActionDisabledByAdminControllerFactory}.
+ *
+ * @see {@link android.hardware.biometrics.ParentalControlsUtilsInternal}
+ * @see {@link com.android.settings.biometrics.ParentalControlsUtils}
+ *
+ * @hide
+ */
+ public static final String DISALLOW_BIOMETRIC = "disallow_biometric";
+
+ /**
* Application restriction key that is used to indicate the pending arrival
* of real restrictions for the app.
*
@@ -1415,6 +1435,7 @@
DISALLOW_MICROPHONE_TOGGLE,
DISALLOW_CAMERA_TOGGLE,
KEY_RESTRICTIONS_PENDING,
+ DISALLOW_BIOMETRIC,
})
@Retention(RetentionPolicy.SOURCE)
public @interface UserRestrictionKey {}
@@ -3202,6 +3223,33 @@
}
/**
+ * Returns the list of the system packages that would be installed on this type of user upon
+ * its creation.
+ *
+ * Returns {@code null} if all system packages would be installed.
+ *
+ * @hide
+ */
+ @TestApi
+ @SuppressLint("NullableCollection")
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.CREATE_USERS
+ })
+ public @Nullable Set<String> getPreInstallableSystemPackages(@NonNull String userType) {
+ try {
+ final String[] installableSystemPackages
+ = mService.getPreInstallableSystemPackages(userType);
+ if (installableSystemPackages == null) {
+ return null;
+ }
+ return new ArraySet<>(installableSystemPackages);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @hide
*
* Returns the preferred account name for user creation.
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
index cec323f..43ea2e7 100644
--- a/core/java/android/os/VibrationAttributes.java
+++ b/core/java/android/os/VibrationAttributes.java
@@ -63,6 +63,11 @@
public @interface Usage{}
/**
+ * Vibration usage filter value to match all usages.
+ * @hide
+ */
+ public static final int USAGE_FILTER_MATCH_ALL = -1;
+ /**
* Vibration usage class value to use when the vibration usage class is unknown.
*/
public static final int USAGE_CLASS_UNKNOWN = 0x0;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 36bc3e7..cb87653 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6661,6 +6661,20 @@
public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category.";
/**
+ * Whether or not compress blocks should be released on install.
+ * <p>The setting only determines if the platform will attempt to release
+ * compress blocks; it does not guarantee that the files will have their
+ * compress blocks released. Compression is currently only supported on
+ * some f2fs filesystems.
+ * <p>
+ * Type: int (0 for false, 1 for true)
+ *
+ * @hide
+ */
+ public static final String RELEASE_COMPRESS_BLOCKS_ON_INSTALL =
+ "release_compress_blocks_on_install";
+
+ /**
* List of input methods that are currently enabled. This is a string
* containing the IDs of all enabled input methods, each ID separated
* by ':'.
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 12d9055..ff69281 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -50,6 +50,7 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
+import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -162,6 +163,7 @@
private static final String RULE_ATT_ENABLED = "enabled";
private static final String RULE_ATT_SNOOZING = "snoozing";
private static final String RULE_ATT_NAME = "name";
+ private static final String RULE_ATT_PKG = "pkg";
private static final String RULE_ATT_COMPONENT = "component";
private static final String RULE_ATT_CONFIG_ACTIVITY = "configActivity";
private static final String RULE_ATT_ZEN = "zen";
@@ -671,11 +673,11 @@
rt.conditionId = safeUri(parser, RULE_ATT_CONDITION_ID);
rt.component = safeComponentName(parser, RULE_ATT_COMPONENT);
rt.configurationActivity = safeComponentName(parser, RULE_ATT_CONFIG_ACTIVITY);
- rt.pkg = (rt.component != null)
- ? rt.component.getPackageName()
- : (rt.configurationActivity != null)
- ? rt.configurationActivity.getPackageName()
- : null;
+ rt.pkg = XmlUtils.readStringAttribute(parser, RULE_ATT_PKG);
+ if (rt.pkg == null) {
+ // backfill from component, if present. configActivity is not safe to backfill from
+ rt.pkg = rt.component != null ? rt.component.getPackageName() : null;
+ }
rt.creationTime = safeLong(parser, RULE_ATT_CREATION_TIME, 0);
rt.enabler = parser.getAttributeValue(null, RULE_ATT_ENABLER);
rt.condition = readConditionXml(parser);
@@ -697,6 +699,9 @@
out.attribute(null, RULE_ATT_NAME, rule.name);
}
out.attributeInt(null, RULE_ATT_ZEN, rule.zenMode);
+ if (rule.pkg != null) {
+ out.attribute(null, RULE_ATT_PKG, rule.pkg);
+ }
if (rule.component != null) {
out.attribute(null, RULE_ATT_COMPONENT, rule.component.flattenToString());
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a8fe875..9450801 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20703,8 +20703,7 @@
}
/**
- * Return the window this view is currently attached to. Used in
- * {@link android.app.ActivityView} to communicate with WM.
+ * Return the window this view is currently attached to.
* @hide
*/
protected IWindow getWindow() {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index d42e0c3..cf8c746 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -461,6 +461,9 @@
protected final ViewFrameInfo mViewFrameInfo = new ViewFrameInfo();
private final InputEventAssigner mInputEventAssigner = new InputEventAssigner();
+ // Set to true if mSurfaceControl is used for Webview Overlay
+ private boolean mIsForWebviewOverlay;
+
/**
* Update the Choreographer's FrameInfo object with the timing information for the current
* ViewRootImpl instance. Erase the data in the current ViewFrameInfo to prepare for the next
@@ -1374,6 +1377,23 @@
mAttachInfo.mThreadedRenderer.setASurfaceTransactionCallback(callback);
}
+ /**
+ * Register a callback to be executed when Webview overlay needs a surface control.
+ * This callback will be executed on RenderThread worker thread, and released inside native code
+ * when CanvasContext is destroyed.
+ */
+ private void addPrepareSurfaceControlForWebviewCallback() {
+ HardwareRenderer.PrepareSurfaceControlForWebviewCallback callback = () -> {
+ // make mSurfaceControl transparent, so child surface controls are visible
+ if (mIsForWebviewOverlay) return;
+ synchronized (ViewRootImpl.this) {
+ mIsForWebviewOverlay = true;
+ }
+ mTransaction.setOpaque(mSurfaceControl, false).apply();
+ };
+ mAttachInfo.mThreadedRenderer.setPrepareSurfaceControlForWebviewCallback(callback);
+ }
+
@UnsupportedAppUsage
private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
mAttachInfo.mHardwareAccelerated = false;
@@ -1418,6 +1438,7 @@
if (mHardwareRendererObserver != null) {
mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
}
+ addPrepareSurfaceControlForWebviewCallback();
addASurfaceTransactionCallback();
mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
}
@@ -7743,6 +7764,7 @@
}
}
if (mAttachInfo.mThreadedRenderer != null) {
+ addPrepareSurfaceControlForWebviewCallback();
addASurfaceTransactionCallback();
mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
}
@@ -7790,7 +7812,14 @@
return;
}
- mTransaction.setOpaque(mSurfaceControl, opaque).apply();
+ synchronized (this) {
+ if (mIsForWebviewOverlay) {
+ mIsSurfaceOpaque = false;
+ return;
+ }
+ mTransaction.setOpaque(mSurfaceControl, opaque).apply();
+ }
+
mIsSurfaceOpaque = opaque;
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index c633268..cc47f09 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -341,11 +341,7 @@
}
}
- try {
- flush(FLUSH_REASON_SESSION_FINISHED);
- } finally {
- onDestroy();
- }
+ onDestroy();
}
abstract void onDestroy();
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index d8ac779..bcb9142 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -263,7 +263,13 @@
@Override
void onDestroy() {
mHandler.removeMessages(MSG_FLUSH);
- mHandler.post(() -> destroySession());
+ mHandler.post(() -> {
+ try {
+ flush(FLUSH_REASON_SESSION_FINISHED);
+ } finally {
+ destroySession();
+ }
+ });
}
/**
@@ -571,9 +577,11 @@
private ParceledListSlice<ContentCaptureEvent> clearEvents() {
// NOTE: we must save a reference to the current mEvents and then set it to to null,
// otherwise clearing it would clear it in the receiving side if the service is also local.
- final List<ContentCaptureEvent> events = mEvents == null
- ? Collections.EMPTY_LIST
- : new ArrayList<>(mEvents);
+ if (mEvents == null) {
+ return new ParceledListSlice<>(Collections.EMPTY_LIST);
+ }
+
+ final List<ContentCaptureEvent> events = new ArrayList<>(mEvents);
mEvents.clear();
return new ParceledListSlice<>(events);
}
diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS
index 64570a8..e1d6012 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -8,6 +8,6 @@
mount@google.com
njawad@google.com
-per-file TextView.java, EditText.java, Editor.java = siyamed@google.com, nona@google.com, clarabayarri@google.com
+per-file TextView*, EditText.java, Editor.java = siyamed@google.com, nona@google.com, clarabayarri@google.com
per-file SpellChecker.java = file:../view/inputmethod/OWNERS
diff --git a/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java b/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java
index a600a94..c57afbc 100644
--- a/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java
+++ b/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java
@@ -16,6 +16,7 @@
package com.android.internal.accessibility.util;
+import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
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_WINDOW;
@@ -28,6 +29,7 @@
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON;
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON_LONG_PRESS;
+import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_FLOATING_MENU;
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__TRIPLE_TAP;
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__UNKNOWN_TYPE;
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__VOLUME_KEY;
@@ -37,6 +39,8 @@
import static com.android.internal.util.FrameworkStatsLog.MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_WINDOW;
import android.content.ComponentName;
+import android.content.Context;
+import android.provider.Settings;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.ShortcutType;
@@ -50,50 +54,54 @@
private AccessibilityStatsLogUtils() {}
/**
- * Logs accessibility feature name that is assigned to the shortcut also its shortcut type.
+ * Logs accessibility feature name that is assigned to the given {@code shortcutType}.
* Calls this when clicking the shortcut {@link AccessibilityManager#ACCESSIBILITY_BUTTON} or
- * {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY}
+ * {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY}.
*
+ * @param context context used to retrieve the {@link Settings} provider
* @param componentName component name of the accessibility feature
- * @param shortcutType accessibility shortcut type {@link ShortcutType}
+ * @param shortcutType accessibility shortcut type
*/
- public static void logAccessibilityShortcutActivated(ComponentName componentName,
- @ShortcutType int shortcutType) {
- logAccessibilityShortcutActivated(componentName, shortcutType, UNKNOWN_STATUS);
+ public static void logAccessibilityShortcutActivated(Context context,
+ ComponentName componentName, @ShortcutType int shortcutType) {
+ logAccessibilityShortcutActivatedInternal(componentName,
+ convertToLoggingShortcutType(context, shortcutType), UNKNOWN_STATUS);
}
/**
- * Logs accessibility feature name that is assigned to the shortcut also its shortcut type and
- * enabled status. Calls this when clicking the shortcut
- * {@link AccessibilityManager#ACCESSIBILITY_BUTTON}
- * or {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY}
+ * Logs accessibility feature name that is assigned to the given {@code shortcutType} and the
+ * {@code serviceEnabled} status.
+ * Calls this when clicking the shortcut {@link AccessibilityManager#ACCESSIBILITY_BUTTON}
+ * or {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY}.
*
+ * @param context context used to retrieve the {@link Settings} provider
* @param componentName component name of the accessibility feature
* @param shortcutType accessibility shortcut type
* @param serviceEnabled {@code true} if the service is enabled
*/
- public static void logAccessibilityShortcutActivated(ComponentName componentName,
- @ShortcutType int shortcutType, boolean serviceEnabled) {
- logAccessibilityShortcutActivated(componentName, shortcutType,
+ public static void logAccessibilityShortcutActivated(Context context,
+ ComponentName componentName, @ShortcutType int shortcutType, boolean serviceEnabled) {
+ logAccessibilityShortcutActivatedInternal(componentName,
+ convertToLoggingShortcutType(context, shortcutType),
convertToLoggingServiceStatus(serviceEnabled));
}
/**
- * Logs accessibility feature name that is assigned to the shortcut also its shortcut type and
- * status code. Calls this when clicking the shortcut
- * {@link AccessibilityManager#ACCESSIBILITY_BUTTON}
- * or {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY}
+ * Logs accessibility feature name that is assigned to the given {@code loggingShortcutType} and
+ * {@code loggingServiceStatus} code.
*
- * @param componentName component name of the accessibility feature
- * @param shortcutType accessibility shortcut type {@link ShortcutType}
- * @param serviceStatus The service status code. 0 denotes unknown_status, 1 denotes enabled, 2
- * denotes disabled.
+ * @param componentName component name of the accessibility feature
+ * @param loggingShortcutType accessibility shortcut type for logging. 0 denotes
+ * unknown_type, 1 denotes accessibility button, 2 denotes volume
+ * key, 3 denotes triple tap on the screen, 4 denotes long press on
+ * accessibility button, 5 denotes accessibility floating menu.
+ * @param loggingServiceStatus The service status code for logging. 0 denotes unknown_status, 1
+ * denotes enabled, 2 denotes disabled.
*/
- private static void logAccessibilityShortcutActivated(ComponentName componentName,
- @ShortcutType int shortcutType, int serviceStatus) {
+ private static void logAccessibilityShortcutActivatedInternal(ComponentName componentName,
+ int loggingShortcutType, int loggingServiceStatus) {
FrameworkStatsLog.write(FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED,
- componentName.flattenToString(), convertToLoggingShortcutType(shortcutType),
- serviceStatus);
+ componentName.flattenToString(), loggingShortcutType, loggingServiceStatus);
}
/**
@@ -144,10 +152,19 @@
convertToLoggingMagnificationMode(mode));
}
- private static int convertToLoggingShortcutType(@ShortcutType int shortcutType) {
+ private static boolean isFloatingMenuEnabled(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_BUTTON_MODE, /* def= */ -1)
+ == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
+ }
+
+ private static int convertToLoggingShortcutType(Context context,
+ @ShortcutType int shortcutType) {
switch (shortcutType) {
case ACCESSIBILITY_BUTTON:
- return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON;
+ return isFloatingMenuEnabled(context)
+ ? ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_FLOATING_MENU
+ : ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON;
case ACCESSIBILITY_SHORTCUT_KEY:
return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__VOLUME_KEY;
}
diff --git a/core/java/com/android/internal/content/F2fsUtils.java b/core/java/com/android/internal/content/F2fsUtils.java
new file mode 100644
index 0000000..27f1b30
--- /dev/null
+++ b/core/java/com/android/internal/content/F2fsUtils.java
@@ -0,0 +1,296 @@
+/*
+ * 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.content;
+
+import android.annotation.NonNull;
+import android.content.ContentResolver;
+import android.os.Environment;
+import android.os.incremental.IncrementalManager;
+import android.provider.Settings.Secure;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility methods to work with the f2fs file system.
+ */
+public final class F2fsUtils {
+ private static final String TAG = "F2fsUtils";
+ private static final boolean DEBUG_F2FS = false;
+
+ /** Directory containing kernel features */
+ private static final File sKernelFeatures =
+ new File("/sys/fs/f2fs/features");
+ /** File containing features enabled on "/data" */
+ private static final File sUserDataFeatures =
+ new File("/dev/sys/fs/by-name/userdata/features");
+ private static final File sDataDirectory = Environment.getDataDirectory();
+ /** Name of the compression feature */
+ private static final String COMPRESSION_FEATURE = "compression";
+
+ private static final boolean sKernelCompressionAvailable;
+ private static final boolean sUserDataCompressionAvailable;
+
+ static {
+ sKernelCompressionAvailable = isCompressionEnabledInKernel();
+ if (!sKernelCompressionAvailable) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression DISABLED; feature not part of the kernel");
+ }
+ }
+ sUserDataCompressionAvailable = isCompressionEnabledOnUserData();
+ if (!sUserDataCompressionAvailable) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression DISABLED; feature not enabled on filesystem");
+ }
+ }
+ }
+
+ /**
+ * Releases compressed blocks from eligible installation artifacts.
+ * <p>
+ * Modern f2fs implementations starting in {@code S} support compression
+ * natively within the file system. The data blocks of specific installation
+ * artifacts [eg. .apk, .so, ...] can be compressed at the file system level,
+ * making them look and act like any other uncompressed file, but consuming
+ * a fraction of the space.
+ * <p>
+ * However, the unused space is not free'd automatically. Instead, we must
+ * manually tell the file system to release the extra blocks [the delta between
+ * the compressed and uncompressed block counts] back to the free pool.
+ * <p>
+ * Because of how compression works within the file system, once the blocks
+ * have been released, the file becomes read-only and cannot be modified until
+ * the free'd blocks have again been reserved from the free pool.
+ */
+ public static void releaseCompressedBlocks(ContentResolver resolver, File file) {
+ if (!sKernelCompressionAvailable || !sUserDataCompressionAvailable) {
+ return;
+ }
+
+ // NOTE: Retrieving this setting means we need to delay releasing cblocks
+ // of any APKs installed during the PackageManagerService constructor. Instead
+ // of being able to release them in the constructor, they can only be released
+ // immediately prior to the system being available. When we no longer need to
+ // read this setting, move cblock release back to the package manager constructor.
+ final boolean releaseCompressBlocks =
+ Secure.getInt(resolver, Secure.RELEASE_COMPRESS_BLOCKS_ON_INSTALL, 1) != 0;
+ if (!releaseCompressBlocks) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "SKIP; release compress blocks not enabled");
+ }
+ return;
+ }
+ if (!isCompressionAllowed(file)) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "SKIP; compression not allowed");
+ }
+ return;
+ }
+ final File[] files = getFilesToRelease(file);
+ if (files == null || files.length == 0) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "SKIP; no files to compress");
+ }
+ return;
+ }
+ for (int i = files.length - 1; i >= 0; --i) {
+ final long releasedBlocks = nativeReleaseCompressedBlocks(files[i].getAbsolutePath());
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "RELEASED " + releasedBlocks + " blocks"
+ + " from \"" + files[i] + "\"");
+ }
+ }
+ }
+
+ /**
+ * Returns {@code true} if compression is allowed on the file system containing
+ * the given file.
+ * <p>
+ * NOTE: The return value does not mean if the given file, or any other file
+ * on the same file system, is actually compressed. It merely determines whether
+ * not files <em>may</em> be compressed.
+ */
+ private static boolean isCompressionAllowed(@NonNull File file) {
+ final String filePath;
+ try {
+ filePath = file.getCanonicalPath();
+ } catch (IOException e) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression DISABLED; could not determine path");
+ }
+ return false;
+ }
+ if (IncrementalManager.isIncrementalPath(filePath)) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression DISABLED; file on incremental fs");
+ }
+ return false;
+ }
+ if (!isChild(sDataDirectory, filePath)) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression DISABLED; file not on /data");
+ }
+ return false;
+ }
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression ENABLED");
+ }
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if the given child is a descendant of the base.
+ */
+ private static boolean isChild(@NonNull File base, @NonNull String childPath) {
+ try {
+ base = base.getCanonicalFile();
+
+ File parentFile = new File(childPath).getCanonicalFile();
+ while (parentFile != null) {
+ if (base.equals(parentFile)) {
+ return true;
+ }
+ parentFile = parentFile.getParentFile();
+ }
+ return false;
+ } catch (IOException ignore) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns whether or not the compression feature is enabled in the kernel.
+ * <p>
+ * NOTE: This doesn't mean compression is enabled on a particular file system
+ * or any files have been compressed. Only that the functionality is enabled
+ * on the device.
+ */
+ private static boolean isCompressionEnabledInKernel() {
+ final File[] features = sKernelFeatures.listFiles();
+ if (features == null || features.length == 0) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; no kernel features");
+ }
+ return false;
+ }
+ for (int i = features.length - 1; i >= 0; --i) {
+ final File feature = features[i];
+ if (COMPRESSION_FEATURE.equals(features[i].getName())) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "FOUND kernel compression feature");
+ }
+ return true;
+ }
+ }
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; kernel compression feature not found");
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether or not the compression feature is enabled on user data [ie. "/data"].
+ * <p>
+ * NOTE: This doesn't mean any files have been compressed. Only that the functionality
+ * is enabled on the file system.
+ */
+ private static boolean isCompressionEnabledOnUserData() {
+ if (!sUserDataFeatures.exists()
+ || !sUserDataFeatures.isFile()
+ || !sUserDataFeatures.canRead()) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; filesystem features not available");
+ }
+ return false;
+ }
+ final List<String> configLines;
+ try {
+ configLines = Files.readAllLines(sUserDataFeatures.toPath());
+ } catch (IOException ignore) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; couldn't read filesystem features");
+ }
+ return false;
+ }
+ if (configLines == null
+ || configLines.size() > 1
+ || TextUtils.isEmpty(configLines.get(0))) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; no filesystem features");
+ }
+ return false;
+ }
+ final String[] features = configLines.get(0).split(",");
+ for (int i = features.length - 1; i >= 0; --i) {
+ if (COMPRESSION_FEATURE.equals(features[i].trim())) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "FOUND filesystem compression feature");
+ }
+ return true;
+ }
+ }
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; filesystem compression feature not found");
+ }
+ return false;
+ }
+
+ /**
+ * Returns all files contained within the directory at any depth from the given path.
+ */
+ private static List<File> getFilesRecursive(@NonNull File path) {
+ final File[] allFiles = path.listFiles();
+ if (allFiles == null) {
+ return null;
+ }
+ final ArrayList<File> files = new ArrayList<>();
+ for (File f : allFiles) {
+ if (f.isDirectory()) {
+ files.addAll(getFilesRecursive(f));
+ } else if (f.isFile()) {
+ files.add(f);
+ }
+ }
+ return files;
+ }
+
+ /**
+ * Returns all files contained within the directory at any depth from the given path.
+ */
+ private static File[] getFilesToRelease(@NonNull File codePath) {
+ final List<File> files = getFilesRecursive(codePath);
+ if (files == null) {
+ if (codePath.isFile()) {
+ return new File[] { codePath };
+ }
+ return null;
+ }
+ if (files.size() == 0) {
+ return null;
+ }
+ return files.toArray(new File[files.size()]);
+ }
+
+ private static native long nativeReleaseCompressedBlocks(String path);
+
+}
diff --git a/core/java/com/android/internal/content/OWNERS b/core/java/com/android/internal/content/OWNERS
new file mode 100644
index 0000000..c42bee6
--- /dev/null
+++ b/core/java/com/android/internal/content/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 36137
+include /core/java/android/content/pm/OWNERS
+
+per-file ReferrerIntent.aidl = file:/services/core/java/com/android/server/am/OWNERS
+per-file ReferrerIntent.java = file:/services/core/java/com/android/server/am/OWNERS
diff --git a/core/java/com/android/internal/display/BrightnessSynchronizer.java b/core/java/com/android/internal/display/BrightnessSynchronizer.java
index bd90890..19183b8 100644
--- a/core/java/com/android/internal/display/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/display/BrightnessSynchronizer.java
@@ -31,9 +31,6 @@
import android.util.MathUtils;
import android.view.Display;
-import java.util.LinkedList;
-import java.util.Queue;
-
/**
* BrightnessSynchronizer helps convert between the int (old) system and float
* (new) system for storing the brightness. It has methods to convert between the two and also
@@ -43,12 +40,11 @@
private static final int MSG_UPDATE_FLOAT = 1;
private static final int MSG_UPDATE_INT = 2;
+ private static final int MSG_UPDATE_BOTH = 3;
private static final String TAG = "BrightnessSynchronizer";
private static final Uri BRIGHTNESS_URI =
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
- private static final Uri BRIGHTNESS_FLOAT_URI =
- Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
// The tolerance within which we consider brightness values approximately equal to eachother.
// This value is approximately 1/3 of the smallest possible brightness value.
@@ -57,8 +53,6 @@
private DisplayManager mDisplayManager;
private final Context mContext;
- private final Queue<Object> mWriteHistory = new LinkedList<>();
-
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
@@ -69,6 +63,9 @@
case MSG_UPDATE_INT:
updateBrightnessIntFromFloat(Float.intBitsToFloat(msg.arg1));
break;
+ case MSG_UPDATE_BOTH:
+ updateBoth(Float.intBitsToFloat(msg.arg1));
+ break;
default:
super.handleMessage(msg);
}
@@ -139,7 +136,7 @@
/**
* Translates specified value from the float brightness system to the int brightness system,
- * given the min/max of each range. Accounts for special values such as OFF and invalid values.
+ * given the min/max of each range. Accounts for special values such as OFF and invalid values.
* Value returned as a float primitive (to preserve precision), but is a value within the
* int-system range.
*/
@@ -168,49 +165,63 @@
}
/**
- * Updates the float setting based on a passed in int value. This is called whenever the int
- * setting changes. mWriteHistory keeps a record of the values that been written to the settings
- * from either this method or updateBrightnessIntFromFloat. This is to ensure that the value
- * being set is due to an external value being set, rather than the updateBrightness* methods.
- * The intention of this is to avoid race conditions when the setting is being changed
- * frequently and to ensure we are not reacting to settings changes from this file.
+ * Updates the settings based on a passed in int value. This is called whenever the int
+ * setting changes. mPreferredSettingValue holds the most recently updated brightness value
+ * as a float that we would like the display to be set to.
+ *
+ * We then schedule an update to both the int and float settings, but, remove all the other
+ * messages to update all, to prevent us getting stuck in a loop.
+ *
* @param value Brightness value as int to store in the float setting.
*/
private void updateBrightnessFloatFromInt(int value) {
- Object topOfQueue = mWriteHistory.peek();
- if (topOfQueue != null && topOfQueue.equals(value)) {
- mWriteHistory.poll();
- } else {
- if (brightnessFloatToInt(mPreferredSettingValue) == value) {
- return;
- }
- float newBrightnessFloat = brightnessIntToFloat(value);
- mWriteHistory.offer(newBrightnessFloat);
- mPreferredSettingValue = newBrightnessFloat;
- mDisplayManager.setBrightness(Display.DEFAULT_DISPLAY, newBrightnessFloat);
+ if (brightnessFloatToInt(mPreferredSettingValue) == value) {
+ return;
}
+
+ mPreferredSettingValue = brightnessIntToFloat(value);
+ final int newBrightnessAsIntBits = Float.floatToIntBits(mPreferredSettingValue);
+ mHandler.removeMessages(MSG_UPDATE_BOTH);
+ mHandler.obtainMessage(MSG_UPDATE_BOTH, newBrightnessAsIntBits, 0).sendToTarget();
}
/**
- * Updates the int setting based on a passed in float value. This is called whenever the float
- * setting changes. mWriteHistory keeps a record of the values that been written to the settings
- * from either this method or updateBrightnessFloatFromInt. This is to ensure that the value
- * being set is due to an external value being set, rather than the updateBrightness* methods.
- * The intention of this is to avoid race conditions when the setting is being changed
- * frequently and to ensure we are not reacting to settings changes from this file.
+ * Updates the settings based on a passed in float value. This is called whenever the float
+ * setting changes. mPreferredSettingValue holds the most recently updated brightness value
+ * as a float that we would like the display to be set to.
+ *
+ * We then schedule an update to both the int and float settings, but, remove all the other
+ * messages to update all, to prevent us getting stuck in a loop.
+ *
* @param value Brightness setting as float to store in int setting.
*/
private void updateBrightnessIntFromFloat(float value) {
- int newBrightnessInt = brightnessFloatToInt(value);
- Object topOfQueue = mWriteHistory.peek();
- if (topOfQueue != null && topOfQueue.equals(value)) {
- mWriteHistory.poll();
- } else {
- mWriteHistory.offer(newBrightnessInt);
- mPreferredSettingValue = value;
+ if (floatEquals(mPreferredSettingValue, value)) {
+ return;
+ }
+
+ mPreferredSettingValue = value;
+ final int newBrightnessAsIntBits = Float.floatToIntBits(mPreferredSettingValue);
+ mHandler.removeMessages(MSG_UPDATE_BOTH);
+ mHandler.obtainMessage(MSG_UPDATE_BOTH, newBrightnessAsIntBits, 0).sendToTarget();
+ }
+
+
+ /**
+ * Updates both setting values if they have changed
+ * mDisplayManager.setBrightness automatically checks for changes
+ * Settings.System.putIntForUser needs to be checked, to prevent an extra callback to this class
+ *
+ * @param newBrightnessFloat Brightness setting as float to store in both settings
+ */
+ private void updateBoth(float newBrightnessFloat) {
+ int newBrightnessInt = brightnessFloatToInt(newBrightnessFloat);
+ mDisplayManager.setBrightness(Display.DEFAULT_DISPLAY, newBrightnessFloat);
+ if (getScreenBrightnessInt(mContext) != newBrightnessInt) {
Settings.System.putIntForUser(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS, newBrightnessInt, UserHandle.USER_CURRENT);
}
+
}
/**
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5dfc5fa..945a6ab 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -341,6 +341,19 @@
}
}
+ /**
+ * Listener for the battery stats reset.
+ */
+ public interface BatteryResetListener {
+
+ /**
+ * Callback invoked immediately prior to resetting battery stats.
+ */
+ void prepareForBatteryStatsReset();
+ }
+
+ private BatteryResetListener mBatteryResetListener;
+
public interface BatteryCallback {
public void batteryNeedsCpuUpdate();
public void batteryPowerChanged(boolean onBattery);
@@ -10736,6 +10749,10 @@
}
}
+ PowerProfile getPowerProfile() {
+ return mPowerProfile;
+ }
+
/**
* Starts tracking CPU time-in-state for threads of the system server process,
* keeping a separate account of threads receiving incoming binder calls.
@@ -11184,6 +11201,10 @@
mDischargeCounter.reset(false, elapsedRealtimeUs);
}
+ public void setBatteryResetListener(BatteryResetListener batteryResetListener) {
+ mBatteryResetListener = batteryResetListener;
+ }
+
public void resetAllStatsCmdLocked() {
final long mSecUptime = mClocks.uptimeMillis();
long uptimeUs = mSecUptime * 1000;
@@ -11219,6 +11240,10 @@
}
private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis) {
+ if (mBatteryResetListener != null) {
+ mBatteryResetListener.prepareForBatteryStatsReset();
+ }
+
final long uptimeUs = uptimeMillis * 1000;
final long elapsedRealtimeUs = elapsedRealtimeMillis * 1000;
mStartCount = 0;
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index 3aaccdd..8943db6 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -38,14 +38,24 @@
public class BatteryUsageStatsProvider {
private final Context mContext;
private final BatteryStats mStats;
+ private final BatteryUsageStatsStore mBatteryUsageStatsStore;
private final PowerProfile mPowerProfile;
private final Object mLock = new Object();
private List<PowerCalculator> mPowerCalculators;
public BatteryUsageStatsProvider(Context context, BatteryStats stats) {
+ this(context, stats, null);
+ }
+
+ @VisibleForTesting
+ public BatteryUsageStatsProvider(Context context, BatteryStats stats,
+ BatteryUsageStatsStore batteryUsageStatsStore) {
mContext = context;
mStats = stats;
- mPowerProfile = new PowerProfile(mContext);
+ mBatteryUsageStatsStore = batteryUsageStatsStore;
+ mPowerProfile = stats instanceof BatteryStatsImpl
+ ? ((BatteryStatsImpl) stats).getPowerProfile()
+ : new PowerProfile(context);
}
private List<PowerCalculator> getPowerCalculators() {
@@ -126,6 +136,15 @@
private BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query,
long currentTimeMs) {
+ if (query.getToTimestamp() == 0) {
+ return getCurrentBatteryUsageStats(query, currentTimeMs);
+ } else {
+ return getAggregatedBatteryUsageStats(query);
+ }
+ }
+
+ private BatteryUsageStats getCurrentBatteryUsageStats(BatteryUsageStatsQuery query,
+ long currentTimeMs) {
final long realtimeUs = elapsedRealtime() * 1000;
final long uptimeUs = uptimeMillis() * 1000;
@@ -209,6 +228,25 @@
BatteryStats.STATS_SINCE_CHARGED) / 1000;
}
+ private BatteryUsageStats getAggregatedBatteryUsageStats(BatteryUsageStatsQuery query) {
+ final boolean includePowerModels = (query.getFlags()
+ & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0;
+
+ final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(
+ mStats.getCustomEnergyConsumerNames(), includePowerModels);
+ final long[] timestamps = mBatteryUsageStatsStore.listBatteryUsageStatsTimestamps();
+ for (long timestamp : timestamps) {
+ if (timestamp > query.getFromTimestamp() && timestamp <= query.getToTimestamp()) {
+ final BatteryUsageStats snapshot =
+ mBatteryUsageStatsStore.loadBatteryUsageStats(timestamp);
+ if (snapshot != null) {
+ builder.add(snapshot);
+ }
+ }
+ }
+ return builder.build();
+ }
+
private long elapsedRealtime() {
if (mStats instanceof BatteryStatsImpl) {
return ((BatteryStatsImpl) mStats).mClocks.elapsedRealtime();
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsStore.java b/core/java/com/android/internal/os/BatteryUsageStatsStore.java
new file mode 100644
index 0000000..5c97602
--- /dev/null
+++ b/core/java/com/android/internal/os/BatteryUsageStatsStore.java
@@ -0,0 +1,285 @@
+/*
+ * 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;
+import android.content.Context;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.Handler;
+import android.util.AtomicFile;
+import android.util.LongArray;
+import android.util.Slog;
+import android.util.TypedXmlPullParser;
+import android.util.TypedXmlSerializer;
+import android.util.Xml;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.StandardOpenOption;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+
+/**
+ * A storage mechanism for BatteryUsageStats snapshots.
+ */
+public class BatteryUsageStatsStore {
+ private static final String TAG = "BatteryUsageStatsStore";
+
+ private static final List<BatteryUsageStatsQuery> BATTERY_USAGE_STATS_QUERY = List.of(
+ new BatteryUsageStatsQuery.Builder()
+ .setMaxStatsAgeMs(0)
+ .includePowerModels()
+ .build());
+ private static final String BATTERY_USAGE_STATS_DIR = "battery-usage-stats";
+ private static final String SNAPSHOT_FILE_EXTENSION = ".bus";
+ private static final String DIR_LOCK_FILENAME = ".lock";
+ private static final String CONFIG_FILENAME = "config";
+ private static final String BATTERY_USAGE_STATS_BEFORE_RESET_TIMESTAMP_PROPERTY =
+ "BATTERY_USAGE_STATS_BEFORE_RESET_TIMESTAMP";
+ private static final long MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES = 100 * 1024;
+
+ private final Context mContext;
+ private final BatteryStatsImpl mBatteryStats;
+ private final File mStoreDir;
+ private final File mLockFile;
+ private final AtomicFile mConfigFile;
+ private final long mMaxStorageBytes;
+ private final Handler mHandler;
+ private final BatteryUsageStatsProvider mBatteryUsageStatsProvider;
+
+ public BatteryUsageStatsStore(Context context, BatteryStatsImpl stats, File systemDir,
+ Handler handler) {
+ this(context, stats, systemDir, handler, MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES);
+ }
+
+ @VisibleForTesting
+ public BatteryUsageStatsStore(Context context, BatteryStatsImpl batteryStats, File systemDir,
+ Handler handler, long maxStorageBytes) {
+ mContext = context;
+ mBatteryStats = batteryStats;
+ mStoreDir = new File(systemDir, BATTERY_USAGE_STATS_DIR);
+ mLockFile = new File(mStoreDir, DIR_LOCK_FILENAME);
+ mConfigFile = new AtomicFile(new File(mStoreDir, CONFIG_FILENAME));
+ mHandler = handler;
+ mMaxStorageBytes = maxStorageBytes;
+ mBatteryStats.setBatteryResetListener(this::prepareForBatteryStatsReset);
+ mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(mContext, mBatteryStats);
+ }
+
+ private void prepareForBatteryStatsReset() {
+ final List<BatteryUsageStats> stats =
+ mBatteryUsageStatsProvider.getBatteryUsageStats(BATTERY_USAGE_STATS_QUERY);
+ if (stats.isEmpty()) {
+ Slog.wtf(TAG, "No battery usage stats generated");
+ return;
+ }
+
+ mHandler.post(() -> storeBatteryUsageStats(stats.get(0)));
+ }
+
+ private void storeBatteryUsageStats(BatteryUsageStats stats) {
+ try (FileLock lock = lockSnapshotDirectory()) {
+ if (!mStoreDir.exists()) {
+ if (!mStoreDir.mkdirs()) {
+ Slog.e(TAG,
+ "Could not create a directory for battery usage stats snapshots");
+ return;
+ }
+ }
+ File file = makeSnapshotFilename(stats.getStatsEndTimestamp());
+ try {
+ writeXmlFileLocked(stats, file);
+ } catch (Exception e) {
+ Slog.e(TAG, "Cannot save battery usage stats", e);
+ }
+
+ removeOldSnapshotsLocked();
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot lock battery usage stats directory", e);
+ }
+ }
+
+ /**
+ * Returns the timestamps of the stored BatteryUsageStats snapshots. The timestamp corresponds
+ * to the time the snapshot was taken {@link BatteryUsageStats#getStatsEndTimestamp()}.
+ */
+ public long[] listBatteryUsageStatsTimestamps() {
+ LongArray timestamps = new LongArray(100);
+ try (FileLock lock = lockSnapshotDirectory()) {
+ for (File file : mStoreDir.listFiles()) {
+ String fileName = file.getName();
+ if (fileName.endsWith(SNAPSHOT_FILE_EXTENSION)) {
+ try {
+ String fileNameWithoutExtension = fileName.substring(0,
+ fileName.length() - SNAPSHOT_FILE_EXTENSION.length());
+ timestamps.add(Long.parseLong(fileNameWithoutExtension));
+ } catch (NumberFormatException e) {
+ Slog.wtf(TAG, "Invalid format of BatteryUsageStats snapshot file name: "
+ + fileName);
+ }
+ }
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot lock battery usage stats directory", e);
+ }
+ return timestamps.toArray();
+ }
+
+ /**
+ * Reads the specified snapshot of BatteryUsageStats. Returns null if the snapshot
+ * does not exist.
+ */
+ @Nullable
+ public BatteryUsageStats loadBatteryUsageStats(long timestamp) {
+ try (FileLock lock = lockSnapshotDirectory()) {
+ File file = makeSnapshotFilename(timestamp);
+ try {
+ return readXmlFileLocked(file);
+ } catch (Exception e) {
+ Slog.e(TAG, "Cannot read battery usage stats", e);
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot lock battery usage stats directory", e);
+ }
+ return null;
+ }
+
+ /**
+ * Saves the supplied timestamp of the BATTERY_USAGE_STATS_BEFORE_RESET statsd atom pull
+ * in persistent file.
+ */
+ public void setLastBatteryUsageStatsBeforeResetAtomPullTimestamp(long timestamp) {
+ Properties props = new Properties();
+ try (FileLock lock = lockSnapshotDirectory()) {
+ try (InputStream in = mConfigFile.openRead()) {
+ props.load(in);
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot load config file " + mConfigFile, e);
+ }
+ props.put(BATTERY_USAGE_STATS_BEFORE_RESET_TIMESTAMP_PROPERTY,
+ String.valueOf(timestamp));
+ FileOutputStream out = null;
+ try {
+ out = mConfigFile.startWrite();
+ props.store(out, "Statsd atom pull timestamps");
+ mConfigFile.finishWrite(out);
+ } catch (IOException e) {
+ mConfigFile.failWrite(out);
+ Slog.e(TAG, "Cannot save config file " + mConfigFile, e);
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot lock battery usage stats directory", e);
+ }
+ }
+
+ /**
+ * Retrieves the previously saved timestamp of the last BATTERY_USAGE_STATS_BEFORE_RESET
+ * statsd atom pull.
+ */
+ public long getLastBatteryUsageStatsBeforeResetAtomPullTimestamp() {
+ Properties props = new Properties();
+ try (FileLock lock = lockSnapshotDirectory()) {
+ try (InputStream in = mConfigFile.openRead()) {
+ props.load(in);
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot load config file " + mConfigFile, e);
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot lock battery usage stats directory", e);
+ }
+ return Long.parseLong(
+ props.getProperty(BATTERY_USAGE_STATS_BEFORE_RESET_TIMESTAMP_PROPERTY, "0"));
+ }
+
+ private FileLock lockSnapshotDirectory() throws IOException {
+ mLockFile.getParentFile().mkdirs();
+ mLockFile.createNewFile();
+ return FileChannel.open(mLockFile.toPath(), StandardOpenOption.WRITE).lock();
+ }
+
+ /**
+ * Creates a file name by formatting the timestamp as 19-digit zero-padded number.
+ * This ensures that sorted directory list follows the chronological order.
+ */
+ private File makeSnapshotFilename(long statsEndTimestamp) {
+ return new File(mStoreDir, String.format(Locale.ENGLISH, "%019d", statsEndTimestamp)
+ + SNAPSHOT_FILE_EXTENSION);
+ }
+
+ private void writeXmlFileLocked(BatteryUsageStats stats, File file) throws IOException {
+ try (OutputStream out = new FileOutputStream(file)) {
+ TypedXmlSerializer serializer = Xml.newBinarySerializer();
+ serializer.setOutput(out, StandardCharsets.UTF_8.name());
+ serializer.startDocument(null, true);
+ stats.writeXml(serializer);
+ serializer.endDocument();
+ }
+ }
+
+ private BatteryUsageStats readXmlFileLocked(File file)
+ throws IOException, XmlPullParserException {
+ try (InputStream in = new FileInputStream(file)) {
+ TypedXmlPullParser parser = Xml.newBinaryPullParser();
+ parser.setInput(in, StandardCharsets.UTF_8.name());
+ return BatteryUsageStats.createFromXml(parser);
+ }
+ }
+
+ private void removeOldSnapshotsLocked() {
+ // Read the directory list into a _sorted_ map. The alphanumeric ordering
+ // corresponds to the historical order of snapshots because the file names
+ // are timestamps zero-padded to the same length.
+ long totalSize = 0;
+ TreeMap<File, Long> mFileSizes = new TreeMap<>();
+ for (File file : mStoreDir.listFiles()) {
+ final long fileSize = file.length();
+ totalSize += fileSize;
+ if (file.getName().endsWith(SNAPSHOT_FILE_EXTENSION)) {
+ mFileSizes.put(file, fileSize);
+ }
+ }
+
+ while (totalSize > mMaxStorageBytes) {
+ final Map.Entry<File, Long> entry = mFileSizes.firstEntry();
+ if (entry == null) {
+ break;
+ }
+
+ File file = entry.getKey();
+ if (!file.delete()) {
+ Slog.e(TAG, "Cannot delete battery usage stats " + file);
+ }
+ totalSize -= entry.getValue();
+ mFileSizes.remove(file);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/EmphasizedNotificationButton.java b/core/java/com/android/internal/widget/EmphasizedNotificationButton.java
index 4460e4a..ce6af49 100644
--- a/core/java/com/android/internal/widget/EmphasizedNotificationButton.java
+++ b/core/java/com/android/internal/widget/EmphasizedNotificationButton.java
@@ -40,6 +40,7 @@
@RemoteViews.RemoteView
public class EmphasizedNotificationButton extends Button {
private final RippleDrawable mRipple;
+ private final GradientDrawable mBackground;
private boolean mPriority;
public EmphasizedNotificationButton(Context context) {
@@ -57,9 +58,10 @@
public EmphasizedNotificationButton(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- DrawableWrapper background = (DrawableWrapper) getBackground().mutate();
- mRipple = (RippleDrawable) background.getDrawable();
+ mRipple = (RippleDrawable) getBackground();
mRipple.mutate();
+ DrawableWrapper inset = (DrawableWrapper) mRipple.getDrawable(0);
+ mBackground = (GradientDrawable) inset.getDrawable();
}
@RemotableViewMethod
@@ -70,8 +72,7 @@
@RemotableViewMethod
public void setButtonBackground(ColorStateList color) {
- GradientDrawable inner = (GradientDrawable) mRipple.getDrawable(0);
- inner.setColor(color);
+ mBackground.setColor(color);
invalidate();
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 68388d98..125182c 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -84,6 +84,7 @@
android: {
srcs: [
"AndroidRuntime.cpp",
+ "com_android_internal_content_F2fsUtils.cpp",
"com_android_internal_content_NativeLibraryHelper.cpp",
"com_google_android_gles_jni_EGLImpl.cpp",
"com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 3debb3e..443bfce 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -189,6 +189,7 @@
extern int register_android_content_res_Configuration(JNIEnv* env);
extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
extern int register_android_security_Scrypt(JNIEnv *env);
+extern int register_com_android_internal_content_F2fsUtils(JNIEnv* env);
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
@@ -1624,6 +1625,7 @@
REG_JNI(register_android_animation_PropertyValuesHolder),
REG_JNI(register_android_security_Scrypt),
+ REG_JNI(register_com_android_internal_content_F2fsUtils),
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
REG_JNI(register_com_android_internal_os_DmabufInfoReader),
REG_JNI(register_com_android_internal_os_FuseAppLoop),
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index e47f18a..365a18d 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -566,8 +566,9 @@
env->ReleaseStringChars(clientPackageName,
reinterpret_cast<const jchar*>(rawClientName));
- sp<Camera> camera =
- Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID, Camera::USE_CALLING_PID);
+ int targetSdkVersion = android_get_application_target_sdk_version();
+ sp<Camera> camera = Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID,
+ Camera::USE_CALLING_PID, targetSdkVersion);
if (camera == NULL) {
return -EACCES;
}
diff --git a/core/jni/com_android_internal_content_F2fsUtils.cpp b/core/jni/com_android_internal_content_F2fsUtils.cpp
new file mode 100644
index 0000000..8b9d59c
--- /dev/null
+++ b/core/jni/com_android_internal_content_F2fsUtils.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "F2fsUtils"
+
+#include "core_jni_helpers.h"
+
+#include <nativehelper/ScopedUtfChars.h>
+#include <nativehelper/jni_macros.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <linux/f2fs.h>
+#include <linux/fs.h>
+
+#include <android-base/unique_fd.h>
+
+#include <utils/Log.h>
+
+#include <errno.h>
+#include <fcntl.h>
+
+#include <array>
+
+using namespace std::literals;
+
+namespace android {
+
+static jlong com_android_internal_content_F2fsUtils_nativeReleaseCompressedBlocks(JNIEnv *env,
+ jclass clazz,
+ jstring path) {
+ unsigned long long blkcnt;
+ int ret;
+ ScopedUtfChars filePath(env, path);
+
+ android::base::unique_fd fd(open(filePath.c_str(), O_RDONLY | O_CLOEXEC, 0));
+ if (fd < 0) {
+ ALOGW("Failed to open file: %s (%d)\n", filePath.c_str(), errno);
+ return 0;
+ }
+
+ long flags = 0;
+ ret = ioctl(fd, FS_IOC_GETFLAGS, &flags);
+ if (ret < 0) {
+ ALOGW("Failed to get flags for file: %s (%d)\n", filePath.c_str(), errno);
+ return 0;
+ }
+ if ((flags & FS_COMPR_FL) == 0) {
+ return 0;
+ }
+
+ ret = ioctl(fd, F2FS_IOC_RELEASE_COMPRESS_BLOCKS, &blkcnt);
+ if (ret < 0) {
+ return -errno;
+ }
+ return blkcnt;
+}
+
+static const std::array gMethods = {
+ MAKE_JNI_NATIVE_METHOD(
+ "nativeReleaseCompressedBlocks", "(Ljava/lang/String;)J",
+ com_android_internal_content_F2fsUtils_nativeReleaseCompressedBlocks),
+};
+
+int register_com_android_internal_content_F2fsUtils(JNIEnv *env) {
+ return RegisterMethodsOrDie(env, "com/android/internal/content/F2fsUtils", gMethods.data(),
+ gMethods.size());
+}
+
+}; // namespace android
diff --git a/core/res/res/drawable/btn_notification_emphasized.xml b/core/res/res/drawable/btn_notification_emphasized.xml
index 63707ab..29c51f2a 100644
--- a/core/res/res/drawable/btn_notification_emphasized.xml
+++ b/core/res/res/drawable/btn_notification_emphasized.xml
@@ -15,13 +15,13 @@
~ limitations under the License
-->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="@dimen/button_inset_horizontal_material"
- android:insetTop="@dimen/button_inset_vertical_material"
- android:insetRight="@dimen/button_inset_horizontal_material"
- android:insetBottom="@dimen/button_inset_vertical_material">
- <ripple android:color="?attr/colorControlHighlight">
- <item>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?attr/colorControlHighlight">
+ <item>
+ <inset
+ android:insetLeft="@dimen/button_inset_horizontal_material"
+ android:insetTop="@dimen/button_inset_vertical_material"
+ android:insetRight="@dimen/button_inset_horizontal_material"
+ android:insetBottom="@dimen/button_inset_vertical_material">
<shape android:shape="rectangle">
<corners android:radius="@dimen/notification_action_button_radius" />
<padding android:left="12dp"
@@ -30,6 +30,6 @@
android:bottom="@dimen/button_padding_vertical_material" />
<solid android:color="@color/white" />
</shape>
- </item>
- </ripple>
-</inset>
+ </inset>
+ </item>
+</ripple>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 85de02e..803ba64 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Teks na knipbord gekopieër."</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> van jou knipbord af geplak"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> het van jou knipbord af geplak"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> het teks geplak wat jy gekopieer het"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> het \'n prent geplak wat jy gekopieer het"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> het inhoud geplak wat jy gekopieer het"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Laat \'n program toe om te versoek dat pakkette uitgevee word."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"vra om batteryoptimerings te ignoreer"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Laat \'n program toe om toestemming te vra om batteryoptimerings vir daardie program ignoreer."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"navraag oor alle pakkette"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Laat \'n program toe om alle geïnstalleerde pakette te sien."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Klop twee keer vir zoembeheer"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Kon nie legstuk byvoeg nie."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Gaan"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 18cc4c6..e5ef55a 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"አንድ መተግበሪያ የጥቅሎች ስረዛን እንዲጠይቅ ይፈቅዳል።"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"የባትሪ ማትባቶችን ችላ ለማለት መጠየቅ"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"አንድ መተግበሪያ ለዚያ መተግበሪያ የባትሪ ማትባቶችን ችላ ለማለት እንዲጠይቅ ይፈቅድለታል።"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"ሁሉንም ጥቅሎች ይጠይቁ"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"አንድ መተግበሪያ ሁሉንም የተጫኑ ጥቅሎችን እንዲያይ ይፈቅድለታል።"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ለአጉላ መቆጣጠሪያ ሁለት ጊዜ ነካ አድርግ"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ምግብር ማከል አልተቻለም።"</string>
<string name="ime_action_go" msgid="5536744546326495436">"ሂድ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 1d7ce15..86a09ee 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1538,10 +1538,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"للسماح لتطبيق ما بطلب حذف الحِزم."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"طلب تجاهل تحسينات البطارية"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"للسماح للتطبيق بطلب الإذن لتجاهل تحسينات البطارية في هذا التطبيق."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"طلب البحث في كل الحِزم"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"يسمح هذا الإذن للتطبيق بعرض كل الحِزم المثبّتة."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"اضغط مرتين للتحكم في التكبير أو التصغير"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"تعذرت إضافة أداة."</string>
<string name="ime_action_go" msgid="5536744546326495436">"تنفيذ"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index b1bf980..5b2149e 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"এপটোক পেকেজবোৰ মচাৰ অনুৰোধ কৰিবলৈ দিয়ে।"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"বেটাৰি অপ্টিমাইজেশ্বন উপেক্ষা কৰিবলৈ বিচাৰক"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"কোনো এপক সেই এপটোৰ বাবে বেটাৰি অপ্টিমাইজেশ্বন উপেক্ষা কৰিবলৈ অনুমতি বিচাৰিবলৈ দিয়ে।"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"আটাইবোৰ পেকেজত প্ৰশ্ন সোধক"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"এপক আটাইবোৰ ইনষ্টল কৰি থোৱা পেকেজ চাবলৈ দিয়ে।"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"জুম নিয়ন্ত্ৰণ কৰিবলৈ দুবাৰ টিপক"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ৱিজেট যোগ কৰিব পৰা নগ\'ল।"</string>
<string name="ime_action_go" msgid="5536744546326495436">"যাওক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index af66b0b..54dc932 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Mətn panoya kopyalandı."</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> mübadilə buferinizdən əlavə edilib"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> datanı panodan əlavə edib"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kopyaladığınız mətni əlavə etdi"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kopyaladığınız şəkli əlavə etdi"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kopyaladığınız kontenti əlavə etdi"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Tətbiqə paketlərin silinməsi sorğusunu göndərməyə icazə verir."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"batareya optimallaşdırmasını iqnor etmək üçün soruşun"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Tatareya optimallaşdırılmasını o tətbiq üçün iqnor edilməsinə icazə vermək məqsədilə soruşmağa tətbiqə icazə verilir."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"bütün paketlər üçün sorğu göndərin"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Tətbiqə bütün quraşdırılmış paketləri görmək icazəsi verir."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Zoom kontrolu üçün iki dəfə toxunun"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Widget əlavə edilə bilmədi."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Get"</string>
@@ -1992,7 +1990,7 @@
<string name="pin_specific_target" msgid="7824671240625957415">"İşarələyin: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Çıxarın"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"İşarələməyin: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="app_info" msgid="6113278084877079851">"Tətbiq infosu"</string>
+ <string name="app_info" msgid="6113278084877079851">"Tətbiq haqqında"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demo başlayır…"</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"Cihaz sıfırlanır…"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 4cc46d9..ff2289f 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -365,11 +365,11 @@
<string name="permlab_receiveMms" msgid="4000650116674380275">"prijem tekstualnih poruka (MMS)"</string>
<string name="permdesc_receiveMms" msgid="958102423732219710">"Dozvoljava aplikaciji da prima i obrađuje MMS poruke. To znači da aplikacija može da nadgleda ili briše poruke koje se šalju uređaju, a da vam ih ne prikaže."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Prosleđivanje poruka za mobilne uređaje na lokalitetu"</string>
- <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Dozvoljava aplikaciji da se vezuje za modul poruka za mobilne uređaje na lokalitetu da bi prosleđivala poruke za mobilne uređaje na lokalitetu onako kako su primljene. Obaveštenja poruka za mobilne uređaje na lokalitetu se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju rad uređaja kada se primi poruka o hitnom slučaju za mobilne uređaje na lokalitetu."</string>
+ <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Dozvoljava aplikaciji da se vezuje za modul poruka za mobilne uređaje na lokalitetu da bi prosleđivala poruke za mobilne uređaje na lokalitetu onako kako su primljene. Obaveštenja poruka za mobilne uređaje na lokalitetu se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na performanse ili ometaju rad uređaja kada se primi poruka o hitnom slučaju za mobilne uređaje na lokalitetu."</string>
<string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje odlaznim pozivima"</string>
<string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Omogućava aplikaciji da vidi detalje o odlaznim pozivima na uređaju i da kontroliše te pozive."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čitanje poruka info servisa"</string>
- <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućava aplikaciji da čita poruke info servisa koje uređaj prima. Upozorenja info servisa se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju funkcionisanje uređaja kada se primi poruka info servisa o hitnom slučaju."</string>
+ <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućava aplikaciji da čita poruke info servisa koje uređaj prima. Upozorenja info servisa se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na performanse ili ometaju funkcionisanje uređaja kada se primi poruka info servisa o hitnom slučaju."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čitanje prijavljenih fidova"</string>
<string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"Dozvoljava aplikaciji da preuzima detalje o trenutno sinhronizovanim fidovima."</string>
<string name="permlab_sendSms" msgid="7757368721742014252">"šalje i pregleda SMS poruke"</string>
@@ -1022,7 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Tekst je kopiran u privremenu memoriju."</string>
<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="7355790625710831847">"Sadržaj aplikacije <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je nalepljen u privr. memoriju"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je prelepio/la iz privremene memorije"</string>
<string name="pasted_text" msgid="4298871641549173733">"Aplikacija<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je nalepila tekst koji ste kopirali"</string>
<string name="pasted_image" msgid="4729097394781491022">"Aplikacija<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je nalepila sliku koju ste kopirali"</string>
<string name="pasted_content" msgid="646276353060777131">"Aplikacija<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je nalepila sadržaj koji ste kopirali"</string>
@@ -1283,7 +1283,7 @@
<string name="heavy_weight_notification" msgid="8382784283600329576">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> je pokrenuta"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Dodirnite da biste se vratili u igru"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Odaberite igru"</string>
- <string name="heavy_weight_switcher_text" msgid="6814316627367160126">"Da bi učinak bio bolji, možete da otvorite samo jednu od ovih igara odjednom."</string>
+ <string name="heavy_weight_switcher_text" msgid="6814316627367160126">"Da bi performanse bile bolje, može da bude otvorena samo jedna od ovih igara."</string>
<string name="old_app_action" msgid="725331621042848590">"Nazad na <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
<string name="new_app_action" msgid="547772182913269801">"Otvori <xliff:g id="NEW_APP">%1$s</xliff:g>"</string>
<string name="new_app_description" msgid="1958903080400806644">"<xliff:g id="OLD_APP">%1$s</xliff:g> će se zatvoriti bez čuvanja"</string>
@@ -1395,7 +1395,7 @@
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Omogućen je režim probnog korišćenja"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Obavite resetovanje na fabrička podešavanja da biste onemogućili režim probnog korišćenja."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"Serijska konzola je omogućena"</string>
- <string name="console_running_notification_message" msgid="7892751888125174039">"Učinak je smanjen. Da biste onemogući konzolu, proverite pokretački program."</string>
+ <string name="console_running_notification_message" msgid="7892751888125174039">"Performanse su smanjene. Da biste onemogući konzolu, proverite pokretački program."</string>
<string name="usb_contaminant_detected_title" msgid="4359048603069159678">"Tečnost ili nečistoća u USB portu"</string>
<string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB port je automatski isključen. Dodirnite da biste saznali više."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"Korišćenje USB porta je dozvoljeno"</string>
@@ -1478,10 +1478,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Omogućava da aplikacija zahteva brisanje paketa."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"traženje dozvole za ignorisanje optimizacija baterije"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Dozvoljava aplikaciji da traži dozvolu za ignorisanje optimizacija baterije za tu aplikaciju."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"slanje upita za sve pakete"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Dozvoljava aplikaciji da vidi sve instalirane pakete."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Dodirnite dvaput za kontrolu zumiranja"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Nije moguće dodati vidžet."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Idi"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 1423737..b6ba47a 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1025,7 +1025,7 @@
<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="7355790625710831847">"Праграма (\"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\") уставіла даныя з буфера абмену"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Праграма \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\" уставіла даныя з буфера абмену"</string>
<string name="pasted_text" msgid="4298871641549173733">"Скапіраваны вамі тэкст устаўлены праграмай \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\""</string>
<string name="pasted_image" msgid="4729097394781491022">"Скапіраваны вамі відарыс устаўлены праграмай \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\""</string>
<string name="pasted_content" msgid="646276353060777131">"Скапіраванае вамі змесціва ўстаўлена праграмай \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\""</string>
@@ -1498,10 +1498,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Дазваляе праграме запытваць выдаленне пакетаў."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"запытваць дазвол на ігнараванне аптымізацыі акумулятара"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Дазваляе праграме запытваць дазвол на ігнараванне аптымізацыі акумулятара для гэтай праграмы."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"запыт усіх пакетаў"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Дазваляе праграме выяўляць усе ўсталяваныя пакеты."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Націсніце двойчы, каб кіраваць маштабаваннем"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Немагчыма дадаць віджэт."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Пачаць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 92e1a86..9ab5dfe 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Разрешава на приложението да заявява изтриване на пакети."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"искане за пренебрегване на оптимизациите на батерията"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Разрешава на дадено приложение да иска разрешение за пренебрегване на свързаните с него оптимизации на батерията."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"заявка за всички пакети"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Разрешава на приложението да вижда всички инсталирани пакети."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Докоснете двукратно за управление на промяната на мащаба"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Приспособлението не можа да бъде добавено."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Старт"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index f811ac2..2d7003b 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1478,10 +1478,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Omogućava aplikaciji da zatraži brisanje paketa."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"traži zanemarivanje optimizacije baterije"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Omogućava aplikaciji da traži odobrenje za zanemarivanje optimizacije baterije za tu aplikaciju."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"upit za sve pakete"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Omogućava aplikaciji da pregleda sve instalirane pakete."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Dodirnite dvaput za kontrolu uvećanja"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Dodavanje vidžeta nije uspjelo."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Započni"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 19762bf..330713d 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Text copiat al Porta-retalls."</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha enganxat contingut del porta-retalls"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha enganxat dades del porta-retalls"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha enganxat text que has copiat"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha enganxat una imatge que has copiat"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha enganxat contingut que has copiat"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Permet que una aplicació sol·liciti la supressió de paquets."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"Demanar permís per ignorar les optimitzacions de bateria"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Permet que una aplicació demani permís per ignorar les optimitzacions de bateria per a l\'aplicació."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"consultar tots els paquets"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Permet que una aplicació vegi els paquets instal·lats."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Piqueu dos cops per controlar el zoom"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"No s\'ha pogut afegir el widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Ves"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 95b2b55..c4eb66e 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1498,10 +1498,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Umožňuje aplikaci požádat o smazání balíčků."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"požádat o ignorování optimalizace využití baterie"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Povoluje aplikaci požádat o oprávnění ignorovat optimalizaci využití baterie, která pro ni je nastavena."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"zjistit všechny balíčky"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Umožňuje aplikaci načíst všechny nainstalované balíčky."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Poklepáním můžete ovládat přiblížení"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Widget nelze přidat."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Přejít"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 79379f1..2708487 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Tillader, at en app anmoder om sletning af pakker."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"bede om at ignorere batterioptimeringer"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Gør det muligt for en app at bede om tilladelse til at ignorere batterioptimeringer for den pågældende app."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"forespørg om alle pakker"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Giver en app tilladelse til at se alle installerede pakker."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tryk to gange for zoomkontrol"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Widget kunne ikke tilføjes."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Gå"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b8727e8..03b9904 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Text in Zwischenablage kopiert."</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> aus der Zwischenablage eingefügt"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> hat Informationen aus der Zwischenablage eingefügt"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> hat einen von dir kopierten Text eingefügt"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> hat ein von dir kopiertes Bild eingefügt"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> hat den von dir kopierten Inhalt eingefügt"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Ermöglicht der App, das Löschen von Paketen anzufordern."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"fragen, ob Akku-Leistungsoptimierungen ignoriert werden können"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Erlaubt einer App, nach der Berechtigung zum Ignorieren der Akku-Leistungsoptimierungen zu fragen."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"Alle Pakete abfragen"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Ermöglicht der App, alle installierten Pakete zu sehen."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Für Zoomeinstellung zweimal berühren"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Widget konnte nicht hinzugefügt werden."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Los"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 2aa10e5..fce9d98 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Επιτρέπει σε μια εφαρμογή να ζητά διαγραφή πακέτων."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"αίτημα αγνόησης βελτιστοποιήσεων μπαταρίας"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Επιτρέπει σε μια εφαρμογή να ζητήσει άδεια για την αγνόηση βελτιστοποιήσεων της μπαταρίας για τη συγκεκριμένη εφαρμογή."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"υποβολή ερωτήματος σε όλα τα πακέτα"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Επιτρέπει σε μια εφαρμογή να βλέπει όλα τα εγκατεστημένα πακέτα."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Πατήστε δύο φορές για έλεγχο εστίασης"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Δεν ήταν δυνατή η προσθήκη του γραφικού στοιχείου."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Μετάβαση"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 0817cb5..805f344 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Allows an application to request deletion of packages."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ask to ignore battery optimisations"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Allows an app to ask for permission to ignore battery optimisations for that app."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"query all packages"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Allows an app to see all installed packages."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Go"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 6e3b041..86ddb1f 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Allows an application to request deletion of packages."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ask to ignore battery optimisations"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Allows an app to ask for permission to ignore battery optimisations for that app."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"query all packages"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Allows an app to see all installed packages."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Go"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 74973c4..da1c49a 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Allows an application to request deletion of packages."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ask to ignore battery optimisations"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Allows an app to ask for permission to ignore battery optimisations for that app."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"query all packages"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Allows an app to see all installed packages."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Go"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8fe3f42..eeedf21 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Allows an application to request deletion of packages."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ask to ignore battery optimisations"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Allows an app to ask for permission to ignore battery optimisations for that app."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"query all packages"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Allows an app to see all installed packages."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Go"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 2d92123..5a2d3f3 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Allows an application to request deletion of packages."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ask to ignore battery optimizations"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Allows an app to ask for permission to ignore battery optimizations for that app."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"query all packages"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Allows an app to see all installed packages."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Go"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 9102b89..d3614f1 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -407,7 +407,7 @@
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"Permite que la aplicación se inicie en cuanto el sistema haya finalizado la inicialización. Esto puede ocasionar que la tablet tarde más en inicializarse y que la aplicación ralentice el funcionamiento general de la tablet al estar en ejecución constante."</string>
<string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"Permite que se active la app en cuanto el sistema haya terminado de iniciarse. Esto puede ocasionar que el dispositivo Android TV tarde más en arrancar y que la app, al estar en ejecución constante, ralentice el funcionamiento general."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"Permite que la aplicación se inicie en cuanto el sistema haya finalizado la inicialización. Esto puede ocasionar que el dispositivo tarde más en inicializarse y que la aplicación ralentice el funcionamiento general del dispositivo al estar en ejecución constante."</string>
- <string name="permlab_broadcastSticky" msgid="4552241916400572230">"enviar emisiones pegajosas"</string>
+ <string name="permlab_broadcastSticky" msgid="4552241916400572230">"enviar emisiones persistentes"</string>
<string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"Permite que la aplicación envíe transmisiones persistentes que permanecen después de que finaliza la transmisión. Un uso excesivo podría ralentizar la tablet o hacer que funcione de manera inestable al forzarla a utilizar mucha memoria."</string>
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permite que la app envíe transmisiones persistentes que permanecen después de que finaliza la emisión. Un uso excesivo podría ralentizar el dispositivo Android TV o forzarlo a utilizar demasiada memoria, lo que generaría un funcionamiento inestable."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permite que la aplicación envíe transmisiones persistentes que permanecen después de que finaliza la transmisión. Un uso excesivo podría ralentizar el dispositivo o hacer que funcione de manera inestable al forzarlo a utilizar mucha memoria."</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Permite que una aplicación solicite que se borren paquetes."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"solicitar permiso para ignorar las optimizaciones de la batería"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Permite que una app solicite permiso para ignorar las optimizaciones de la batería."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"Búsqueda de todos los paquetes"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Permite que una app vea todos los paquetes que se instalaron."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Presiona dos veces para obtener el control del zoom"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"No se pudo agregar el widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Ir"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 07f805b..7257159 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Texto copiado al portapapeles."</string>
<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="7355790625710831847">"Se ha pegado <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> desde el portapapeles"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha pegado contenido desde el portapapeles"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha pegado texto que has copiado"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha pegado una imagen que has copiado"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha pegado contenido que has copiado"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Permite a una aplicación solicitar la eliminación de paquetes."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"solicitar permiso para ignorar las optimizaciones de la batería"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Permite que una aplicación solicite permiso para ignorar las optimizaciones de la batería."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"consultar todos los paquetes"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Permite que una aplicación vea todos los paquetes instalados."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Da dos toques para acceder al control de zoom."</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"No se ha podido añadir el widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Ir"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 937161b..1ae8730 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Võimaldab rakendusel taotleda pakettide kustutamist."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"küsida luba aku optimeerimise eiramiseks"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Lubab rakendusel küsida luba rakenduse aku optimeerimise eiramiseks."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"päringute esitamine kõikide pakettide kohta"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Võimaldab rakendusel näha kõiki installitud pakette."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Suumi kasutamiseks koputage kaks korda"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Vidinat ei saanud lisada."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Mine"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 3160134..de6e5e7 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -866,11 +866,11 @@
<string name="keyguard_password_enter_pin_code" msgid="6401406801060956153">"Idatzi PIN kodea"</string>
<string name="keyguard_password_enter_puk_code" msgid="3112256684547584093">"Idatzi PUKa eta PIN berria"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="2825313071899938305">"PUK kodea"</string>
- <string name="keyguard_password_enter_pin_prompt" msgid="5505434724229581207">"PIN berria"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="5505434724229581207">"PIN kode berria"</string>
<string name="keyguard_password_entry_touch_hint" msgid="4032288032993261520"><font size="17">"Sakatu pasahitza idazteko"</font></string>
<string name="keyguard_password_enter_password_code" msgid="2751130557661643482">"Idatzi desblokeatzeko pasahitza"</string>
- <string name="keyguard_password_enter_pin_password_code" msgid="7792964196473964340">"Idatzi desblokeatzeko PIN kodea"</string>
- <string name="keyguard_password_wrong_pin_code" msgid="8583732939138432793">"PIN kode okerra."</string>
+ <string name="keyguard_password_enter_pin_password_code" msgid="7792964196473964340">"Idatzi desblokeatzeko PINa"</string>
+ <string name="keyguard_password_wrong_pin_code" msgid="8583732939138432793">"PIN kodea okerra da."</string>
<string name="keyguard_label_text" msgid="3841953694564168384">"Desblokeatzeko, sakatu Menua eta, ondoren, 0."</string>
<string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"Larrialdietarako zenbakia"</string>
<string name="lockscreen_carrier_default" msgid="6192313772955399160">"Ez dago zerbitzurik"</string>
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Testua arbelean kopiatu da."</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> aplikazioak arbeletik itsatsi du"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> aplikazioak arbeleko edukia itsatsi du"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> aplikazioak kopiatu duzun testua itsatsi du"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> aplikazioak kopiatu duzun irudia itsatsi du"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> aplikazioak kopiatu duzun edukia itsatsi du"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Paketeak ezabatzeko eskatzea baimentzen die aplikazioei."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"eskatu bateria-optimizazioei ez ikusi egitea"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Bateriaren optimizazioei ez ikusi egiteko baimena eskatzea baimentzen die aplikazioei."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"Kontsultatu pakete guztiak"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Instalatutako pakete guztiak ikusteko baimena ematen dio aplikazioari."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Sakatu birritan zooma kontrolatzeko"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Ezin izan da widgeta gehitu."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Joan"</string>
@@ -1649,14 +1647,14 @@
<item quantity="one">Saiatu berriro segundo bat igarotakoan.</item>
</plurals>
<string name="kg_pattern_instructions" msgid="8366024510502517748">"Marraztu eredua"</string>
- <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Idatzi SIMaren PIN kodea"</string>
+ <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Idatzi SIMaren PINa"</string>
<string name="kg_pin_instructions" msgid="7355933174673539021">"Idatzi PINa"</string>
<string name="kg_password_instructions" msgid="7179782578809398050">"Idatzi pasahitza"</string>
<string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIMa desgaitu egin da. Jarraitzeko, idatzi PUK kodea. Xehetasunak lortzeko, jarri operadorearekin harremanetan."</string>
<string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Idatzi erabili nahi duzun PIN kodea"</string>
<string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Berretsi erabili nahi duzun PIN kodea"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"SIM txartela desblokeatzen…"</string>
- <string name="kg_password_wrong_pin_code" msgid="9013856346870572451">"PIN okerra."</string>
+ <string name="kg_password_wrong_pin_code" msgid="9013856346870572451">"PIN kodea okerra da."</string>
<string name="kg_invalid_sim_pin_hint" msgid="4821601451222564077">"Idatzi 4 eta 8 zenbaki arteko PINa."</string>
<string name="kg_invalid_sim_puk_hint" msgid="2539364558870734339">"PUK kodeak 8 zenbaki izan behar ditu."</string>
<string name="kg_invalid_puk" msgid="4809502818518963344">"Idatzi berriro PUK kode zuzena. Hainbat saiakera oker eginez gero, betiko desgaituko da SIMa."</string>
@@ -1729,7 +1727,7 @@
<string name="user_switched" msgid="7249833311585228097">"Erabiltzailea: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"\"<xliff:g id="NAME">%1$s</xliff:g>\" erabiltzailera aldatzen…"</string>
<string name="user_logging_out_message" msgid="7216437629179710359">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzailearen saioa amaitzen…"</string>
- <string name="owner_name" msgid="8713560351570795743">"\"Jabea\""</string>
+ <string name="owner_name" msgid="8713560351570795743">"Jabea"</string>
<string name="error_message_title" msgid="4082495589294631966">"Errorea"</string>
<string name="error_message_change_not_allowed" msgid="843159705042381454">"Administratzaileak ez du eman aldaketa egiteko baimena"</string>
<string name="app_not_found" msgid="3429506115332341800">"Ez da ekintza gauza dezakeen aplikaziorik aurkitu"</string>
@@ -1835,13 +1833,13 @@
<string name="reason_service_unavailable" msgid="5288405248063804713">"Inprimatze-zerbitzua ez dago gaituta"</string>
<string name="print_service_installed_title" msgid="6134880817336942482">"<xliff:g id="NAME">%s</xliff:g> zerbitzua instalatu da"</string>
<string name="print_service_installed_message" msgid="7005672469916968131">"Sakatu gaitzeko"</string>
- <string name="restr_pin_enter_admin_pin" msgid="1199419462726962697">"Idatzi administratzailearen PIN kodea"</string>
+ <string name="restr_pin_enter_admin_pin" msgid="1199419462726962697">"Idatzi administratzailearen PINa"</string>
<string name="restr_pin_enter_pin" msgid="373139384161304555">"Idatzi PINa"</string>
<string name="restr_pin_incorrect" msgid="3861383632940852496">"Okerra"</string>
<string name="restr_pin_enter_old_pin" msgid="7537079094090650967">"Oraingo PINa"</string>
<string name="restr_pin_enter_new_pin" msgid="3267614461844565431">"PIN berria"</string>
<string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Berretsi PIN berria"</string>
- <string name="restr_pin_create_pin" msgid="917067613896366033">"Konfiguratu debekuak aldatu ahal izateko idatzi beharko den PIN kodea"</string>
+ <string name="restr_pin_create_pin" msgid="917067613896366033">"Konfiguratu debekuak aldatu ahal izateko idatzi beharko den PINa"</string>
<string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"PINak ez datoz bat. Saiatu berriro."</string>
<string name="restr_pin_error_too_short" msgid="1547007808237941065">"PINa laburregia da. Lau digitu izan behar ditu gutxienez."</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
@@ -2168,11 +2166,11 @@
<string name="miniresolver_open_in_work" msgid="152208044699347924">"Laneko profileko <xliff:g id="APP">%s</xliff:g> aplikazioan ireki nahi duzu?"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Erabili arakatzaile pertsonala"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Erabili laneko arakatzailea"</string>
- <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIMaren sarearen bidez desblokeatzeko PIN kodea"</string>
+ <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIMaren sarearen bidez desblokeatzeko PINa"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIMaren sareko azpimultzoaren bidez desblokeatzeko PINa"</string>
- <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Enpresaren SIMaren bidez desblokeatzeko PIN kodea"</string>
- <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"SIMaren zerbitzu-hornitzailearen bidez desblokeatzeko PIN kodea"</string>
- <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"SIMaren bidez desblokeatzeko PIN kodea"</string>
+ <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Enpresaren SIMaren bidez desblokeatzeko PINa"</string>
+ <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"SIMaren zerbitzu-hornitzailearen bidez desblokeatzeko PINa"</string>
+ <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"SIMaren bidez desblokeatzeko PINa"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"Idatzi PUK kodea"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"Idatzi PUK kodea"</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"Idatzi PUK kodea"</string>
@@ -2181,9 +2179,9 @@
<string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIMaren 1 motako sarearen bidez desblokeatzeko PINa"</string>
<string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIMaren 2 motako sarearen bidez desblokeatzeko PINa"</string>
<string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"HRPD sarearen bidez desblokeatzeko PINa"</string>
- <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"Enpresaren RUIMaren bidez desblokeatzeko PIN kodea"</string>
- <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIMaren zerbitzu-hornitzailearen bidez desblokeatzeko PIN kodea"</string>
- <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"RUIMaren bidez desblokeatzeko PIN kodea"</string>
+ <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"Enpresaren RUIMaren bidez desblokeatzeko PINa"</string>
+ <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIMaren zerbitzu-hornitzailearen bidez desblokeatzeko PINa"</string>
+ <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"RUIMaren bidez desblokeatzeko PINa"</string>
<string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"Idatzi PUK kodea"</string>
<string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"Idatzi PUK kodea"</string>
<string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY" msgid="1730510161529488920">"Idatzi PUK kodea"</string>
@@ -2191,8 +2189,8 @@
<string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"Idatzi PUK kodea"</string>
<string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"Idatzi PUK kodea"</string>
<string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPNaren bidez desblokeatzeko PINa"</string>
- <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"Zerbitzu-hornitzailearen PLMN sare nagusi baliokidearen bidez desblokeatzeko PIN kodea"</string>
- <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCIDaren bidez desblokeatzeko PIN kodea"</string>
+ <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"Zerbitzu-hornitzailearen PLMN sare nagusi baliokidearen bidez desblokeatzeko PINa"</string>
+ <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCIDaren bidez desblokeatzeko PINa"</string>
<string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPIaren bidez desblokeatzeko PINa"</string>
<string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"Sareko azpimultzoaren zerbitzu-hornitzailearen bidez desblokeatzeko PINa"</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"SIMaren sarearen bidez desblokeatzeko eskatzen…"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3787d4c..cc2223c 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"به برنامه اجازه میدهد حذف بستهها را درخواست کند."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"درخواست نادیدهگرفتن بهینهسازی باتری"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"به یک برنامه اجازه میدهد جهت نادیده گرفتن بهینهسازی باتری برای خود مجوز درخواست کند."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"پُرسمان همه بستهها"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"به برنامه اجازه میدهد همه بستههای نصبشده را ببیند."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"برای کنترل بزرگنمایی، دو بار ضربه بزنید"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"افزودن ابزارک انجام نشد."</string>
<string name="ime_action_go" msgid="5536744546326495436">"برو"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 965970c..1b28ca1 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Antaa sovelluksen pyytää pakettien poistamista."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"Lupa ohittaa akun optimoinnit"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Sallii sovelluksen pyytää lupaa ohittaa tietyn sovelluksen akun optimoinnit."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"kaikkien pakettien näkeminen"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Antaa sovelluksen nähdä kaikki asennetut paketit."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Hallitse zoomausta napauttamalla kahdesti"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Widgetin lisääminen epäonnistui."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Siirry"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 44754d7..fa373784 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Permet à une application de demander la suppression de paquets."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"demander d\'ignorer les optimisations de la pile"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Permet à une application de demander la permission d\'ignorer les optimisations de la pile."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"envoyer une requête à propos de tous les paquets"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Permet à une application de voir tous les paquets installés."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Appuyer deux fois pour régler le zoom"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Impossible d\'ajouter le widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Aller"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index cc22d83..0ee3c88 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Le texte a été copié dans le presse-papier."</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a copié des données depuis le presse-papiers"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a collé des données depuis le presse-papiers"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a collé du texte que vous avez copié"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a collé une image que vous avez copiée"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a collé le contenu que vous avez copié"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Permet à une application de demander la suppression de packages."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"demander à ignorer les optimisations de batterie"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Autorise une application à demander l\'autorisation d\'ignorer les optimisations de batterie pour cette application."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"interroger tous les packages"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Autorise une appli à voir tous les packages installés."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Appuyer deux fois pour régler le zoom"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Impossible d\'ajouter le widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"OK"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index ba41c75..5e10fdb 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Permite a unha aplicación solicitar a eliminación dos paquetes."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"pedir que se ignore a optimización da batería"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Fai que unha aplicación poida solicitar permiso para ignorar as optimizacións da batería."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"consultar todos os paquetes"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Permite que unha aplicación consulte todos os paquetes instalados."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Toca dúas veces para controlar o zoom"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Non se puido engadir o widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Ir"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 6e8bd94..8fe4ebf 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"किसी ऐप्लिकेशन को पैकेज हटाने का अनुरोध करने देती है."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"बैटरी ऑप्टिमाइज़ेशन पर ध्यान ना देने के लिए पूछें"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"किसी ऐप्लिकेशन को उस ऐप्लिकेशन के लिए बैटरी ऑप्टिमाइज़ेशन पर ध्यान ना देने की अनुमति के लिए पूछने देता है."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"डिवाइस पर इंस्टॉल किए गए सभी पैकेज देखें"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"यह किसी ऐप्लिकेशन को, डिवाइस पर इंस्टॉल किए गए सभी पैकेज देखने की अनुमति देता है."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ज़ूम नियंत्रण के लिए दो बार टैप करें"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"विजेट नहीं जोड़ा जा सका."</string>
<string name="ime_action_go" msgid="5536744546326495436">"जाएं"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 98acb89..630ba2b 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1022,7 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Tekst kopiran u međuspremnik."</string>
<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="7355790625710831847">"Zalijepljen je sadržaj aplikacije <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Apl. <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> zalijepila je ovaj sadržaj iz međuspremnika"</string>
<string name="pasted_text" msgid="4298871641549173733">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> zalijepila je tekst koji ste kopirali"</string>
<string name="pasted_image" msgid="4729097394781491022">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> zalijepila je sliku koju ste kopirali"</string>
<string name="pasted_content" msgid="646276353060777131">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> zalijepila je ono što ste kopirali"</string>
@@ -1212,7 +1212,7 @@
<string name="whichEditApplication" msgid="6191568491456092812">"Uređivanje pomoću aplikacije"</string>
<string name="whichEditApplicationNamed" msgid="8096494987978521514">"Uređivanje pomoću aplikacije %1$s"</string>
<string name="whichEditApplicationLabel" msgid="1463288652070140285">"Uredi"</string>
- <string name="whichSendApplication" msgid="4143847974460792029">"Dijeli"</string>
+ <string name="whichSendApplication" msgid="4143847974460792029">"Dijeljenje"</string>
<string name="whichSendApplicationNamed" msgid="4470386782693183461">"Dijeljenje pomoću aplikacije %1$s"</string>
<string name="whichSendApplicationLabel" msgid="7467813004769188515">"Dijeli"</string>
<string name="whichSendToApplication" msgid="77101541959464018">"Pošalji aplikacijom"</string>
@@ -1478,10 +1478,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Aplikaciji omogućuje zahtijevanje brisanja paketa."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"tražiti zanemarivanje optimizacija baterije"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Aplikaciji omogućuje da traži dopuštenje za zanemarivanje optimizacija baterije za tu aplikaciju."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"slanje upita za sve pakete"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Aplikaciji omogućuje pregled instaliranih paketa."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Dvaput dotaknite za upravljanje zumiranjem"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Widget nije moguće dodati."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Idi"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 58c3875..f945d39 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Lehetővé teszi az alkalmazás számára, hogy csomagok törlését kérje."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"Akkumulátoroptimalizálási beállítások mellőzésének kérése"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Az alkalmazás engedélyt kérhet az akkumulátoroptimalizálási beállítások mellőzésére."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"az összes csomag lekérdezése"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Engedélyezi az adott alkalmazás számára, hogy lássa az összes telepített csomagot."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Érintse meg kétszer a nagyítás beállításához"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Nem sikerült hozzáadni a modult."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Ugrás"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 860dcf9..d3057ca 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Թույլ է տալիս հավելվածին պահանջել փաթեթների ջնջում:"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"հայցել մարտկոցի օպտիմալացումն անտեսելու թույլտվություն"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Հավելվածին հնարավորություն է տալիս հայցելու թույլտվություն՝ տվյալ հավելվածի համար մարտկոցի օպտիմալացումն անտեսելու համար:"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"հարցում բոլոր փաթեթների համար"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Թույլ է տալիս հավելվածին տեսնել բոլոր տեղադրված փաթեթները։"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Հպեք երկու անգամ` խոշորացման վերահսկման համար"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Չհաջողվեց վիջեթ ավելացնել:"</string>
<string name="ime_action_go" msgid="5536744546326495436">"Առաջ"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index b8649c1..abe3608 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -399,7 +399,7 @@
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"Memungkinkan aplikasi membuat bagian dari dirinya sendiri terus-menerus berada dalam memori. Izin ini dapat membatasi memori yang tersedia untuk aplikasi lain sehingga menjadikan ponsel lambat."</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"jalankan layanan di latar depan"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"Mengizinkan aplikasi menggunakan layanan di latar depan."</string>
- <string name="permlab_getPackageSize" msgid="375391550792886641">"mengukur ruang penyimpanan apl"</string>
+ <string name="permlab_getPackageSize" msgid="375391550792886641">"mengukur ruang penyimpanan aplikasi"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"Mengizinkan apl mengambil kode, data, dan ukuran temboloknya"</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"ubah setelan sistem"</string>
<string name="permdesc_writeSettings" msgid="8293047411196067188">"Mengizinkan apl memodifikasi data setelan sistem. Apl berbahaya dapat merusak konfigurasi sistem anda."</string>
@@ -437,7 +437,7 @@
<string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"Aplikasi ini dapat menambahkan, menghapus, atau mengubah acara kalender di ponsel. Aplikasi ini dapat mengirim pesan yang kelihatannya berasal dari pemilik kalender, atau mengubah acara tanpa memberi tahu pemilik."</string>
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"akses perintah penyedia lokasi ekstra"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Memungkinkan aplikasi mengakses perintah penyedia lokasi ekstra. Tindakan ini memungkinkan aplikasi mengganggu pengoperasian GPS atau sumber lokasi lain."</string>
- <string name="permlab_accessFineLocation" msgid="6426318438195622966">"akses lokasi pasti hanya saat di latar depan"</string>
+ <string name="permlab_accessFineLocation" msgid="6426318438195622966">"akses lokasi akurat hanya saat di latar depan"</string>
<string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Aplikasi ini bisa mendapatkan lokasi pasti Anda dari layanan lokasi saat aplikasi sedang digunakan. Layanan lokasi untuk perangkat harus diaktifkan agar aplikasi bisa mendapatkan lokasi. Ini dapat meningkatkan penggunaan baterai."</string>
<string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"akses perkiraan lokasi hanya saat berada di latar depan"</string>
<string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Aplikasi ini bisa mendapatkan perkiraan lokasi Anda dari layanan lokasi saat aplikasi sedang digunakan. Layanan lokasi untuk perangkat harus diaktifkan agar aplikasi bisa mendapatkan lokasi."</string>
@@ -658,7 +658,7 @@
<string-array name="face_error_vendor">
</string-array>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikon wajah"</string>
- <string name="permlab_readSyncSettings" msgid="6250532864893156277">"baca setelan sinkron"</string>
+ <string name="permlab_readSyncSettings" msgid="6250532864893156277">"baca setelan sinkronisasi"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Memungkinkan aplikasi membaca setelan sinkronisasi untuk sebuah akun. Misalnya, izin ini dapat menentukan apakah aplikasi Orang disinkronkan dengan sebuah akun."</string>
<string name="permlab_writeSyncSettings" msgid="6583154300780427399">"nyalakan dan matikan sinkronisasi"</string>
<string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"Memungkinkan aplikasi mengubah setelan sinkronisasi untuk sebuah akun. Misalnya, izin ini dapat digunakan untuk mengaktifkan sinkronisasi dari aplikasi Orang dengan sebuah akun."</string>
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Teks disalin ke papan klip."</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> menempel dari papan klip"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> menempelkan konten dari papan klip Anda"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> menempelkan teks yang Anda salin"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> menempelkan gambar yang Anda salin"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> menempelkan konten yang Anda salin"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Mengizinkan aplikasi meminta penghapusan paket."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"meminta mengabaikan pengoptimalan baterai"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Mengizinkan aplikasi meminta izin untuk mengabaikan pengoptimalan baterai bagi aplikasi tersebut."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"mengkueri semua paket"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Mengizinkan aplikasi melihat semua paket yang diinstal."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Ketuk dua kali untuk kontrol perbesar/perkecil"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Tidak dapat menambahkan widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Buka"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 0cf1eff..6be07b0 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Leyfir forriti að biðja um eyðingu pakka."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"biðja um að hunsa rafhlöðusparnað"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Gerir forriti kleift að biðja um heimild til að hunsa rafhlöðusparnað fyrir forritið."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"spyrja fyrir alla pakka"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Leyfir forriti að sjá alla uppsetta pakka."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Ýttu tvisvar til að opna aðdráttarstýringar"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Ekki tókst að bæta græju við."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Áfram"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 29dbd76..d4f2fdb 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Testo copiato negli appunti."</string>
<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="7355790625710831847">"L\'app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha incollato dati dagli appunti"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha incollato dati dagli appunti"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha incollato il testo che hai copiato"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha incollato un\'immagine che hai copiato"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ha incollato i contenuti che hai copiato"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Consente a un\'applicazione di richiedere l\'eliminazione di pacchetti."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"richiesta di ignorare le ottimizzazioni della batteria"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Consente a un\'app di chiedere l\'autorizzazione a ignorare le ottimizzazioni della batteria per quell\'app."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"Invio di query per tutti i pacchetti"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Consente a un\'app di visualizzare tutti i pacchetti installati."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tocca due volte per il comando dello zoom"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Aggiunta del widget non riuscita."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Vai"</string>
@@ -1870,8 +1868,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Aggiornato dall\'amministratore"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminato dall\'amministratore"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"L\'opzione Risparmio energetico attiva il tema scuro e limita o disattiva l\'attività in background, nonché alcuni effetti visivi, funzionalità e connessioni di rete."</string>
- <string name="battery_saver_description" msgid="8518809702138617167">"L\'opzione Risparmio energetico attiva il tema scuro e limita o disattiva l\'attività in background, nonché alcuni effetti visivi, funzionalità e connessioni di rete."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Il risparmio energetico attiva il tema scuro e limita o disattiva l\'attività in background, nonché alcuni effetti visivi, funzionalità e connessioni di rete."</string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Il risparmio energetico attiva il tema scuro e limita o disattiva l\'attività in background, nonché alcuni effetti visivi, funzionalità e connessioni di rete."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Per contribuire a ridurre l\'utilizzo dei dati, la funzione Risparmio dati impedisce ad alcune app di inviare o ricevere dati in background. Un\'app in uso può accedere ai dati, ma potrebbe farlo con meno frequenza. Esempio: le immagini non vengono visualizzate finché non le tocchi."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Attivare Risparmio dati?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Attiva"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index dc43bde..7c9d97e 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1025,7 +1025,7 @@
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> הודבקה מהלוח שלך"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"אפליקציית <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ביצעה הדבקה מהלוח"</string>
<string name="pasted_text" msgid="4298871641549173733">"טקסט שהעתקת הודבק על ידי <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_image" msgid="4729097394781491022">"תמונה שהעתקת הודבקה על ידי <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_content" msgid="646276353060777131">"התוכן שהעתקת הודבק על ידי <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
@@ -1498,10 +1498,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"מאפשרת לאפליקציה לבקש מחיקה של חבילות."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"בקשה להתעלם מאופטימיזציות של הסוללה"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"מאפשרת לאפליקציה לבקש רשות להתעלם מאופטימיזציות של הסוללה לאפליקציה הזו."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"שליחת שאילתות לכל החבילות"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"מאפשרת לאפליקציה לראות את כל החבילות המותקנות."</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>
@@ -2123,7 +2121,7 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="227760698553988751">"ניהול התצורה של כרטיס ה-SIM לא מתאים לזיהוי קולי"</string>
<string name="mmcc_illegal_ms" msgid="7509650265233909445">"כרטיס ה-SIM לא מורשה לזיהוי קולי"</string>
<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_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_me_msim_template" msgid="4802735138861422802">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> אינו מאושר לשימוש ברשת"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index b282b44..3968187 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"パッケージの削除をリクエストすることをアプリに許可します。"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"電池の最適化を無視するかどうかの確認"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"電池の最適化の無視についてアプリが確認することを許可します。"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"すべてのパッケージを照会する"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"すべてのインストール済みパッケージを参照することをアプリに許可します。"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ダブルタップでズームします"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ウィジェットを追加できませんでした。"</string>
<string name="ime_action_go" msgid="5536744546326495436">"移動"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index dbc92da..e941b5e 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1019,7 +1019,7 @@
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ჩასმულია თქვენი გაცვლის ბუფერიდან"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-მა ჩასვა ტექსტი თქვენი გაცვლის ბუფერიდან"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-მ(ა) ჩასვა თქვენ მიერ დაკოპირებული ტექსტი"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-მ(ა) ჩასვა თქვენ მიერ დაკოპირებული სურათი"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-მ(ა) ჩასვა თქვენ მიერ დაკოპირებული კონტენტი"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"აპლიკაციას შეეძლება პაკეტების წაშლის მოთხოვნა."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ბატარეის ოპტიმიზაციის იგნორირების მოთხოვნა"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"საშუალებას მისცემს აპს, მოითხოვოს მასთან დაკავშირებული ბატარეის ოპტიმიზაციის იგნორირების ნებართვა."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"ყველა პაკეტის მოთხოვნა"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"საშუალებას აძლევს აპს, ნახოს ყველა ინსტალირებული პაკეტი."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"მასშტაბის ცვლილებისთვის შეეხეთ ორჯერ"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ვერ დაემატა ვიჯეტი."</string>
<string name="ime_action_go" msgid="5536744546326495436">"გადასვლა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 6d3429e..1324d2d 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Қолданбаның пакеттерді жоюға рұқсат сұрауына мүмкіндік береді."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"батареяны оңтайландыру әрекетін елемеуді сұрау"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Қолданба батареяны оңтайландыру әрекетін елемеуді сұрай алады."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"барлық бумаға сұрау жасау"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Қолданба барлық орнатылған буманы көре алады."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Масштабтау параметрін басқару үшін екі рет түртіңіз"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Виджетті қосу."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Өту"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 19aa889..df0b082 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1019,7 +1019,7 @@
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> បានដាក់ចូលពីឃ្លីបបតរបស់អ្នក"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"បានដាក់ចូល <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ពីឃ្លីបបតរបស់អ្នក"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> បានដាក់ចូលអត្ថបទដែលអ្នកបានចម្លង"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> បានដាក់ចូលរូបភាពដែលអ្នកបានចម្លង"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> បានដាក់ចូលខ្លឹមសារដែលអ្នកបានចម្លង"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"អនុញ្ញាតឲ្យកម្មវិធីស្នើសុំលុបកញ្ចប់។"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ស្នើឲ្យមិនអើពើចំពោះការបង្កើនប្រសិទ្ធភាពថ្ម"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"អនុញ្ញាតឲ្យកម្មវិធីស្នើសុំការអនុញ្ញាត ដើម្បីមិនអើពើចំពោះការបង្កើនប្រសិទ្ធភាពថ្ម។"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"សួរសំណួរអំពីកញ្ចប់ទាំងអស់"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"អនុញ្ញាតឱ្យកម្មវិធីមើលកញ្ចប់ដែលបានដំឡើងទាំងអស់។"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ប៉ះ ពីរដងដើម្បីពិនិត្យការពង្រីក"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"មិនអាចបន្ថែមធាតុក្រាហ្វិក។"</string>
<string name="ime_action_go" msgid="5536744546326495436">"ទៅ"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index a3e0ca5..a8e5b640 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1019,7 +1019,7 @@
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ಅನ್ನು ನಿಮ್ಮ ಕ್ಲಿಪ್ಬೋರ್ಡ್ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>, ನಿಮ್ಮ ಕ್ಲಿಪ್ಬೋರ್ಡ್ನಲ್ಲಿನ ಡೇಟಾವನ್ನು ಅಂಟಿಸಿದೆ"</string>
<string name="pasted_text" msgid="4298871641549173733">"ನೀವು ನಕಲಿಸಿರುವ ಪಠ್ಯವನ್ನು <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
<string name="pasted_image" msgid="4729097394781491022">"ನೀವು ನಕಲಿಸಿರುವ ಚಿತ್ರವನ್ನು <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
<string name="pasted_content" msgid="646276353060777131">"ನೀವು ನಕಲಿಸಿರುವ ವಿಷಯವನ್ನು <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"ಪ್ಯಾಕೇಜ್ಗಳನ್ನು ಅಳಿಸುವುದಕ್ಕಾಗಿ ವಿನಂತಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ಬ್ಯಾಟರಿ ಆಪ್ಟಿಮೈಸೇಶನ್ಗಳನ್ನು ಕಡೆಗಣಿಸಲು ಕೇಳಿ"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"ಈ ಅಪ್ಲಿಕೇಶನ್ಗೆ ಬ್ಯಾಟರಿ ಆಪ್ಟಿಮೈಸೇಶನ್ಗಳನ್ನು ಕಡೆಗಣಿಸುವುದಕ್ಕೆ ಅನುಮತಿಯನ್ನು ಕೇಳಲು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"ಎಲ್ಲಾ ಪ್ಯಾಕೇಜ್ಗಳ ಕುರಿತಾದ ಮಾಹಿತಿಯನ್ನು ಕೇಳಿ"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿದ ಎಲ್ಲಾ ಪ್ಯಾಕೇಜ್ಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ಝೂಮ್ ನಿಯಂತ್ರಿಸಲು ಎರಡು ಬಾರಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ವಿಜೆಟ್ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string>
<string name="ime_action_go" msgid="5536744546326495436">"ಹೋಗು"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 4c1691b..cf9ade7 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"애플리케이션이 패키지 삭제를 요청하도록 허용합니다."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"배터리 최적화를 무시하도록 요청"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"앱에서 배터리 최적화를 무시할 수 있는 권한을 요청할 수 있도록 허용합니다."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"모든 패키지 쿼리"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"앱이 설치된 패키지를 모두 볼 수 있도록 허용합니다."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"확대/축소하려면 두 번 탭하세요."</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"위젯을 추가할 수 없습니다."</string>
<string name="ime_action_go" msgid="5536744546326495436">"이동"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 66ec9aa..5479f11 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1019,7 +1019,7 @@
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> алмашуу буферинен чапталды"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Алмашуу буфериндеги нерселер <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> колдонмосуна жайгаштырылды"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>: көчүрүлгөн текст чапталды"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>: көчүрүлгөн сүрөт чапталды"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>: көчүрүлгөн мазмун чапталды"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Колдонмо топтомдорду жок кылууга уруксат сурай алат."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"батареянын кубатын көп керектей берсин"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Колдонмо батареянын кубатын керектегенден мурун уруксат суралсын."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"бардык топтомдор боюнча сурам жөнөтүү"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Колдонмо бардык орнотулган топтомдорду көрөт."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Масштабдын параметрлерин өзгөртүү үчүн бул жерди эки жолу басыңыз."</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Виджетти кошуу мүмкүн болбоду."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Өтүү"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index fd83eda..ee2f058 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນຮ້ອງຂໍການລຶບແພັກເກດ."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ຖາມເພື່ອໃຫ້ເພີກເສີຍການປັບແຕ່ງແບັດເຕີຣີ"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"ອະນຸຍາດໃຫ້ແອັບຖາມສິດອະນຸຍາດເພື່ອເພີກເສີຍຕໍ່ການປັບແຕ່ງແບັດເຕີຣີສຳລັບແອັບນັ້ນ."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"ຊອກຫາແພັກເກດທັງໝົດ"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"ອະນຸຍາດໃຫ້ແອັບເບິ່ງເຫັນແພັກເກດທີ່ຕິດຕັ້ງແລ້ວທັງໝົດໄດ້."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ແຕະສອງເທື່ອເພື່ອຄວບຄຸມການຊູມ"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ບໍ່ສາມາດເພີ່ມວິດເຈັດໄດ້."</string>
<string name="ime_action_go" msgid="5536744546326495436">"ໄປ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index ca43ce7..8ebb09e 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1498,10 +1498,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Programai leidžiama pateikti užklausą dėl paketų ištrynimo."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"prašyti nepaisyti akumuliatoriaus optimizavimo nustatymų"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Programai leidžiama prašyti leidimo nepaisyti tai programai skirto akumuliatoriaus optimizavimo nustatymų."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"Teikti visų paketų užklausą"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Programai leidžiama peržiūrėti visus įdiegtus paketus."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Bakstelėkite du kartus, kad valdytumėte mastelio keitimą"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Nepavyko pridėti."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Pradėti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 47094a4..9b86c4d 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1478,10 +1478,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Atļauj lietojumprogrammai pieprasīt pakotņu dzēšanu."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"Lūgt akumulatora optimizācijas ignorēšanu"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Ļauj lietotnei lūgt atļauju ignorēt akumulatora optimizāciju šai lietotnei."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"pieprasīt atļauju skatīt visas pakotnes"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Ļauj lietotnei skatīt visas instalētās pakotnes."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Pieskarieties divreiz, lai kontrolētu tālummaiņu."</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Nevarēja pievienot logrīku."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Doties uz"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 5a9486e..d0e11f1 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Дозволува апликацијата да бара бришење на пакетите."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"прашај дали да се игнорираат оптимизациите на батеријата"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Овозможува апликацијата да побара дозвола за игнорирање на оптимизациите на батеријата за таа апликација."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"пребарување на сите пакети"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Дозволува апликацијата да ги гледа сите инсталирани пакети."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Допрете двапати за контрола на зумот"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Не може да се додаде виџет."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Оди"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 9ca392a..22fac7e 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"പാക്കേജുകളെ ഇല്ലാതാക്കാനുള്ള അഭ്യർത്ഥന നടത്താൻ ആപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ബാറ്ററി ഒപ്റ്റിമൈസേഷനുകൾ അവഗണിക്കാൻ ആവശ്യപ്പെടുക"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"ആപ്പിന് വേണ്ടിയുള്ള ബാറ്ററി ഒപ്റ്റിമൈസേഷനുകളെ അവഗണിക്കാനുള്ള അനുമതി ചോദിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"എല്ലാ പാക്കേജുകളും നോക്കുക"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"ഇൻസ്റ്റാൾ ചെയ്ത എല്ലാ പാക്കേജുകളും കാണാൻ ഒരു ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"സൂം നിയന്ത്രണം ലഭിക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"വിജറ്റ് ചേർക്കാനായില്ല."</string>
<string name="ime_action_go" msgid="5536744546326495436">"പോവുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 4c01871d..1060f64 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Апп-д багц устгах хүсэлт тавихыг зөвшөөрнө."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"батерейны оновчлол алгасахыг асуух"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Тухайн аппaaс батерейны оновчлол алгасах зөвшөөрөл асуухыг зөвшөөрдөг."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"бүх багцыг лавлах"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Аппап бүх суулгасан багцыг харахыг зөвшөөрнө."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Өсгөх контрол дээр хоёр удаа товшино уу"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Виджет нэмж чадсангүй."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Очих"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 1dfa5de..bf5f8e7 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"अनुप्रयोगास पॅकेज हटवण्यासाठी विनंती करण्याची अनुमती देते."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"बॅटरी ऑप्टिमायझेशन दुर्लक्षित करण्यास सांगा"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"त्या ॲपसाठी बॅटरी ऑप्टिमायझेशन दुर्लक्षित करण्यासाठी ॲपला परवानगी मागण्याची अनुमती देते."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"सर्व पॅकेजविषयी क्वेरी करा"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"ॲपला इंस्टॉल केलेले सर्व पॅकेज पाहण्याची अनुमती देते."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"झूम नियंत्रणासाठी दोनदा टॅप करा"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"विजेट जोडू शकलो नाही."</string>
<string name="ime_action_go" msgid="5536744546326495436">"जा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 2960ca2..ccc0828 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Membenarkan aplikasi meminta pemadaman pakej."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"minta kebenaran untuk mengabaikan pengoptimuman bateri"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Membenarkan apl meminta kebenaran untuk mengabaikan pengoptimuman bateri untuk apl itu."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"buat pertanyaan untuk semua pakej"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Membenarkan apl melihat semua pakej yang dipasang."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Ketik dua kali untuk mendapatkan kawalan zum"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Tidak dapat menambahkan widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Pergi"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 2c0ed7b..7797e08 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"clipboardထံ စာသားအားကူးယူမည်"</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> က ဒေတာကို သင့်ကလစ်ဘုတ်မှ ကူးထည့်ထားသည်"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> က သင့်ကလစ်ဘုတ်မှ ကူးထည့်ထားသည်"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> က သင်မိတ္တူကူးထားသော စာသားကို ထည့်လိုက်သည်"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> က သင်မိတ္တူကူးထားသော ပုံကို ထည့်လိုက်သည်"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> က သင်မိတ္တူကူးထားသော အကြောင်းအရာကို ထည့်လိုက်သည်"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"အပလီကေးရှင်းတစ်ခုအား ပက်ကေ့ဂျ်များကို ဖျက်ရန် တောင်းဆိုခွင့်ပေးပါ။"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ဘက်ထရီ ပိုမိုကောင်းမွန်အောင် ပြုလုပ်ခြင်းကို လျစ်လျူရှုရန် တောင်းဆိုပါ"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"ဘက်ထရီ ပိုမိုကောင်းမွန်အောင် ပြုလုပ်ခြင်းကို လျစ်လျူရှုရန်အတွက် ခွင့်ပြုချက်တောင်းရန် အက်ပ်ကို ခွင့်ပြုပါ။"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"ပက်ကေ့ဂျ်အားလုံးကို မေးမြန်းခြင်း"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"ထည့်သွင်းထားသော ပက်ကေ့ဂျ်အားလုံး ကြည့်ရန် အက်ပ်ကို ခွင့်ပြုပါ။"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ဇူးမ်အသုံးပြုရန် နှစ်ချက်တို့ပါ"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ဝဒ်ဂျက်ထည့်လို့ မရပါ"</string>
<string name="ime_action_go" msgid="5536744546326495436">"သွားပါ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 0ceebf1..395dc1d 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Lar apper be om sletting av pakker."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"be om å ignorere batterioptimaliseringer"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Gjør det mulig for apper å be om tillatelse til å ignorere batterioptimaliseringer for disse appene."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"søk i alle pakker"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Lar en app se alle installerte pakker."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Trykk to ganger for zoomkontroll"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Kunne ikke legge til modulen."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Utfør"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 8e7ca71..130adcdc 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"एपलाई प्याकेजहरू मेटाउने अनुरोध गर्न अनुमति दिन्छ।"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ब्याट्री सम्बन्धी अनुकूलनहरूलाई बेवास्ता गर्न सोध्नुहोस्"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"कुनै एपलाई त्यसका ब्याट्री सम्बन्धी अनुकूलनहरूलाई बेवास्ता गर्नाका लागि अनुमति माग्न दिन्छ।"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"सबै प्याकेजहरू खोज्नुहोस्"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"यसले यस एपलाई इन्स्टल गरिएका सबै प्याकेजहरू हेर्ने अनुमति दिन्छ।"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"जुम नियन्त्रणको लागि दुई चोटि ट्याप गर्नुहोस्"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"विजेट थप गर्न सकिँदैन।"</string>
<string name="ime_action_go" msgid="5536744546326495436">"जानुहोस्"</string>
@@ -2002,7 +2000,7 @@
<string name="app_category_game" msgid="4534216074910244790">"खेलहरू"</string>
<string name="app_category_audio" msgid="8296029904794676222">"सङ्गीत तथा अडियो"</string>
<string name="app_category_video" msgid="2590183854839565814">"चलचित्र तथा भिडियो"</string>
- <string name="app_category_image" msgid="7307840291864213007">"फोटो तथा छविहरू"</string>
+ <string name="app_category_image" msgid="7307840291864213007">"फोटो तथा फोटो"</string>
<string name="app_category_social" msgid="2278269325488344054">"सामाजिक तथा सञ्चार"</string>
<string name="app_category_news" msgid="1172762719574964544">"समाचार तथा पत्रिकाहरू"</string>
<string name="app_category_maps" msgid="6395725487922533156">"नक्सा तथा नेभिगेसन"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 9700939..9449ac1 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Hiermee kan een app verwijdering van pakketten aanvragen."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"vragen om batterijoptimalisatie te negeren"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Hiermee kan een app rechten vragen om batterijoptimalisatie voor die app te negeren."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"alle pakketten opvragen"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Hiermee kan een app alle geïnstalleerde pakketten zien."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tik twee keer voor zoomregeling"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Kan widget niet toevoegen."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Ga"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index d6b1e1e..b609827 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1239,7 +1239,7 @@
<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 OSରେ ତିଆରି ହୋଇଛି ଏବଂ ଆକସ୍ମିକ ଗତିବିଧି ଦେଖାଦେଇପାରେ। ଆପ୍ର ଏକ ଅପଡେଟ୍ ଭର୍ସନ୍ ଉପଲବ୍ଧ ରହିପାରେ।"</string>
<string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"ସର୍ବଦା ଦେଖାନ୍ତୁ"</string>
- <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"କୌଣସି ଅପଡେଟ୍ ଅଛି କି ନାହିଁ ଦେଖନ୍ତୁ"</string>
+ <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"ଅପଡେଟ୍ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="smv_application" msgid="3775183542777792638">"ଆପ୍ <xliff:g id="APPLICATION">%1$s</xliff:g> (ପ୍ରକ୍ରିୟା <xliff:g id="PROCESS">%2$s</xliff:g>) ଏହାର ସ୍ୱ-ଲାଗୁ କରାଯାଇଥିବା ଷ୍ଟ୍ରିକ୍ଟ-ମୋଡ୍ ପଲିସୀ ଉଲ୍ଲଂଘନ କରିଛି।"</string>
<string name="smv_process" msgid="1398801497130695446">"ଏହି {0/PROCESS<xliff:g id="PROCESS">%1$s</xliff:g> ନିଜ ଦ୍ୱାରା ଲାଗୁ କରାଯାଇଥିବା ଷ୍ଟ୍ରିକ୍ଟମୋଡ୍ ପଲିସୀକୁ ଉଲ୍ଲଂଘନ କରିଛି।"</string>
<string name="android_upgrading_title" product="default" msgid="7279077384220829683">"ଫୋନ୍ ଅପଡେଟ୍ ହେଉଛି…"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"ପ୍ୟାକେଜ୍ଗୁଡ଼ିକ ଡିଲିଟ୍ କରିବା ପାଇଁ ଅନୁରୋଧ କରିବାକୁ ଏକ ଆପ୍ଲିକେଶନକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ବ୍ୟାଟେରୀ ଅନୁକୂଳନ ଏଡ଼ାଇବା ପାଇଁ ପଚାରନ୍ତୁ"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"ଆପ୍ ପାଇଁ ବ୍ୟାଟେରୀ ଅନୁକୂଳନ ଏଡ଼ାଇବାର ଅନୁମତି ମାଗିବା ନିମନ୍ତେ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"ସବୁ ପ୍ୟାକେଜ୍ ବିଷୟରେ କ୍ୱେରୀ କରନ୍ତୁ"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"ଇନଷ୍ଟଲ୍ କରାଯାଇଥିବା ସମସ୍ତ ପ୍ୟାକେଜକୁ ଦେଖିବା ପାଇଁ ଏକ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ଜୁମ୍ ନିୟନ୍ତ୍ରଣ ପାଇଁ ଦୁଇଥର ଟାପ୍ କରନ୍ତୁ"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ୱିଜେଟ୍ ଯୋଡ଼ିପାରିବ ନାହିଁ।"</string>
<string name="ime_action_go" msgid="5536744546326495436">"ଯାଆନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 9a73f9b..2efcc76 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"ਕਿਸੇ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਪੈਕੇਜਾਂ ਨੂੰ ਮਿਟਾਉਣ ਦੀ ਬੇਨਤੀ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ਬੈਟਰੀ ਸੁਯੋਗਤਾਵਾਂ ਨੂੰ ਅਣਡਿੱਠ ਕਰਨ ਲਈ ਪੁੱਛੋ"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"ਕਿਸੇ ਐਪ ਨੂੰ ਉਸ ਵਾਸਤੇ ਬੈਟਰੀ ਸੁਯੋਗਤਾਵਾਂ ਨੂੰ ਅਣਡਿੱਠ ਕਰਨ ਲਈ ਇਜਾਜ਼ਤ ਵਾਸਤੇ ਪੁੱਛਣ ਲਈ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"ਸਾਰੇ ਪੈਕੇਜਾਂ ਬਾਰੇ ਪੁੱਛਗਿੱਛ"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"ਇਸ ਨਾਲ ਐਪ ਨੂੰ ਸਥਾਪਤ ਕੀਤੇ ਸਾਰੇ ਪੈਕੇਜ ਦੇਖਣ ਦੀ ਇਜਾਜ਼ਤ ਮਿਲਦੀ ਹੈ।"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ਜ਼ੂਮ ਕੰਟਰੋਲ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ਵਿਜੇਟ ਸ਼ਾਮਲ ਨਹੀਂ ਹੋ ਸਕਿਆ।"</string>
<string name="ime_action_go" msgid="5536744546326495436">"ਜਾਓ"</string>
@@ -2152,7 +2150,7 @@
<string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"ਗੁਰੱਪ ਗੱਲਬਾਤ"</string>
<string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
<string name="resolver_personal_tab" msgid="2051260504014442073">"ਨਿੱਜੀ"</string>
- <string name="resolver_work_tab" msgid="2690019516263167035">"ਕੰਮ"</string>
+ <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_cross_profile_blocked" msgid="3014597376026044840">"ਤੁਹਾਡੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 2781df7..49890fc 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1025,7 +1025,7 @@
<string name="text_copied" msgid="2531420577879738860">"Tekst został skopiowany do schowka."</string>
<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="7355790625710831847">"Aplikacja <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> skopiowała dane ze schowka"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Aplikacja <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> wkleiła dane ze schowka"</string>
<string name="pasted_text" msgid="4298871641549173733">"Aplikacja <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> wkleiła skopiowany tekst"</string>
<string name="pasted_image" msgid="4729097394781491022">"Aplikacja <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> wkleiła skopiowany obraz"</string>
<string name="pasted_content" msgid="646276353060777131">"Aplikacja <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> wkleiła skopiowane treści"</string>
@@ -1498,10 +1498,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Zezwala aplikacji na żądanie usunięcia pakietów."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"Prośba o ignorowanie optymalizacji wykorzystania baterii"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Zezwala aplikacji na proszenie o uprawnienia do ignorowania optymalizacji wykorzystania baterii w przypadku danej aplikacji."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"zapytanie o wszystkie pakiety"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Pozwala aplikacji wyświetlać wszystkie zainstalowane pakiety."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Dotknij dwukrotnie, aby sterować powiększeniem"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Nie można dodać widżetu."</string>
<string name="ime_action_go" msgid="5536744546326495436">"OK"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index a60cb23..f4c0cdb 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Permite que um app solicite a exclusão de pacotes."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"solicitar que as otimizações de bateria sejam ignoradas"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Permite que um app peça permissão para ignorar as otimizações de bateria para esse app."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"consultar todos os pacotes"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Permite que um app veja todos os pacotes instalados."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Toque duas vezes para ter controle do zoom"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Não foi possível adicionar widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Ir"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 5f10462..f1c8476 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Texto copiado para a área de transferência."</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou a partir da área de transferência"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"A app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou a partir da área de transferência"</string>
<string name="pasted_text" msgid="4298871641549173733">"A app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou o texto que copiou"</string>
<string name="pasted_image" msgid="4729097394781491022">"A app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou uma imagem que copiou"</string>
<string name="pasted_content" msgid="646276353060777131">"A app <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> colou o conteúdo que copiou"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Permite que uma app solicite a eliminação de pacotes."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"pedir para ignorar as otimizações da bateria"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Permite que uma app solicite autorização para ignorar as otimizações da bateria para a mesma."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"consultar todos os pacotes"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Permite a uma app ver todos os pacotes instalados."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tocar duas vezes para controlar o zoom"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Não foi possível adicionar widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Ir"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index a60cb23..f4c0cdb 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Permite que um app solicite a exclusão de pacotes."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"solicitar que as otimizações de bateria sejam ignoradas"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Permite que um app peça permissão para ignorar as otimizações de bateria para esse app."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"consultar todos os pacotes"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Permite que um app veja todos os pacotes instalados."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Toque duas vezes para ter controle do zoom"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Não foi possível adicionar widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Ir"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index dc351a2..c50f2e3 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1478,10 +1478,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Permite unei aplicații să solicite ștergerea pachetelor."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"să solicite ignorarea optimizărilor bateriei"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Permite unei aplicații să solicite permisiunea de a ignora optimizările bateriei pentru aplicația respectivă."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"să interogheze toate pachetele"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Permite unei aplicații să vadă toate pachetele instalate."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Apăsați de două ori pentru a controla mărirea/micșorarea"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Nu s-a putut adăuga widgetul."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Accesați"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ea9e292..dde5ebc 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -447,7 +447,7 @@
<string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Приложение сможет получать сведения о вашем точном местоположении, только когда используется. Для этого на устройстве должна быть включена геолокация. Учтите, что при этом заряд батареи может расходоваться быстрее."</string>
<string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"Доступ к приблизительному местоположению только в активном режиме"</string>
<string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Приложение сможет получать сведения о вашем приблизительном местоположении, только когда используется. Для этого на устройстве должна быть включена геолокация."</string>
- <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"доступ к геоданным в фоновом режиме"</string>
+ <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"Доступ к геоданным в фоновом режиме"</string>
<string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Приложение сможет получать доступ к сведениям о местоположении, даже когда не используется."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"Изменение настроек аудио"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Приложение сможет изменять системные настройки звука, например уровень громкости и активный динамик."</string>
@@ -457,7 +457,7 @@
<string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"Приложение может в любое время записывать аудио с помощью микрофона."</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"Отправка команд SIM-карте"</string>
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Приложение сможет отправлять команды SIM-карте (данное разрешение представляет большую угрозу)."</string>
- <string name="permlab_activityRecognition" msgid="1782303296053990884">"распознавать физическую активность"</string>
+ <string name="permlab_activityRecognition" msgid="1782303296053990884">"Распознавать физическую активность"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"Приложение может распознавать физическую активность."</string>
<string name="permlab_camera" msgid="6320282492904119413">"Фото- и видеосъемка"</string>
<string name="permdesc_camera" msgid="5240801376168647151">"Когда приложение используется, оно может делать фотографии и снимать видео с помощью камеры."</string>
@@ -512,8 +512,8 @@
<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">"Приложение сможет создавать сетевые сокеты и использовать различные сетевые протоколы. Так как браузер и другие приложения обеспечивают средства для отправки данных в Интернет, это разрешение предоставлять не обязательно."</string>
+ <string name="permlab_createNetworkSockets" msgid="3224420491603590541">"Неограниченный доступ к интернету"</string>
+ <string name="permdesc_createNetworkSockets" msgid="7722020828749535988">"Приложение сможет создавать сетевые сокеты и использовать различные сетевые протоколы. Так как браузер и другие приложения обеспечивают средства для отправки данных в интернет, это разрешение предоставлять не обязательно."</string>
<string name="permlab_changeNetworkState" msgid="8945711637530425586">"Изменение сетевых настроек"</string>
<string name="permdesc_changeNetworkState" msgid="649341947816898736">"Приложение сможет изменять состояние подключения к сети."</string>
<string name="permlab_changeTetherState" msgid="9079611809931863861">"Изменение подключения к компьютеру"</string>
@@ -540,9 +540,9 @@
<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="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="permlab_bluetooth_connect" msgid="6657463246355003528">"Доступ к подключенным устройствам Bluetooth"</string>
<string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"У приложения будет доступ к подключенным устройствам Bluetooth."</string>
<string name="permlab_bluetooth_advertise" msgid="2781147747928853177">"Передача рекламы на устройства Bluetooth рядом"</string>
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Приложение сможет передавать рекламу на устройства Bluetooth поблизости."</string>
@@ -568,7 +568,7 @@
<string name="permdesc_videoWrite" msgid="6124731210613317051">"Приложение сможет вносить изменения в вашу видеоколлекцию."</string>
<string name="permlab_imagesWrite" msgid="1774555086984985578">"изменение фотоколлекции"</string>
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Приложение сможет вносить изменения в вашу фотоколлекцию."</string>
- <string name="permlab_mediaLocation" msgid="7368098373378598066">"доступ к геоданным в медиаколлекции"</string>
+ <string name="permlab_mediaLocation" msgid="7368098373378598066">"Доступ к геоданным в медиаколлекции"</string>
<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>
@@ -1498,10 +1498,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Приложение сможет запрашивать разрешения на удаление пакетов."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"Без ограничения расхода батареи"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Разрешает приложению игнорировать ограничение на расход заряда батареи."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"Запрос информации обо всех пакетах"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Приложение сможет просматривать все установленные пакеты."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Нажмите дважды для изменения масштаба"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Не удалось добавить виджет."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Выбрать"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 6064103..13df5e2 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"ස්ථාපන පැකේජ මැකීමට යෙදුමකට ඉඩ දීම."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"බැටරි ප්රශස්තකරණ නොසලකා හැරීමට ඉල්ලන්න"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"යෙදුමකට එම යෙදුම සඳහා බැටරි ප්රශස්තකරණ නොසලකා හැරීමට අවසර ඉල්ලීමට ඉඩ දෙයි."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"සියලු පැකේජ විමසන්න"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"ස්ථාපනය කර ඇති සියලු පැකේජ බැලීමට යෙදුමකට ඉඩ දෙයි."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"විශාලන පාලක සඳහා දෙවතාවක් තට්ටු කරන්න"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"විජටය එකතු කිරීමට නොහැකි විය."</string>
<string name="ime_action_go" msgid="5536744546326495436">"යන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index e42cc01..4f8329a 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1025,7 +1025,7 @@
<string name="text_copied" msgid="2531420577879738860">"Text bol skopírovaný do schránky."</string>
<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="7355790625710831847">"Aplikácia <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> bola prilepená zo schránky"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Aplikácia <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> vložila obsah zo schránky"</string>
<string name="pasted_text" msgid="4298871641549173733">"Aplikácia <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> prilepila text, ktorý ste skopírovali"</string>
<string name="pasted_image" msgid="4729097394781491022">"Aplik. <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> prilepila obrázok, ktorý ste skopírovali"</string>
<string name="pasted_content" msgid="646276353060777131">"Aplikácia <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> prilepila obsah, ktorý ste skopírovali"</string>
@@ -1498,10 +1498,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Umožňuje aplikácii vyžiadať odstránenie balíkov."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"požiadať o ignorovanie optimalizácií výdrže batérie"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Umožňuje aplikácii požiadať o povolenie ignorovať optimalizácie výdrže batérie pre danú aplikáciu."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"dopytovať všetky balíky"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Povoľuje aplikácii čítať všetky nainštalované balíky."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Dvojitým klepnutím môžete ovládať priblíženie"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Miniaplikáciu sa nepodarilo pridať."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Hľadať"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 506c066..fb6fc9a 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1498,10 +1498,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Omogoča aplikaciji, da zahteva brisanje paketov."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"Dovoljenje za prezrtje optimizacij baterije"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Aplikaciji dovoljuje, da vpraša za dovoljenje, ali naj prezre optimizacije baterije."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"poizvedovanje po vseh paketih"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Aplikaciji dovoli, da vidi vse nameščene pakete."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tapnite dvakrat za nadzor povečave/pomanjšave"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Pripomočka ni bilo mogoče dodati."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Pojdi"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index ed6a616..646cc85 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Teksti u kopjua në kujtesën e fragmenteve."</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ngjitur nga kujtesa jote e fragmenteve"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ngjiti përmbajtje nga kujtesa jote e fragmenteve"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ngjiti një tekst që kopjove"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ngjiti një imazh që kopjove"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ngjiti një përmbajtje që kopjove"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Lejon që një aplikacion të kërkojë fshirjen e paketave."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"kërko të shpërfillësh optimizimet e baterisë"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Lejon që një aplikacion të kërkojë leje për të shpërfillur optimizimet e baterisë për atë aplikacion."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"kërko të gjitha paketat"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Lejon një aplikacion të shikojë të gjitha paketat e instaluara."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Trokit dy herë për të kontrolluar zmadhimin"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Nuk mundi të shtonte miniaplikacion."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Shko"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 14f5673..98ddb39 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -365,11 +365,11 @@
<string name="permlab_receiveMms" msgid="4000650116674380275">"пријем текстуалних порука (MMS)"</string>
<string name="permdesc_receiveMms" msgid="958102423732219710">"Дозвољава апликацији да прима и обрађује MMS поруке. То значи да апликација може да надгледа или брише поруке које се шаљу уређају, а да вам их не прикаже."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Прослеђивање порука за мобилне уређаје на локалитету"</string>
- <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозвољава апликацији да се везује за модул порука за мобилне уређаје на локалитету да би прослеђивала поруке за мобилне уређаје на локалитету онако како су примљене. Обавештења порука за мобилне уређаје на локалитету се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају рад уређаја када се прими порука о хитном случају за мобилне уређаје на локалитету."</string>
+ <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозвољава апликацији да се везује за модул порука за мобилне уређаје на локалитету да би прослеђивала поруке за мобилне уређаје на локалитету онако како су примљене. Обавештења порука за мобилне уређаје на локалитету се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на перформансе или ометају рад уређаја када се прими порука о хитном случају за мобилне уређаје на локалитету."</string>
<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>
@@ -1022,7 +1022,7 @@
<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="7355790625710831847">"Садржај апликације <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> је налепљен у привр. меморију"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> је прелепио/ла из привремене меморије"</string>
<string name="pasted_text" msgid="4298871641549173733">"Апликација<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> је налепила текст који сте копирали"</string>
<string name="pasted_image" msgid="4729097394781491022">"Апликација<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> је налепила слику коју сте копирали"</string>
<string name="pasted_content" msgid="646276353060777131">"Апликација<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> је налепила садржај који сте копирали"</string>
@@ -1283,7 +1283,7 @@
<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>
- <string name="heavy_weight_switcher_text" msgid="6814316627367160126">"Да би учинак био бољи, можете да отворите само једну од ових игара одједном."</string>
+ <string name="heavy_weight_switcher_text" msgid="6814316627367160126">"Да би перформансе биле боље, може да буде отворена само једна од ових игара."</string>
<string name="old_app_action" msgid="725331621042848590">"Назад на <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
<string name="new_app_action" msgid="547772182913269801">"Отвори <xliff:g id="NEW_APP">%1$s</xliff:g>"</string>
<string name="new_app_description" msgid="1958903080400806644">"<xliff:g id="OLD_APP">%1$s</xliff:g> ће се затворити без чувања"</string>
@@ -1395,7 +1395,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>
@@ -1478,10 +1478,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Омогућава да апликација захтева брисање пакета."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"тражење дозволе за игнорисање оптимизација батерије"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Дозвољава апликацији да тражи дозволу за игнорисање оптимизација батерије за ту апликацију."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"слање упита за све пакете"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Дозвољава апликацији да види све инсталиране пакете."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Додирните двапут за контролу зумирања"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Није могуће додати виџет."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Иди"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index f5e1f81..f155f3c 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Tillåter att en app begär paketborttagning."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"får be om tillstånd att ignorera batterioptimering"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Appen får be om tillstånd att ignorera batterioptimering."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"fråga alla paket"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Tillåter att en app ser alla installerade paket."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Peka två gånger för zoomkontroll"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Det gick inte att lägga till widgeten."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Kör"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index c05f866..8ca0ac0 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Huruhusu programu kuomba idhini ya kufuta vifurushi."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"omba kupuuza uimarishji wa betri"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Huruhusu programu kuomba ruhusa ya kupuuza uimarishaji wa betri katika programu yako."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"kutuma hoja kwa vifurushi vyote"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Huruhusu programu kuona vifurushi vyote vilivyosakinishwa."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Gusa mara mbili kwa udhibiti wa kuza"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Haikuweza kuongeza wijeti."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Nenda"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 9be38c9..4a50960 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"தொகுப்புகளை நீக்க கோர, ஆப்ஸை அனுமதிக்கும்."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"பேட்டரி மேம்படுத்தல்களைப் புறக்கணிப்பதற்கான அனுமதியைக் கோரு"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"பயன்பாட்டிற்கான பேட்டரி மேம்படுத்தல்களைப் புறக்கணிப்பதற்கான அனுமதியைக் கோர, ஆப்ஸை அனுமதிக்கும்."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"அனைத்துப் பேக்கேஜ்களையும் பார்க்க அனுமதித்தல்"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"நிறுவப்பட்டுள்ள அனைத்துப் பேக்கேஜ்களையும் பார்ப்பதற்கு ஆப்ஸை அனுமதிக்கும்."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"அளவை மாற்றுவதற்கான கட்டுப்பாட்டிற்கு, இருமுறை தட்டவும்"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"விட்ஜெட்டைச் சேர்க்க முடியவில்லை."</string>
<string name="ime_action_go" msgid="5536744546326495436">"செல்"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b6c6ed5c2..3f9ae3a 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -658,7 +658,7 @@
<string-array name="face_error_vendor">
</string-array>
<string name="face_icon_content_description" msgid="465030547475916280">"ไอคอนใบหน้า"</string>
- <string name="permlab_readSyncSettings" msgid="6250532864893156277">"อ่านการตั้งค่าการซิงค์แล้ว"</string>
+ <string name="permlab_readSyncSettings" msgid="6250532864893156277">"อ่านการตั้งค่าการซิงค์"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"อนุญาตให้แอปพลิเคชันอ่านการตั้งค่าการซิงค์ของบัญชี ตัวอย่างเช่น การอนุญาตนี้สามารถระบุได้ว่าแอปพลิเคชัน People ซิงค์กับบัญชีหรือไม่"</string>
<string name="permlab_writeSyncSettings" msgid="6583154300780427399">"สลับระหว่างเปิดและปิดการซิงค์"</string>
<string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงการตั้งค่าการซิงค์ของบัญชี ตัวอย่างเช่น สามารถใช้การอนุญาตเปิดใช้งานการซิงค์แอปพลิเคชัน People กับบัญชี"</string>
@@ -1019,7 +1019,7 @@
<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="7355790625710831847">"วาง <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> จากคลิปบอร์ดแล้ว"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ได้วางข้อมูลจากคลิปบอร์ดแล้ว"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> วางข้อความที่คุณคัดลอก"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> วางรูปภาพที่คุณคัดลอก"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> วางเนื้อหาที่คุณคัดลอก"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"อนุญาตให้แอปพลิเคชันขอการลบแพ็กเกจ"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"ขอเพิกเฉยต่อการเพิ่มประสิทธิภาพแบตเตอรี่"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"อนุญาตให้แอปขอสิทธิ์เพิกเฉยต่อการเพิ่มประสิทธิภาพแบตเตอรี่สำหรับแอปนั้น"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"ค้นหาแพ็กเกจทั้งหมด"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"อนุญาตให้แอปดูแพ็กเกจที่ติดตั้งไว้ทั้งหมด"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"แตะสองครั้งเพื่อควบคุมการซูม"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ไม่สามารถเพิ่มวิดเจ็ต"</string>
<string name="ime_action_go" msgid="5536744546326495436">"ไป"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 4ea1da9..edc7427 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Pinapayagan ang isang application na humiling ng pag-delete ng mga package."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"hilingin na balewalain ang mga pag-optimize ng baterya"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Pinapayagang humingi ng pahintulot ang isang app na balewalain ang mga pag-optimize ng baterya para sa app na iyon."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"i-query ang lahat ng package"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Nagbibigay-daan sa isang app na makita ang lahat ng naka-install na package."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tapikin ng dalawang beses para sa pagkontrol ng zoom"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Hindi maidagdag ang widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Pumunta"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 306fc82..e5f9fe9 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Uygulamaya, paketleri silme isteğinde bulunma izni verir."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"pil optimizasyonlarını göz ardı etme izni iste"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Bir uygulamanın, kendisi için pil optimizasyonlarını göz ardı etme izni istemesine olanak sağlar."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"tüm paketleri sorgulama"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Uygulamaya tüm yüklü paketleri görme izni verir."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Zum denetimi için iki kez dokun"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Widget eklenemedi."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Git"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index baf4a44..964c077 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1498,10 +1498,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Додаток зможе надсилати запити на видалення пакетів."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"запитувати дозвіл ігнорувати оптимізацію використання заряду акумулятора"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Додаток зможе запитувати дозвіл ігнорувати оптимізацію використання заряду акумулятора."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"подавати запити на всі пакети"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Дозволяє додатку переглядати всі встановлені пакети."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Двічі натис. для кер. масшт."</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Не вдалося додати віджет."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Йти"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 8318021..7f5046b 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"متن کو کلپ بورڈ پر کاپی کیا گیا۔"</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> نے آپ کے کلپ بورڈ سے پپیسٹ کر دیا"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> نے آپ کے کلپ بورڈ سے پپیسٹ کر دیا"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> نے آپ کا کاپی کردہ ٹیکسٹ پیسٹ کر دیا"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> نے آپ کی کاپی کردہ ایک تصویر پیسٹ کر دی"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> نے آپ کا کاپی کردہ مواد پیسٹ کر دیا"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"ایپلیکیشن کو پیکجز حذف کرنے کیلئے درخواست کرنے کی اجازت ہے۔"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"بیٹری کی بہتریاں نظر انداز کرنے کا پوچھیں"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"اس ایپ کیلئے ایک ایپ کو بیٹری کی کارکردگی بہتر بنانے کو نظر انداز کرنے کی اجازت دیں۔"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"سبھی پیکیجز سے متعلق استفسار کریں"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"ایپ کو سبھی انسٹال کردہ پیکیجز دیکھنے کی اجازت دیتا ہے۔"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"زوم کنٹرول کیلئے دوبار تھپتھپائیں"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"ویجٹس کو شامل نہیں کرسکا۔"</string>
<string name="ime_action_go" msgid="5536744546326495436">"جائیں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 4c30b54..d8769b2 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1019,7 +1019,7 @@
<string name="text_copied" msgid="2531420577879738860">"Matn klipboardga nusxa olindi."</string>
<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="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> vaqtinchalik xotiradan joylandi"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> vaqtinchalik xotiradan joyladi"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> siz nusxa olgan matnni joyladi"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> siz nusxa olgan rasmni joyladi"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> siz nusxa olgan kontentni joyladi"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Ilovaga paketlarni o‘chirib tashlash so‘rovini yuborish imkonini beradi."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"batareya quvvatidan xohlagancha foydalanishni so‘rash"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Ilovaga batareya quvvatidan xohlagancha foydalanish uchun ruxsat so‘rashga imkon beradi."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"barcha paketlarni chiqarish"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Ilova oʻrnatilgan barcha paketlarni koʻrishiga ruxsat beradi"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Ko‘lamini o‘zgartirish uchun ikki marta bosing"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Vidjet qo‘shilmadi."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Tanlash"</string>
@@ -1990,8 +1988,8 @@
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Fayllarni ko‘rish uchun bosing"</string>
<string name="pin_target" msgid="8036028973110156895">"Qadash"</string>
<string name="pin_specific_target" msgid="7824671240625957415">"Mahkamlash: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="unpin_target" msgid="3963318576590204447">"Olib tashlash"</string>
- <string name="unpin_specific_target" msgid="3859828252160908146">"Olib tashlash: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="unpin_target" msgid="3963318576590204447">"Yechib olish"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Yechib olish: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Ilova haqida"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demo boshlanmoqda…"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 61aba14..b276ff1 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Cho phép ứng dụng yêu cầu xóa gói."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"hỏi để bỏ qua tối ưu hóa pin"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Cho phép ứng dụng hỏi quyền để bỏ qua tối ưu hóa pin cho ứng dụng đó."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"truy vấn tất cả các gói"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Cho phép một ứng dụng xem tất cả các gói đã cài đặt."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Nhấn hai lần để kiểm soát thu phóng"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Không thể thêm tiện ích."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Đến"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 7fefe74..b745661 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"允许应用请求删除文件包。"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"请求忽略电池优化"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"允许应用请求相应的权限,以便忽略针对该应用的电池优化。"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"查询所有软件包"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"允许应用查看所有已安装的软件包。"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"双击可以进行缩放控制"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"无法添加微件。"</string>
<string name="ime_action_go" msgid="5536744546326495436">"开始"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 457f0d5..fd0bd9f 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1019,7 +1019,7 @@
<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="7355790625710831847">"已將剪貼簿內容貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」已貼上剪貼簿內容"</string>
<string name="pasted_text" msgid="4298871641549173733">"您複製的文字已貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
<string name="pasted_image" msgid="4729097394781491022">"您複製的圖片已貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
<string name="pasted_content" msgid="646276353060777131">"您複製的內容已貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"允許應用程式要求刪除套件。"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"要求忽略電池優化"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"允許應用程式要求就該應用程式忽略電池優化。"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"查詢所有套件"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"允許應用程式查看所有已安裝的套件。"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"輕觸兩下控制縮放"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"無法新增小工具。"</string>
<string name="ime_action_go" msgid="5536744546326495436">"開始"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 82be318..310663f 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"允許應用程式要求刪除套件。"</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"要求忽略電池效能最佳化設定"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"允許應用程式要求權限,以便忽略針對該應用程式的電池效能最佳化設定。"</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"查詢所有套件"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"允許應用程式查看所有已安裝的套件。"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"點兩下以進行縮放控制"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"無法新增小工具。"</string>
<string name="ime_action_go" msgid="5536744546326495436">"開始"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 85cf88c..ae01829 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1458,10 +1458,8 @@
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Ivumela uhlelo lokusebenza ukuthi lucele ukususwa kwamaphakheji."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"cela ukuziba ukulungiselelwa kwebhethri"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Ivumela uhlelo lokusebenza ukuthi licele imvume yokuziba ukulungiselela ibhethri yalolo hlelo lokusebenza."</string>
- <!-- no translation found for permlab_queryAllPackages (2928450604653281650) -->
- <skip />
- <!-- no translation found for permdesc_queryAllPackages (5339069855520996010) -->
- <skip />
+ <string name="permlab_queryAllPackages" msgid="2928450604653281650">"buza wonke amaphakheji"</string>
+ <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"Ivumela i-app ibone wonke amaphakheji afakiwe."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Thepha kabili ukuthola ukulawula ukusondeza"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Yehlulekile ukwengeza i-widget."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Iya"</string>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index d94bcfb..55ed83b 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -140,7 +140,7 @@
<color name="notification_secondary_text_color_light">@color/primary_text_default_material_light</color>
<item name="notification_secondary_text_disabled_alpha" format="float" type="dimen">0.38</item>
<color name="notification_secondary_text_color_dark">@color/primary_text_default_material_dark</color>
- <color name="notification_default_color_dark">@color/primary_text_default_material_light</color>
+ <color name="notification_default_color_dark">#ddffffff</color>
<color name="notification_default_color_light">#a3202124</color>
<color name="notification_primary_text_color_current">@color/notification_primary_text_color_light</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ee33d48..3c47366 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3529,6 +3529,12 @@
<!-- If true, all guest users created on the device will be ephemeral. -->
<bool name="config_guestUserEphemeral">false</bool>
+ <!-- Whether device should always have a guest user available. If true, guest user will be
+ created on boot, and a new guest user will be created in the background anytime the current
+ guest user is removed. Instead of showing "Add guest" and "Remove guest", the UI will show
+ "Guest" and "Reset guest". -->
+ <bool name="config_guestUserAutoCreated">false</bool>
+
<!-- Enforce strong auth on boot. Setting this to false represents a security risk and should
not be ordinarily done. The only case in which this might be permissible is in a car head
unit where there are hardware mechanisms to protect the device (physical keys) and not
@@ -4521,6 +4527,9 @@
-->
</integer-array>
+ <!-- How long it takes for the HW to start illuminating after the illumination is requested. -->
+ <integer name="config_udfps_illumination_transition_ms">50</integer>
+
<!-- Indicates whether device has a power button fingerprint sensor. -->
<bool name="config_is_powerbutton_fps" translatable="false" >false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7d685a2..97a2a38 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -402,6 +402,7 @@
<java-symbol type="bool" name="config_supportsSystemDecorsOnSecondaryDisplays" />
<java-symbol type="bool" name="config_supportsInsecureLockScreen" />
<java-symbol type="bool" name="config_guestUserEphemeral" />
+ <java-symbol type="bool" name="config_guestUserAutoCreated" />
<java-symbol type="bool" name="config_localDisplaysMirrorContent" />
<java-symbol type="array" name="config_localPrivateDisplayPorts" />
<java-symbol type="integer" name="config_defaultDisplayDefaultColorMode" />
@@ -2590,6 +2591,7 @@
<java-symbol type="array" name="config_biometric_sensors" />
<java-symbol type="bool" name="allow_test_udfps" />
<java-symbol type="array" name="config_udfps_sensor_props" />
+ <java-symbol type="integer" name="config_udfps_illumination_transition_ms" />
<java-symbol type="bool" name="config_is_powerbutton_fps" />
<java-symbol type="array" name="config_face_acquire_enroll_ignorelist" />
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index 46e2772..90a9572 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -44,6 +44,7 @@
BatteryStatsUidTest.class,
BatteryUsageStatsProviderTest.class,
BatteryUsageStatsTest.class,
+ BatteryUsageStatsStoreTest.class,
BatteryStatsUserLifecycleTests.class,
BluetoothPowerCalculatorTest.class,
BstatsCpuTimesValidationTest.class,
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
index d83645d..cbd67c8 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
@@ -20,10 +20,14 @@
import android.app.ActivityManager;
import android.content.Context;
+import android.os.BatteryConsumer;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.os.Parcel;
import android.os.Process;
import android.os.UidBatteryConsumer;
@@ -36,6 +40,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.File;
import java.util.List;
@SmallTest
@@ -45,7 +50,8 @@
private static final long MINUTE_IN_MS = 60 * 1000;
@Rule
- public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(12345);
+ public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(12345)
+ .setAveragePower(PowerProfile.POWER_FLASHLIGHT, 360.0);
@Test
public void test_getBatteryUsageStats() {
@@ -187,4 +193,84 @@
mStatsRule.setTime(11500, 0);
assertThat(provider.shouldUpdateStats(queries, 10000)).isTrue();
}
+
+ @Test
+ public void testAggregateBatteryStats() {
+ Context context = InstrumentationRegistry.getContext();
+ BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+ mStatsRule.setCurrentTime(5 * MINUTE_IN_MS);
+ batteryStats.resetAllStatsCmdLocked();
+
+ BatteryUsageStatsStore batteryUsageStatsStore = new BatteryUsageStatsStore(context,
+ batteryStats, new File(context.getCacheDir(), "BatteryUsageStatsProviderTest"),
+ new TestHandler(), Integer.MAX_VALUE);
+
+ BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context,
+ batteryStats, batteryUsageStatsStore);
+
+ batteryStats.noteFlashlightOnLocked(APP_UID,
+ 10 * MINUTE_IN_MS, 10 * MINUTE_IN_MS);
+ batteryStats.noteFlashlightOffLocked(APP_UID,
+ 20 * MINUTE_IN_MS, 20 * MINUTE_IN_MS);
+ mStatsRule.setCurrentTime(25 * MINUTE_IN_MS);
+ batteryStats.resetAllStatsCmdLocked();
+
+ batteryStats.noteFlashlightOnLocked(APP_UID,
+ 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS);
+ batteryStats.noteFlashlightOffLocked(APP_UID,
+ 50 * MINUTE_IN_MS, 50 * MINUTE_IN_MS);
+ mStatsRule.setCurrentTime(55 * MINUTE_IN_MS);
+ batteryStats.resetAllStatsCmdLocked();
+
+ // This section should be ignored because the timestamp is out or range
+ batteryStats.noteFlashlightOnLocked(APP_UID,
+ 60 * MINUTE_IN_MS, 60 * MINUTE_IN_MS);
+ batteryStats.noteFlashlightOffLocked(APP_UID,
+ 70 * MINUTE_IN_MS, 70 * MINUTE_IN_MS);
+ mStatsRule.setCurrentTime(75 * MINUTE_IN_MS);
+ batteryStats.resetAllStatsCmdLocked();
+
+ // This section should be ignored because it represents the current stats session
+ batteryStats.noteFlashlightOnLocked(APP_UID,
+ 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
+ batteryStats.noteFlashlightOffLocked(APP_UID,
+ 90 * MINUTE_IN_MS, 90 * MINUTE_IN_MS);
+ mStatsRule.setCurrentTime(95 * MINUTE_IN_MS);
+
+ // Include the first and the second snapshot, but not the third or current
+ BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder()
+ .aggregateSnapshots(20 * MINUTE_IN_MS, 60 * MINUTE_IN_MS)
+ .build();
+ final BatteryUsageStats stats = provider.getBatteryUsageStats(query);
+
+ assertThat(stats.getStatsStartTimestamp()).isEqualTo(5 * MINUTE_IN_MS);
+ assertThat(stats.getStatsEndTimestamp()).isEqualTo(55 * MINUTE_IN_MS);
+ assertThat(stats.getAggregateBatteryConsumer(
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
+ .getConsumedPower(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
+ .isWithin(0.0001)
+ .of(180.0); // 360 mA * 0.5 hours
+ assertThat(stats.getAggregateBatteryConsumer(
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
+ .getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
+ .isEqualTo((10 + 20) * MINUTE_IN_MS);
+ final UidBatteryConsumer uidBatteryConsumer = stats.getUidBatteryConsumers().stream()
+ .filter(uid -> uid.getUid() == APP_UID).findFirst().get();
+ assertThat(uidBatteryConsumer
+ .getConsumedPower(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
+ .isWithin(0.1)
+ .of(180.0);
+ }
+
+ private static class TestHandler extends Handler {
+ TestHandler() {
+ super(Looper.getMainLooper());
+ }
+
+ @Override
+ public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
+ msg.getCallback().run();
+ return true;
+ }
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java
new file mode 100644
index 0000000..141a9fa
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java
@@ -0,0 +1,196 @@
+/*
+ * 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 static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
+import android.os.BatteryManager;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.TypedXmlSerializer;
+import android.util.Xml;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+@RunWith(AndroidJUnit4.class)
+public class BatteryUsageStatsStoreTest {
+ private static final long MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES = 2 * 1024;
+
+ private final MockClocks mMockClocks = new MockClocks();
+ private MockBatteryStatsImpl mBatteryStats;
+ private BatteryUsageStatsStore mBatteryUsageStatsStore;
+ private BatteryUsageStatsProvider mBatteryUsageStatsProvider;
+ private File mStoreDirectory;
+
+ @Before
+ public void setup() {
+ mMockClocks.currentTime = 123;
+ mBatteryStats = new MockBatteryStatsImpl(mMockClocks);
+ mBatteryStats.setNoAutoReset(true);
+ mBatteryStats.setPowerProfile(mock(PowerProfile.class));
+
+ Context context = InstrumentationRegistry.getContext();
+
+ mStoreDirectory = new File(context.getCacheDir(), "BatteryUsageStatsStoreTest");
+ clearDirectory(mStoreDirectory);
+
+ mBatteryUsageStatsStore = new BatteryUsageStatsStore(context, mBatteryStats,
+ mStoreDirectory, new TestHandler(), MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES);
+
+ mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mBatteryStats);
+ }
+
+ @Test
+ public void testStoreSnapshot() {
+ mMockClocks.currentTime = 1_600_000;
+
+ prepareBatteryStats();
+ mBatteryStats.resetAllStatsCmdLocked();
+
+ final long[] timestamps = mBatteryUsageStatsStore.listBatteryUsageStatsTimestamps();
+ assertThat(timestamps).hasLength(1);
+ assertThat(timestamps[0]).isEqualTo(1_600_000);
+
+ final BatteryUsageStats batteryUsageStats = mBatteryUsageStatsStore.loadBatteryUsageStats(
+ 1_600_000);
+ assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(123);
+ assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(1_600_000);
+ assertThat(batteryUsageStats.getBatteryCapacity()).isEqualTo(4000);
+ assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(5);
+ assertThat(batteryUsageStats.getAggregateBatteryConsumer(
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE).getConsumedPower())
+ .isEqualTo(600); // (3_600_000 - 3_000_000) / 1000
+ }
+
+ @Test
+ public void testGarbageCollectOldSnapshots() throws Exception {
+ prepareBatteryStats();
+
+ mMockClocks.realtime = 10_000_000;
+ mMockClocks.uptime = 10_000_000;
+ mMockClocks.currentTime = 10_000_000;
+
+ final int snapshotFileSize = getSnapshotFileSize();
+ final int numberOfSnapshots =
+ (int) (MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES / snapshotFileSize);
+ for (int i = 0; i < numberOfSnapshots + 2; i++) {
+ mBatteryStats.resetAllStatsCmdLocked();
+
+ mMockClocks.realtime += 10_000_000;
+ mMockClocks.uptime += 10_000_000;
+ mMockClocks.currentTime += 10_000_000;
+ prepareBatteryStats();
+ }
+
+ final long[] timestamps = mBatteryUsageStatsStore.listBatteryUsageStatsTimestamps();
+ Arrays.sort(timestamps);
+ assertThat(timestamps).hasLength(numberOfSnapshots);
+ // Two snapshots (10_000_000 and 20_000_000) should have been discarded
+ assertThat(timestamps[0]).isEqualTo(30_000_000);
+ assertThat(getDirectorySize(mStoreDirectory))
+ .isAtMost(MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES);
+ }
+
+ @Test
+ public void testSavingStatsdAtomPullTimestamp() {
+ mBatteryUsageStatsStore.setLastBatteryUsageStatsBeforeResetAtomPullTimestamp(1234);
+ assertThat(mBatteryUsageStatsStore.getLastBatteryUsageStatsBeforeResetAtomPullTimestamp())
+ .isEqualTo(1234);
+ mBatteryUsageStatsStore.setLastBatteryUsageStatsBeforeResetAtomPullTimestamp(5478);
+ assertThat(mBatteryUsageStatsStore.getLastBatteryUsageStatsBeforeResetAtomPullTimestamp())
+ .isEqualTo(5478);
+ }
+
+ private void prepareBatteryStats() {
+ mBatteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
+ /* plugType */ 0, 90, 72, 3700, 3_600_000, 4_000_000, 0,
+ mMockClocks.realtime, mMockClocks.uptime, mMockClocks.currentTime);
+ mBatteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
+ /* plugType */ 0, 85, 72, 3700, 3_000_000, 4_000_000, 0,
+ mMockClocks.realtime + 500_000, mMockClocks.uptime + 500_000,
+ mMockClocks.currentTime + 500_000);
+ }
+
+ private void clearDirectory(File dir) {
+ if (dir.exists()) {
+ for (File child : dir.listFiles()) {
+ if (child.isDirectory()) {
+ clearDirectory(child);
+ }
+ child.delete();
+ }
+ }
+ }
+
+ private long getDirectorySize(File dir) {
+ long size = 0;
+ if (dir.exists()) {
+ for (File child : dir.listFiles()) {
+ if (child.isDirectory()) {
+ size += getDirectorySize(child);
+ } else {
+ size += child.length();
+ }
+ }
+ }
+ return size;
+ }
+
+ private int getSnapshotFileSize() throws IOException {
+ BatteryUsageStats stats = mBatteryUsageStatsProvider.getBatteryUsageStats(
+ new BatteryUsageStatsQuery.Builder()
+ .setMaxStatsAgeMs(0)
+ .includePowerModels()
+ .build());
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ TypedXmlSerializer serializer = Xml.newBinarySerializer();
+ serializer.setOutput(out, StandardCharsets.UTF_8.name());
+ serializer.startDocument(null, true);
+ stats.writeXml(serializer);
+ serializer.endDocument();
+ return out.toByteArray().length;
+ }
+
+ private static class TestHandler extends Handler {
+ TestHandler() {
+ super(Looper.getMainLooper());
+ }
+
+ @Override
+ public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
+ msg.getCallback().run();
+ return true;
+ }
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
index 380b4ae..3e620c2 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
@@ -16,8 +16,13 @@
package com.android.internal.os;
+import static android.os.BatteryConsumer.POWER_MODEL_MEASURED_ENERGY;
+import static android.os.BatteryConsumer.POWER_MODEL_POWER_PROFILE;
+import static android.os.BatteryConsumer.POWER_MODEL_UNDEFINED;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
import android.os.BatteryConsumer;
@@ -25,6 +30,9 @@
import android.os.Parcel;
import android.os.UidBatteryConsumer;
import android.os.UserBatteryConsumer;
+import android.util.TypedXmlPullParser;
+import android.util.TypedXmlSerializer;
+import android.util.Xml;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -32,8 +40,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -42,15 +53,19 @@
@RunWith(AndroidJUnit4.class)
public class BatteryUsageStatsTest {
+ private static final int USER_ID = 42;
+ private static final int APP_UID1 = 271;
+ private static final int APP_UID2 = 314;
+
@Test
public void testBuilder() {
- BatteryUsageStats batteryUsageStats = buildBatteryUsageStats().build();
- validateBatteryUsageStats(batteryUsageStats);
+ BatteryUsageStats batteryUsageStats = buildBatteryUsageStats1(true).build();
+ assertBatteryUsageStats1(batteryUsageStats, true);
}
@Test
public void testParcelability() {
- final BatteryUsageStats outBatteryUsageStats = buildBatteryUsageStats().build();
+ final BatteryUsageStats outBatteryUsageStats = buildBatteryUsageStats1(true).build();
final Parcel outParcel = Parcel.obtain();
outParcel.writeParcelable(outBatteryUsageStats, 0);
final byte[] bytes = outParcel.marshall();
@@ -62,20 +77,20 @@
final BatteryUsageStats inBatteryUsageStats =
inParcel.readParcelable(getClass().getClassLoader());
assertThat(inBatteryUsageStats).isNotNull();
- validateBatteryUsageStats(inBatteryUsageStats);
+ assertBatteryUsageStats1(inBatteryUsageStats, true);
}
@Test
public void testDefaultSessionDuration() {
final BatteryUsageStats stats =
- buildBatteryUsageStats().setStatsDuration(10000).build();
+ buildBatteryUsageStats1(true).setStatsDuration(10000).build();
assertThat(stats.getStatsDuration()).isEqualTo(10000);
}
@Test
public void testDump() {
- final BatteryUsageStats stats = buildBatteryUsageStats().build();
+ final BatteryUsageStats stats = buildBatteryUsageStats1(true).build();
final StringWriter out = new StringWriter();
try (PrintWriter pw = new PrintWriter(out)) {
stats.dump(pw, " ");
@@ -87,7 +102,7 @@
assertThat(dump).contains("actual drain: 1000-2000");
assertThat(dump).contains("cpu: 20100 apps: 10100 duration: 20s 300ms");
assertThat(dump).contains("FOO: 20200 apps: 10200 duration: 20s 400ms");
- assertThat(dump).contains("UID 2000: 1200 ( screen=300 cpu=400 FOO=500 )");
+ assertThat(dump).contains("UID 271: 1200 ( screen=300 cpu=400 FOO=500 )");
assertThat(dump).contains("User 42: 30.0 ( cpu=10.0 FOO=20.0 )");
}
@@ -101,154 +116,297 @@
assertThat(allNames).hasSize(BatteryConsumer.POWER_COMPONENT_COUNT);
}
- private BatteryUsageStats.Builder buildBatteryUsageStats() {
- final MockClocks clocks = new MockClocks();
- final MockBatteryStatsImpl batteryStats = new MockBatteryStatsImpl(clocks);
- final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(2000);
+ @Test
+ public void testAdd() {
+ final BatteryUsageStats stats1 = buildBatteryUsageStats1(false).build();
+ final BatteryUsageStats stats2 = buildBatteryUsageStats2(new String[] {"FOO"}).build();
- final BatteryUsageStats.Builder builder =
- new BatteryUsageStats.Builder(new String[]{"FOO"}, true)
- .setBatteryCapacity(4000)
- .setDischargePercentage(20)
- .setDischargedPowerRange(1000, 2000)
- .setStatsStartTimestamp(1000)
- .setStatsEndTimestamp(3000);
- builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid)
- .setPackageWithHighestDrain("foo")
- .setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND, 1000)
- .setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND, 2000)
- .setConsumedPower(
- BatteryConsumer.POWER_COMPONENT_SCREEN, 300)
- .setConsumedPower(
- BatteryConsumer.POWER_COMPONENT_CPU, 400)
- .setConsumedPowerForCustomComponent(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 500)
- .setUsageDurationMillis(
- BatteryConsumer.POWER_COMPONENT_CPU, 600)
- .setUsageDurationForCustomComponentMillis(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 800);
+ final BatteryUsageStats sum =
+ new BatteryUsageStats.Builder(new String[] {"FOO"}, true)
+ .add(stats1)
+ .add(stats2)
+ .build();
- builder.getAggregateBatteryConsumerBuilder(
- BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS)
- .setConsumedPower(
- BatteryConsumer.POWER_COMPONENT_CPU, 10100)
- .setConsumedPowerForCustomComponent(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 10200)
- .setUsageDurationMillis(
- BatteryConsumer.POWER_COMPONENT_CPU, 10300)
- .setUsageDurationForCustomComponentMillis(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 10400);
-
- builder.getAggregateBatteryConsumerBuilder(
- BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
- .setConsumedPower(30000)
- .setConsumedPower(
- BatteryConsumer.POWER_COMPONENT_CPU, 20100)
- .setConsumedPowerForCustomComponent(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 20200)
- .setUsageDurationMillis(
- BatteryConsumer.POWER_COMPONENT_CPU, 20300)
- .setUsageDurationForCustomComponentMillis(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 20400);
-
- builder.getOrCreateUserBatteryConsumerBuilder(42)
- .setConsumedPower(
- BatteryConsumer.POWER_COMPONENT_CPU, 10)
- .setConsumedPowerForCustomComponent(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 20)
- .setUsageDurationMillis(
- BatteryConsumer.POWER_COMPONENT_CPU, 30)
- .setUsageDurationForCustomComponentMillis(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 40);
-
- return builder;
- }
-
- public void validateBatteryUsageStats(BatteryUsageStats batteryUsageStats) {
- assertThat(batteryUsageStats.getConsumedPower()).isEqualTo(30000);
- assertThat(batteryUsageStats.getBatteryCapacity()).isEqualTo(4000);
- assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(20);
- assertThat(batteryUsageStats.getDischargedPowerRange().getLower()).isEqualTo(1000);
- assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()).isEqualTo(2000);
- assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(1000);
- assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(3000);
- assertThat(batteryUsageStats.getStatsDuration()).isEqualTo(2000);
+ assertBatteryUsageStats(sum, 42345, 50, 2234, 4345, 1000, 5000, 5000);
final List<UidBatteryConsumer> uidBatteryConsumers =
- batteryUsageStats.getUidBatteryConsumers();
+ sum.getUidBatteryConsumers();
for (UidBatteryConsumer uidBatteryConsumer : uidBatteryConsumers) {
- if (uidBatteryConsumer.getUid() == 2000) {
- assertThat(uidBatteryConsumer.getPackageWithHighestDrain()).isEqualTo("foo");
- assertThat(uidBatteryConsumer.getTimeInStateMs(
- UidBatteryConsumer.STATE_FOREGROUND)).isEqualTo(1000);
- assertThat(uidBatteryConsumer.getTimeInStateMs(
- UidBatteryConsumer.STATE_BACKGROUND)).isEqualTo(2000);
- assertThat(uidBatteryConsumer.getConsumedPower(
- BatteryConsumer.POWER_COMPONENT_SCREEN)).isEqualTo(300);
- assertThat(uidBatteryConsumer.getConsumedPower(
- BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(400);
- assertThat(uidBatteryConsumer.getConsumedPowerForCustomComponent(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(500);
- assertThat(uidBatteryConsumer.getUsageDurationMillis(
- BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(600);
- assertThat(uidBatteryConsumer.getUsageDurationForCustomComponentMillis(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(800);
- assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(1200);
- assertThat(uidBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1);
- assertThat(uidBatteryConsumer.getCustomPowerComponentName(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO");
+ if (uidBatteryConsumer.getUid() == APP_UID1) {
+ assertUidBatteryConsumer(uidBatteryConsumer, 2124, null,
+ 5321, 7432, 423, POWER_MODEL_POWER_PROFILE, 745, POWER_MODEL_UNDEFINED,
+ 956, 1167, 1478);
+ } else if (uidBatteryConsumer.getUid() == APP_UID2) {
+ assertUidBatteryConsumer(uidBatteryConsumer, 1332, "bar",
+ 1111, 2222, 333, POWER_MODEL_POWER_PROFILE, 444, POWER_MODEL_POWER_PROFILE,
+ 555, 666, 777);
} else {
fail("Unexpected UID " + uidBatteryConsumer.getUid());
}
}
- final BatteryConsumer appsBatteryConsumer = batteryUsageStats.getAggregateBatteryConsumer(
- BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS);
- assertThat(appsBatteryConsumer.getConsumedPower(
- BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(10100);
- assertThat(appsBatteryConsumer.getConsumedPowerForCustomComponent(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(10200);
- assertThat(appsBatteryConsumer.getUsageDurationMillis(
- BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(10300);
- assertThat(appsBatteryConsumer.getUsageDurationForCustomComponentMillis(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(10400);
- assertThat(appsBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1);
- assertThat(appsBatteryConsumer.getCustomPowerComponentName(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO");
+ assertAggregateBatteryConsumer(sum,
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS,
+ 20223, 20434, 20645, 20856);
- final BatteryConsumer deviceBatteryConsumer = batteryUsageStats.getAggregateBatteryConsumer(
- BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE);
- assertThat(deviceBatteryConsumer.getConsumedPower(
- BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(20100);
- assertThat(deviceBatteryConsumer.getConsumedPowerForCustomComponent(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(20200);
- assertThat(deviceBatteryConsumer.getUsageDurationMillis(
- BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(20300);
- assertThat(deviceBatteryConsumer.getUsageDurationForCustomComponentMillis(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(20400);
- assertThat(deviceBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1);
- assertThat(deviceBatteryConsumer.getCustomPowerComponentName(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO");
+ assertAggregateBatteryConsumer(sum,
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE,
+ 40211, 40422, 40633, 40844);
+ }
+
+ @Test
+ public void testAdd_customComponentMismatch() {
+ final BatteryUsageStats.Builder builder =
+ new BatteryUsageStats.Builder(new String[] {"FOO"}, true);
+ final BatteryUsageStats stats = buildBatteryUsageStats2(new String[] {"BAR"}).build();
+
+ assertThrows(IllegalArgumentException.class, () -> builder.add(stats));
+ }
+
+ @Test
+ public void testXml() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ TypedXmlSerializer serializer = Xml.newBinarySerializer();
+ serializer.setOutput(out, StandardCharsets.UTF_8.name());
+ serializer.startDocument(null, true);
+ final BatteryUsageStats stats = buildBatteryUsageStats1(true).build();
+ stats.writeXml(serializer);
+ serializer.endDocument();
+
+ ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+ TypedXmlPullParser parser = Xml.newBinaryPullParser();
+ parser.setInput(in, StandardCharsets.UTF_8.name());
+ final BatteryUsageStats fromXml = BatteryUsageStats.createFromXml(parser);
+
+ assertBatteryUsageStats1(fromXml, true);
+ }
+
+ private BatteryUsageStats.Builder buildBatteryUsageStats1(boolean includeUserBatteryConsumer) {
+ final MockClocks clocks = new MockClocks();
+ final MockBatteryStatsImpl batteryStats = new MockBatteryStatsImpl(clocks);
+
+ final BatteryUsageStats.Builder builder =
+ new BatteryUsageStats.Builder(new String[] {"FOO"}, true)
+ .setBatteryCapacity(4000)
+ .setDischargePercentage(20)
+ .setDischargedPowerRange(1000, 2000)
+ .setStatsStartTimestamp(1000)
+ .setStatsEndTimestamp(3000);
+
+ addUidBatteryConsumer(builder, batteryStats, APP_UID1, "foo",
+ 1000, 2000,
+ 300, POWER_MODEL_POWER_PROFILE, 400, POWER_MODEL_POWER_PROFILE, 500, 600, 800);
+
+ addAggregateBatteryConsumer(builder,
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 0,
+ 10100, 10200, 10300, 10400);
+
+ addAggregateBatteryConsumer(builder,
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 30000,
+ 20100, 20200, 20300, 20400);
+
+
+ if (includeUserBatteryConsumer) {
+ builder.getOrCreateUserBatteryConsumerBuilder(USER_ID)
+ .setConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_CPU, 10)
+ .setConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 20)
+ .setUsageDurationMillis(
+ BatteryConsumer.POWER_COMPONENT_CPU, 30)
+ .setUsageDurationForCustomComponentMillis(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 40);
+ }
+ return builder;
+ }
+
+ private BatteryUsageStats.Builder buildBatteryUsageStats2(String[] customPowerComponentNames) {
+ final MockClocks clocks = new MockClocks();
+ final MockBatteryStatsImpl batteryStats = new MockBatteryStatsImpl(clocks);
+
+ final BatteryUsageStats.Builder builder =
+ new BatteryUsageStats.Builder(customPowerComponentNames, true)
+ .setDischargePercentage(30)
+ .setDischargedPowerRange(1234, 2345)
+ .setStatsStartTimestamp(2000)
+ .setStatsEndTimestamp(5000);
+
+ addUidBatteryConsumer(builder, batteryStats, APP_UID1, null,
+ 4321, 5432,
+ 123, POWER_MODEL_POWER_PROFILE, 345, POWER_MODEL_MEASURED_ENERGY, 456, 567, 678);
+
+ addUidBatteryConsumer(builder, batteryStats, APP_UID2, "bar",
+ 1111, 2222,
+ 333, POWER_MODEL_POWER_PROFILE, 444, POWER_MODEL_POWER_PROFILE, 555, 666, 777);
+
+ addAggregateBatteryConsumer(builder,
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 0,
+ 10123, 10234, 10345, 10456);
+
+ addAggregateBatteryConsumer(builder,
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 12345,
+ 20111, 20222, 20333, 20444);
+
+ return builder;
+ }
+
+ private void addUidBatteryConsumer(BatteryUsageStats.Builder builder,
+ MockBatteryStatsImpl batteryStats, int uid, String packageWithHighestDrain,
+ int timeInStateForeground, int timeInStateBackground, int screenPower,
+ int screenPowerModel, int cpuPower, int cpuPowerModel, int customComponentPower,
+ int cpuDuration, int customComponentDuration) {
+ final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(uid);
+ builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid)
+ .setPackageWithHighestDrain(packageWithHighestDrain)
+ .setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND, timeInStateForeground)
+ .setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND, timeInStateBackground)
+ .setConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_SCREEN, screenPower, screenPowerModel)
+ .setConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_CPU, cpuPower, cpuPowerModel)
+ .setConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, customComponentPower)
+ .setUsageDurationMillis(
+ BatteryConsumer.POWER_COMPONENT_CPU, cpuDuration)
+ .setUsageDurationForCustomComponentMillis(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, customComponentDuration);
+ }
+
+ private void addAggregateBatteryConsumer(BatteryUsageStats.Builder builder, int scope,
+ double consumedPower, int cpuPower, int customComponentPower, int cpuDuration,
+ int customComponentDuration) {
+ builder.getAggregateBatteryConsumerBuilder(scope)
+ .setConsumedPower(consumedPower)
+ .setConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_CPU, cpuPower)
+ .setConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, customComponentPower)
+ .setUsageDurationMillis(
+ BatteryConsumer.POWER_COMPONENT_CPU, cpuDuration)
+ .setUsageDurationForCustomComponentMillis(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, customComponentDuration);
+ }
+
+ public void assertBatteryUsageStats1(BatteryUsageStats batteryUsageStats,
+ boolean includesUserBatteryConsumers) {
+ assertBatteryUsageStats(batteryUsageStats, 30000, 20, 1000, 2000, 1000, 3000, 2000);
+
+ final List<UidBatteryConsumer> uidBatteryConsumers =
+ batteryUsageStats.getUidBatteryConsumers();
+ assertThat(uidBatteryConsumers).hasSize(1);
+ for (UidBatteryConsumer uidBatteryConsumer : uidBatteryConsumers) {
+ if (uidBatteryConsumer.getUid() == APP_UID1) {
+ assertUidBatteryConsumer(uidBatteryConsumer, 1200, "foo",
+ 1000, 2000, 300, POWER_MODEL_POWER_PROFILE, 400, POWER_MODEL_POWER_PROFILE,
+ 500, 600, 800);
+ } else {
+ fail("Unexpected UID " + uidBatteryConsumer.getUid());
+ }
+ }
final List<UserBatteryConsumer> userBatteryConsumers =
batteryUsageStats.getUserBatteryConsumers();
- for (UserBatteryConsumer userBatteryConsumer : userBatteryConsumers) {
- if (userBatteryConsumer.getUserId() == 42) {
- assertThat(userBatteryConsumer.getConsumedPower(
- BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(10);
- assertThat(userBatteryConsumer.getConsumedPowerForCustomComponent(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(20);
- assertThat(userBatteryConsumer.getUsageDurationMillis(
- BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(30);
- assertThat(userBatteryConsumer.getUsageDurationForCustomComponentMillis(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(40);
- assertThat(userBatteryConsumer.getConsumedPower()).isEqualTo(30);
- assertThat(userBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1);
- assertThat(userBatteryConsumer.getCustomPowerComponentName(
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO");
- } else {
- fail("Unexpected user ID " + userBatteryConsumer.getUserId());
+ if (includesUserBatteryConsumers) {
+ assertThat(userBatteryConsumers).hasSize(1);
+ for (UserBatteryConsumer userBatteryConsumer : userBatteryConsumers) {
+ if (userBatteryConsumer.getUserId() == USER_ID) {
+ assertUserBatteryConsumer(userBatteryConsumer, 42, 10, 20, 30, 40);
+ } else {
+ fail("Unexpected User ID " + userBatteryConsumer.getUserId());
+ }
}
+ } else {
+ assertThat(userBatteryConsumers).isEmpty();
}
+
+ assertAggregateBatteryConsumer(batteryUsageStats,
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS,
+ 10100, 10200, 10300, 10400);
+
+ assertAggregateBatteryConsumer(batteryUsageStats,
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE,
+ 20100, 20200, 20300, 20400);
+ }
+
+ private void assertBatteryUsageStats(BatteryUsageStats batteryUsageStats, int consumedPower,
+ int dischargePercentage, int dischagePowerLower, int dischargePowerUpper,
+ int statsStartTimestamp, int statsEndTimestamp, int statsDuration) {
+ assertThat(batteryUsageStats.getConsumedPower()).isEqualTo(consumedPower);
+ assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(dischargePercentage);
+ assertThat(batteryUsageStats.getDischargedPowerRange().getLower()).isEqualTo(
+ dischagePowerLower);
+ assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()).isEqualTo(
+ dischargePowerUpper);
+ assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(statsStartTimestamp);
+ assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(statsEndTimestamp);
+ assertThat(batteryUsageStats.getStatsDuration()).isEqualTo(statsDuration);
+ }
+
+ private void assertUidBatteryConsumer(UidBatteryConsumer uidBatteryConsumer,
+ int consumedPower, String packageWithHighestDrain, int timeInStateForeground,
+ int timeInStateBackground, int screenPower, int screenPowerModel, int cpuPower,
+ int cpuPowerModel, int customComponentPower, int cpuDuration,
+ int customComponentDuration) {
+ assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(consumedPower);
+ assertThat(uidBatteryConsumer.getPackageWithHighestDrain()).isEqualTo(
+ packageWithHighestDrain);
+ assertThat(uidBatteryConsumer.getTimeInStateMs(
+ UidBatteryConsumer.STATE_FOREGROUND)).isEqualTo(timeInStateForeground);
+ assertThat(uidBatteryConsumer.getTimeInStateMs(
+ UidBatteryConsumer.STATE_BACKGROUND)).isEqualTo(timeInStateBackground);
+ assertThat(uidBatteryConsumer.getConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_SCREEN)).isEqualTo(screenPower);
+ assertThat(uidBatteryConsumer.getPowerModel(
+ BatteryConsumer.POWER_COMPONENT_SCREEN)).isEqualTo(screenPowerModel);
+ assertThat(uidBatteryConsumer.getConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuPower);
+ assertThat(uidBatteryConsumer.getPowerModel(
+ BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuPowerModel);
+ assertThat(uidBatteryConsumer.getConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(customComponentPower);
+ assertThat(uidBatteryConsumer.getUsageDurationMillis(
+ BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuDuration);
+ assertThat(uidBatteryConsumer.getUsageDurationForCustomComponentMillis(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(
+ customComponentDuration);
+ assertThat(uidBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1);
+ assertThat(uidBatteryConsumer.getCustomPowerComponentName(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO");
+ }
+
+ private void assertUserBatteryConsumer(UserBatteryConsumer userBatteryConsumer,
+ int userId, int cpuPower, int customComponentPower,
+ int cpuDuration, int customComponentDuration) {
+ assertThat(userBatteryConsumer.getConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuPower);
+ assertThat(userBatteryConsumer.getConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(customComponentPower);
+ assertThat(userBatteryConsumer.getUsageDurationMillis(
+ BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuDuration);
+ assertThat(userBatteryConsumer.getUsageDurationForCustomComponentMillis(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(
+ customComponentDuration);
+ assertThat(userBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1);
+ assertThat(userBatteryConsumer.getCustomPowerComponentName(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO");
+ }
+
+ private void assertAggregateBatteryConsumer(BatteryUsageStats batteryUsageStats,
+ int aggregateBatteryConsumerScopeAllApps, int cpuPower, int customComponentPower,
+ int cpuDuration, int customComponentDuration) {
+ final BatteryConsumer appsBatteryConsumer = batteryUsageStats.getAggregateBatteryConsumer(
+ aggregateBatteryConsumerScopeAllApps);
+ assertThat(appsBatteryConsumer.getConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuPower);
+ assertThat(appsBatteryConsumer.getConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(customComponentPower);
+ assertThat(appsBatteryConsumer.getUsageDurationMillis(
+ BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuDuration);
+ assertThat(appsBatteryConsumer.getUsageDurationForCustomComponentMillis(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(
+ customComponentDuration);
+ assertThat(appsBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1);
+ assertThat(appsBatteryConsumer.getCustomPowerComponentName(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO");
}
}
diff --git a/data/etc/car/com.android.car.rotary.xml b/data/etc/car/com.android.car.rotary.xml
index eddef1a..a39b244 100644
--- a/data/etc/car/com.android.car.rotary.xml
+++ b/data/etc/car/com.android.car.rotary.xml
@@ -18,6 +18,7 @@
<privapp-permissions package="com.android.car.rotary">
<permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ <permission name="android.car.permission.CAR_MONITOR_INPUT"/>
</privapp-permissions>
</permissions>
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index 954d062..e141d51 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -753,11 +753,25 @@
nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
}
+ private ASurfaceTransactionCallback mASurfaceTransactionCallback;
+
/** @hide */
public void setASurfaceTransactionCallback(ASurfaceTransactionCallback callback) {
+ // ensure callback is kept alive on the java side since weak ref is used in native code
+ mASurfaceTransactionCallback = callback;
nSetASurfaceTransactionCallback(mNativeProxy, callback);
}
+ private PrepareSurfaceControlForWebviewCallback mAPrepareSurfaceControlForWebviewCallback;
+
+ /** @hide */
+ public void setPrepareSurfaceControlForWebviewCallback(
+ PrepareSurfaceControlForWebviewCallback callback) {
+ // ensure callback is kept alive on the java side since weak ref is used in native code
+ mAPrepareSurfaceControlForWebviewCallback = callback;
+ nSetPrepareSurfaceControlForWebviewCallback(mNativeProxy, callback);
+ }
+
/** @hide */
public void setFrameCallback(FrameDrawingCallback callback) {
nSetFrameCallback(mNativeProxy, callback);
@@ -872,6 +886,19 @@
session.close();
}
+ /**
+ * Interface used to receive callbacks when Webview requests a surface control.
+ *
+ * @hide
+ */
+ public interface PrepareSurfaceControlForWebviewCallback {
+ /**
+ * Invoked when Webview calls to get a surface control.
+ *
+ */
+ void prepare();
+ }
+
/**
* Interface used to receive callbacks when a transaction needs to be merged.
*
@@ -1370,6 +1397,9 @@
private static native void nSetASurfaceTransactionCallback(long nativeProxy,
ASurfaceTransactionCallback callback);
+ private static native void nSetPrepareSurfaceControlForWebviewCallback(long nativeProxy,
+ PrepareSurfaceControlForWebviewCallback callback);
+
private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
private static native void nSetFrameCompleteCallback(long nativeProxy,
diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
index 55fb83c..74fb618 100644
--- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java
+++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
@@ -60,6 +60,10 @@
mForceSoftware = forceSoftware;
}
+ boolean isForceSoftware() {
+ return mForceSoftware;
+ }
+
@NonNull RippleAnimationSession enter(Canvas canvas) {
mStartTime = AnimationUtils.currentAnimationTimeMillis();
if (isHwAccelerated(canvas)) {
@@ -130,7 +134,6 @@
return this;
}
-
private void exitHardware(RecordingCanvas canvas) {
AnimationProperties<CanvasProperty<Float>, CanvasProperty<Paint>>
props = getCanvasProperties();
@@ -199,6 +202,15 @@
startAnimation(expand, loop);
}
+ void setRadius(float radius) {
+ mProperties.setRadius(radius);
+ mProperties.getShader().setRadius(radius);
+ if (mCanvasProperties != null) {
+ mCanvasProperties.setRadius(CanvasProperty.createFloat(radius));
+ mCanvasProperties.getShader().setRadius(radius);
+ }
+ }
+
@NonNull AnimationProperties<Float, Paint> getProperties() {
return mProperties;
}
@@ -249,7 +261,7 @@
static class AnimationProperties<FloatType, PaintType> {
private final FloatType mProgress;
- private final FloatType mMaxRadius;
+ private FloatType mMaxRadius;
private final FloatType mNoisePhase;
private final PaintType mPaint;
private final RippleShader mShader;
@@ -273,6 +285,10 @@
return mProgress;
}
+ void setRadius(FloatType radius) {
+ mMaxRadius = radius;
+ }
+
void setOrigin(FloatType x, FloatType y) {
mX = x;
mY = y;
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index fe80b58..8aba87b 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -221,6 +221,7 @@
private boolean mForceSoftware;
// Patterned
+ private boolean mAddRipple = false;
private float mTargetBackgroundOpacity;
private ValueAnimator mBackgroundAnimation;
private float mBackgroundOpacity;
@@ -716,6 +717,7 @@
}
cancelExitingRipples();
+ exitPatternedAnimation();
}
@Override
@@ -732,7 +734,7 @@
}
/**
- * Notifies all the animating ripples that the hotspot bounds have changed.
+ * Notifies all the animating ripples that the hotspot bounds have changed and modify sessions.
*/
private void onHotspotBoundsChanged() {
final int count = mExitingRipplesCount;
@@ -748,6 +750,20 @@
if (mBackground != null) {
mBackground.onHotspotBoundsChanged();
}
+ float newRadius = Math.round(computeRadius());
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ RippleAnimationSession s = mRunningAnimations.get(i);
+ s.setRadius(newRadius);
+ s.getProperties().getShader()
+ .setResolution(mHotspotBounds.width(), mHotspotBounds.height());
+ float cx = mHotspotBounds.centerX(), cy = mHotspotBounds.centerY();
+ s.getProperties().getShader().setOrigin(cx, cy);
+ s.getProperties().setOrigin(cx, cy);
+ if (!s.isForceSoftware()) {
+ s.getCanvasProperties()
+ .setOrigin(CanvasProperty.createFloat(cx), CanvasProperty.createFloat(cy));
+ }
+ }
}
/**
@@ -807,7 +823,7 @@
}
private void startPatternedAnimation() {
- mRippleActive = true;
+ mAddRipple = true;
invalidateSelf(false);
}
@@ -838,41 +854,36 @@
}
private void drawPatterned(@NonNull Canvas canvas) {
- final Rect bounds = getDirtyBounds();
+ final Rect bounds = mHotspotBounds;
final int saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
boolean useCanvasProps = shouldUseCanvasProps(canvas);
- boolean changedHotspotBounds = !bounds.equals(mHotspotBounds);
if (isBounded()) {
- canvas.clipRect(bounds);
+ canvas.clipRect(getDirtyBounds());
}
final float x, y, cx, cy, w, h;
- if (changedHotspotBounds) {
- x = mHotspotBounds.exactCenterX();
- y = mHotspotBounds.exactCenterY();
- cx = x;
- cy = y;
- h = mHotspotBounds.height();
- w = mHotspotBounds.width();
- useCanvasProps = false;
- } else {
- x = mPendingX;
- y = mPendingY;
- cx = bounds.centerX();
- cy = bounds.centerY();
- h = bounds.height();
- w = bounds.width();
- }
- boolean shouldAnimate = mRippleActive;
+ boolean addRipple = mAddRipple;
+ cx = bounds.centerX();
+ cy = bounds.centerY();
boolean shouldExit = mExitingAnimation;
- mRippleActive = false;
mExitingAnimation = false;
- if (mRunningAnimations.size() > 0 && !shouldAnimate) {
+ mAddRipple = false;
+ if (mRunningAnimations.size() > 0 && !addRipple) {
// update paint when view is invalidated
getRipplePaint();
}
drawContent(canvas);
drawPatternedBackground(canvas, cx, cy);
- if (shouldAnimate && mRunningAnimations.size() <= MAX_RIPPLES) {
+ if (addRipple && mRunningAnimations.size() <= MAX_RIPPLES) {
+ if (mHasPending) {
+ x = mPendingX;
+ y = mPendingY;
+ mHasPending = false;
+ } else {
+ x = bounds.exactCenterX();
+ y = bounds.exactCenterY();
+ }
+ h = bounds.height();
+ w = bounds.width();
RippleAnimationSession.AnimationProperties<Float, Paint> properties =
createAnimationProperties(x, y, cx, cy, w, h);
mRunningAnimations.add(new RippleAnimationSession(properties, !useCanvasProps)
@@ -896,33 +907,13 @@
CanvasProperty<Paint>>
p = s.getCanvasProperties();
RecordingCanvas can = (RecordingCanvas) canvas;
- CanvasProperty<Float> xProp, yProp;
- if (changedHotspotBounds) {
- xProp = CanvasProperty.createFloat(x);
- yProp = CanvasProperty.createFloat(y);
- p.getShader().setTouch(x, y);
- p.getShader().setOrigin(x, y);
- } else {
- xProp = p.getX();
- yProp = p.getY();
- }
- can.drawRipple(xProp, yProp, p.getMaxRadius(), p.getPaint(),
+ can.drawRipple(p.getX(), p.getY(), p.getMaxRadius(), p.getPaint(),
p.getProgress(), p.getNoisePhase(), p.getColor(), p.getShader());
} else {
RippleAnimationSession.AnimationProperties<Float, Paint> p =
s.getProperties();
- float xProp, yProp;
- if (changedHotspotBounds) {
- xProp = x;
- yProp = y;
- p.getShader().setTouch(x, y);
- p.getShader().setOrigin(x, y);
- } else {
- xProp = p.getX();
- yProp = p.getY();
- }
float radius = p.getMaxRadius();
- canvas.drawCircle(xProp, yProp, radius, p.getPaint());
+ canvas.drawCircle(p.getX(), p.getY(), radius, p.getPaint());
}
}
canvas.restoreToCount(saveCount);
@@ -1109,6 +1100,11 @@
if (mState.mRippleStyle == STYLE_SOLID) {
mMaskCanvas.translate(left, top);
}
+ if (mState.mRippleStyle == STYLE_PATTERNED) {
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ mRunningAnimations.get(i).getProperties().getShader().setShader(mMaskShader);
+ }
+ }
}
private int getMaskType() {
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 4c2863e..8cea869 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -40,7 +40,7 @@
<integer name="long_press_dock_anim_duration">250</integer>
<!-- Animation duration for translating of one handed when trigger / dismiss. -->
- <integer name="config_one_handed_translate_animation_duration">800</integer>
+ <integer name="config_one_handed_translate_animation_duration">600</integer>
<!-- One handed mode default offset % of display size -->
<fraction name="config_one_handed_offset">40%</fraction>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index afb40d1..9d65d28 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -284,6 +284,15 @@
return mTitle;
}
+ /**
+ * @return the ShortcutInfo id if it exists, or the metadata shortcut id otherwise.
+ */
+ String getShortcutId() {
+ return getShortcutInfo() != null
+ ? getShortcutInfo().getId()
+ : getMetadataShortcutId();
+ }
+
String getMetadataShortcutId() {
return mMetadataShortcutId;
}
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 dfd878f..09fcb86 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
@@ -93,6 +93,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -265,15 +266,7 @@
public void initialize() {
mBubbleData.setListener(mBubbleDataListener);
- mBubbleData.setSuppressionChangedListener(bubble -> {
- // Make sure NoMan knows suppression state so that anyone querying it can tell.
- try {
- mBarService.onBubbleNotificationSuppressionChanged(bubble.getKey(),
- !bubble.showInShade(), bubble.isSuppressed());
- } catch (RemoteException e) {
- // Bad things have happened
- }
- });
+ mBubbleData.setSuppressionChangedListener(this::onBubbleNotificationSuppressionChanged);
mBubbleData.setPendingIntentCancelledListener(bubble -> {
if (bubble.getBubbleIntent() == null) {
@@ -401,6 +394,11 @@
return mImpl;
}
+ @VisibleForTesting
+ public BubblesImpl.CachedState getImplCachedState() {
+ return mImpl.mCachedState;
+ }
+
public ShellExecutor getMainExecutor() {
return mMainExecutor;
}
@@ -500,6 +498,18 @@
updateStack();
}
+ @VisibleForTesting
+ public void onBubbleNotificationSuppressionChanged(Bubble bubble) {
+ // Make sure NoMan knows suppression state so that anyone querying it can tell.
+ try {
+ mBarService.onBubbleNotificationSuppressionChanged(bubble.getKey(),
+ !bubble.showInShade(), bubble.isSuppressed());
+ } catch (RemoteException e) {
+ // Bad things have happened
+ }
+ mImpl.mCachedState.updateBubbleSuppressedState(bubble);
+ }
+
/** Called when the current user changes. */
@VisibleForTesting
public void onUserChanged(int newUserId) {
@@ -694,7 +704,7 @@
mSysuiProxy.getShouldRestoredEntries(savedBubbleKeys, (entries) -> {
mMainExecutor.execute(() -> {
for (BubbleEntry e : entries) {
- if (canLaunchInActivityView(mContext, e)) {
+ if (canLaunchInTaskView(mContext, e)) {
updateBubble(e, true /* suppressFlyout */, false /* showInShade */);
}
}
@@ -808,11 +818,6 @@
}
}
- private boolean isBubbleExpanded(String key) {
- return isStackExpanded() && mBubbleData != null && mBubbleData.getSelectedBubble() != null
- && mBubbleData.getSelectedBubble().getKey().equals(key);
- }
-
/** Promote the provided bubble from the overflow view. */
public void promoteBubbleFromOverflow(Bubble bubble) {
mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_BACK_TO_STACK);
@@ -957,14 +962,14 @@
}
private void onEntryAdded(BubbleEntry entry) {
- if (canLaunchInActivityView(mContext, entry)) {
+ if (canLaunchInTaskView(mContext, entry)) {
updateBubble(entry);
}
}
private void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp) {
// shouldBubbleUp checks canBubble & for bubble metadata
- boolean shouldBubble = shouldBubbleUp && canLaunchInActivityView(mContext, entry);
+ boolean shouldBubble = shouldBubbleUp && canLaunchInTaskView(mContext, entry);
if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) {
// It was previously a bubble but no longer a bubble -- lets remove it
removeBubble(entry.getKey(), DISMISS_NO_LONGER_BUBBLE);
@@ -1191,6 +1196,9 @@
mSysuiProxy.notifyInvalidateNotifications("BubbleData.Listener.applyUpdate");
updateStack();
+
+ // Update the cached state for queries from SysUI
+ mImpl.mCachedState.update(update);
}
};
@@ -1295,15 +1303,16 @@
}
/**
- * Whether an intent is properly configured to display in an {@link android.app.ActivityView}.
+ * Whether an intent is properly configured to display in a
+ * {@link com.android.wm.shell.TaskView}.
*
- * Keep checks in sync with NotificationManagerService#canLaunchInActivityView. Typically
+ * Keep checks in sync with BubbleExtractor#canLaunchInTaskView. Typically
* that should filter out any invalid bubbles, but should protect SysUI side just in case.
*
* @param context the context to use.
* @param entry the entry to bubble.
*/
- static boolean canLaunchInActivityView(Context context, BubbleEntry entry) {
+ static boolean canLaunchInTaskView(Context context, BubbleEntry entry) {
PendingIntent intent = entry.getBubbleMetadata() != null
? entry.getBubbleMetadata().getIntent()
: null;
@@ -1364,25 +1373,124 @@
}
private class BubblesImpl implements Bubbles {
+ // Up-to-date cached state of bubbles data for SysUI to query from the calling thread
+ @VisibleForTesting
+ public class CachedState {
+ private boolean mIsStackExpanded;
+ private String mSelectedBubbleKey;
+ private HashSet<String> mSuppressedBubbleKeys = new HashSet<>();
+ private HashMap<String, String> mSuppressedGroupToNotifKeys = new HashMap<>();
+ private HashMap<String, Bubble> mShortcutIdToBubble = new HashMap<>();
+
+ private ArrayList<Bubble> mTmpBubbles = new ArrayList<>();
+
+ /**
+ * Updates the cached state based on the last full BubbleData change.
+ */
+ synchronized void update(BubbleData.Update update) {
+ if (update.selectionChanged) {
+ mSelectedBubbleKey = update.selectedBubble != null
+ ? update.selectedBubble.getKey()
+ : null;
+ }
+ if (update.expandedChanged) {
+ mIsStackExpanded = update.expanded;
+ }
+ if (update.suppressedSummaryChanged) {
+ String summaryKey =
+ mBubbleData.getSummaryKey(update.suppressedSummaryGroup);
+ if (summaryKey != null) {
+ mSuppressedGroupToNotifKeys.put(update.suppressedSummaryGroup, summaryKey);
+ } else {
+ mSuppressedGroupToNotifKeys.remove(update.suppressedSummaryGroup);
+ }
+ }
+
+ mTmpBubbles.clear();
+ mTmpBubbles.addAll(update.bubbles);
+ mTmpBubbles.addAll(update.overflowBubbles);
+
+ mSuppressedBubbleKeys.clear();
+ mShortcutIdToBubble.clear();
+ for (Bubble b : mTmpBubbles) {
+ mShortcutIdToBubble.put(b.getShortcutId(), b);
+ updateBubbleSuppressedState(b);
+ }
+ }
+
+ /**
+ * Updates a specific bubble suppressed state. This is used mainly because notification
+ * suppression changes don't go through the same BubbleData update mechanism.
+ */
+ synchronized void updateBubbleSuppressedState(Bubble b) {
+ if (!b.showInShade()) {
+ mSuppressedBubbleKeys.add(b.getKey());
+ } else {
+ mSuppressedBubbleKeys.remove(b.getKey());
+ }
+ }
+
+ public synchronized boolean isStackExpanded() {
+ return mIsStackExpanded;
+ }
+
+ public synchronized boolean isBubbleExpanded(String key) {
+ return mIsStackExpanded && key.equals(mSelectedBubbleKey);
+ }
+
+ public synchronized boolean isBubbleNotificationSuppressedFromShade(String key,
+ String groupKey) {
+ return mSuppressedBubbleKeys.contains(key)
+ || (mSuppressedGroupToNotifKeys.containsKey(groupKey)
+ && key.equals(mSuppressedGroupToNotifKeys.get(groupKey)));
+ }
+
+ @Nullable
+ public synchronized Bubble getBubbleWithShortcutId(String id) {
+ return mShortcutIdToBubble.get(id);
+ }
+
+ synchronized void dump(PrintWriter pw) {
+ pw.println("BubbleImpl.CachedState state:");
+
+ pw.println("mIsStackExpanded: " + mIsStackExpanded);
+ pw.println("mSelectedBubbleKey: " + mSelectedBubbleKey);
+
+ pw.print("mSuppressedBubbleKeys: ");
+ pw.println(mSuppressedBubbleKeys.size());
+ for (String key : mSuppressedBubbleKeys) {
+ pw.println(" suppressing: " + key);
+ }
+
+ pw.print("mSuppressedGroupToNotifKeys: ");
+ pw.println(mSuppressedGroupToNotifKeys.size());
+ for (String key : mSuppressedGroupToNotifKeys.keySet()) {
+ pw.println(" suppressing: " + key);
+ }
+ }
+ }
+
+ private CachedState mCachedState = new CachedState();
+
@Override
public boolean isBubbleNotificationSuppressedFromShade(String key, String groupKey) {
- return mMainExecutor.executeBlockingForResult(() -> {
- return BubbleController.this.isBubbleNotificationSuppressedFromShade(key, groupKey);
- }, Boolean.class);
+ return mCachedState.isBubbleNotificationSuppressedFromShade(key, groupKey);
}
@Override
public boolean isBubbleExpanded(String key) {
- return mMainExecutor.executeBlockingForResult(() -> {
- return BubbleController.this.isBubbleExpanded(key);
- }, Boolean.class);
+ return mCachedState.isBubbleExpanded(key);
}
@Override
public boolean isStackExpanded() {
- return mMainExecutor.executeBlockingForResult(() -> {
- return BubbleController.this.isStackExpanded();
- }, Boolean.class);
+ return mCachedState.isStackExpanded();
+ }
+
+ @Override
+ @Nullable
+ public Bubble getBubbleWithShortcutId(String shortcutId) {
+ return mCachedState.getBubbleWithShortcutId(shortcutId);
}
@Override
@@ -1425,14 +1533,6 @@
}
@Override
- @Nullable
- public Bubble getBubbleWithShortcutId(String shortcutId) {
- return mMainExecutor.executeBlockingForResult(() -> {
- return BubbleController.this.mBubbleData.getAnyBubbleWithShortcutId(shortcutId);
- }, Bubble.class);
- }
-
- @Override
public void onTaskbarChanged(Bundle b) {
mMainExecutor.execute(() -> {
BubbleController.this.onTaskbarChanged(b);
@@ -1555,6 +1655,7 @@
try {
mMainExecutor.executeBlocking(() -> {
BubbleController.this.dump(fd, pw, args);
+ mCachedState.dump(pw);
});
} catch (InterruptedException e) {
Slog.e(TAG, "Failed to dump BubbleController in 2s");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index 6f5cfd1..d73ce69 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -73,6 +73,7 @@
boolean expandedChanged;
boolean selectionChanged;
boolean orderChanged;
+ boolean suppressedSummaryChanged;
boolean expanded;
@Nullable BubbleViewProvider selectedBubble;
@Nullable Bubble addedBubble;
@@ -81,6 +82,7 @@
@Nullable Bubble removedOverflowBubble;
@Nullable Bubble suppressedBubble;
@Nullable Bubble unsuppressedBubble;
+ @Nullable String suppressedSummaryGroup;
// Pair with Bubble and @DismissReason Integer
final List<Pair<Bubble, Integer>> removedBubbles = new ArrayList<>();
@@ -103,7 +105,9 @@
|| removedOverflowBubble != null
|| orderChanged
|| suppressedBubble != null
- || unsuppressedBubble != null;
+ || unsuppressedBubble != null
+ || suppressedSummaryChanged
+ || suppressedSummaryGroup != null;
}
void bubbleRemoved(Bubble bubbleToRemove, @DismissReason int reason) {
@@ -380,6 +384,9 @@
*/
void addSummaryToSuppress(String groupKey, String notifKey) {
mSuppressedGroupKeys.put(groupKey, notifKey);
+ mStateChange.suppressedSummaryChanged = true;
+ mStateChange.suppressedSummaryGroup = groupKey;
+ dispatchPendingChanges();
}
/**
@@ -397,6 +404,9 @@
*/
void removeSuppressedSummary(String groupKey) {
mSuppressedGroupKeys.remove(groupKey);
+ mStateChange.suppressedSummaryChanged = true;
+ mStateChange.suppressedSummaryGroup = groupKey;
+ dispatchPendingChanges();
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index f81f086..9687ec6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -90,15 +90,15 @@
private boolean mNeedsNewHeight;
/**
- * Whether we want the TaskView's content to be visible (alpha = 1f). If
- * {@link #mIsAlphaAnimating} is true, this may not reflect the TaskView's actual alpha value
- * until the animation ends.
+ * Whether we want the {@code TaskView}'s content to be visible (alpha = 1f). If
+ * {@link #mIsAlphaAnimating} is true, this may not reflect the {@code TaskView}'s actual alpha
+ * value until the animation ends.
*/
private boolean mIsContentVisible = false;
/**
- * Whether we're animating the TaskView's alpha value. If so, we will hold off on applying alpha
- * changes from {@link #setContentVisibility} until the animation ends.
+ * Whether we're animating the {@code TaskView}'s alpha value. If so, we will hold off on
+ * applying alpha changes from {@link #setContentVisibility} until the animation ends.
*/
private boolean mIsAlphaAnimating = false;
@@ -127,8 +127,8 @@
private BubblePositioner mPositioner;
/**
- * Container for the ActivityView that has a solid, round-rect background that shows if the
- * ActivityView hasn't loaded.
+ * Container for the {@code TaskView} that has a solid, round-rect background that shows if the
+ * {@code TaskView} hasn't loaded.
*/
private final FrameLayout mExpandedViewContainer = new FrameLayout(getContext());
@@ -139,7 +139,7 @@
@Override
public void onInitialized() {
if (DEBUG_BUBBLE_EXPANDED_VIEW) {
- Log.d(TAG, "onActivityViewReady: destroyed=" + mDestroyed
+ Log.d(TAG, "onInitialized: destroyed=" + mDestroyed
+ " initialized=" + mInitialized
+ " bubble=" + getBubbleKey());
}
@@ -159,7 +159,7 @@
// Post to keep the lifecycle normal
post(() -> {
if (DEBUG_BUBBLE_EXPANDED_VIEW) {
- Log.d(TAG, "onActivityViewReady: calling startActivity, bubble="
+ Log.d(TAG, "onInitialized: calling startActivity, bubble="
+ getBubbleKey());
}
try {
@@ -265,7 +265,7 @@
mCurrentPointer = mTopPointer;
mPointerView.setVisibility(INVISIBLE);
- // Set TaskView's alpha value as zero, since there is no view content to be shown.
+ // Set {@code TaskView}'s alpha value as zero, since there is no view content to be shown.
setContentVisibility(false);
mExpandedViewContainer.setOutlineProvider(new ViewOutlineProvider() {
@@ -290,6 +290,27 @@
applyThemeAttrs();
setClipToPadding(false);
+ setOnTouchListener((view, motionEvent) -> {
+ if (mTaskView == null) {
+ return false;
+ }
+
+ final Rect avBounds = new Rect();
+ mTaskView.getBoundsOnScreen(avBounds);
+
+ // Consume and ignore events on the expanded view padding that are within the
+ // {@code TaskView}'s vertical bounds. These events are part of a back gesture, and so
+ // they should not collapse the stack (which all other touches on areas around the AV
+ // would do).
+ if (motionEvent.getRawY() >= avBounds.top
+ && motionEvent.getRawY() <= avBounds.bottom
+ && (motionEvent.getRawX() < avBounds.left
+ || motionEvent.getRawX() > avBounds.right)) {
+ return true;
+ }
+
+ return false;
+ });
// BubbleStackView is forced LTR, but we want to respect the locale for expanded view layout
// so the Manage button appears on the right.
@@ -470,7 +491,7 @@
/**
* Updates the obscured touchable region for the task surface. This calls onLocationChanged,
* which results in a call to {@link BubbleStackView#subtractObscuredTouchableRegion}. This is
- * useful if a view has been added or removed from on top of the ActivityView, such as the
+ * useful if a view has been added or removed from on top of the {@code TaskView}, such as the
* manage menu.
*/
void updateObscuredTouchableRegion() {
@@ -490,8 +511,9 @@
}
/**
- * Whether we are currently animating the TaskView's alpha value. If this is set to true, calls
- * to {@link #setContentVisibility} will not be applied until this is set to false again.
+ * Whether we are currently animating the {@code TaskView}'s alpha value. If this is set to
+ * true, calls to {@link #setContentVisibility} will not be applied until this is set to false
+ * again.
*/
void setAlphaAnimating(boolean animating) {
mIsAlphaAnimating = animating;
@@ -503,8 +525,8 @@
}
/**
- * Sets the alpha of the underlying TaskView, since changing the expanded view's alpha does not
- * affect the TaskView since it uses a Surface.
+ * Sets the alpha of the underlying {@code TaskView}, since changing the expanded view's alpha
+ * does not affect the {@code TaskView} since it uses a Surface.
*/
void setTaskViewAlpha(float alpha) {
if (mTaskView != null) {
@@ -743,9 +765,9 @@
}
/**
- * Cleans up anything related to the task and TaskView. If this view should be reused after this
- * method is called, then {@link #initialize(BubbleController, BubbleStackView, boolean)} must
- * be invoked first.
+ * Cleans up anything related to the task and {@code TaskView}. If this view should be reused
+ * after this method is called, then
+ * {@link #initialize(BubbleController, BubbleStackView, boolean)} must be invoked first.
*/
public void cleanUpExpandedState() {
if (DEBUG_BUBBLE_EXPANDED_VIEW) {
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 c71f123..92e455c 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
@@ -1611,7 +1611,7 @@
if (mIsExpanded && mExpandedBubble != null && mExpandedBubble.getExpandedView() != null
&& !mExpandedViewTemporarilyHidden) {
if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
- // Before screenshotting, have the real ActivityView show on top of other surfaces
+ // Before screenshotting, have the real TaskView show on top of other surfaces
// so that the screenshot doesn't flicker on top of it.
mExpandedBubble.getExpandedView().setSurfaceZOrderedOnTop(true);
}
@@ -2583,8 +2583,8 @@
}
/**
- * Requests a snapshot from the currently expanded bubble's ActivityView and displays it in a
- * SurfaceView. This allows us to load a newly expanded bubble's Activity into the ActivityView,
+ * Requests a snapshot from the currently expanded bubble's TaskView and displays it in a
+ * SurfaceView. This allows us to load a newly expanded bubble's Activity into the TaskView,
* while animating the (screenshot of the) previously selected bubble's content away.
*
* @param onComplete Callback to run once we're done here - called with 'false' if something
@@ -2628,13 +2628,13 @@
mAnimatingOutSurfaceContainer.setTranslationX(mExpandedViewContainer.getPaddingLeft());
mAnimatingOutSurfaceContainer.setTranslationY(0);
- final int[] activityViewLocation =
+ final int[] taskViewLocation =
mExpandedBubble.getExpandedView().getTaskViewLocationOnScreen();
final int[] surfaceViewLocation = mAnimatingOutSurfaceView.getLocationOnScreen();
- // Translate the surface to overlap the real ActivityView.
+ // Translate the surface to overlap the real TaskView.
mAnimatingOutSurfaceContainer.setTranslationY(
- activityViewLocation[1] - surfaceViewLocation[1]);
+ taskViewLocation[1] - surfaceViewLocation[1]);
// Set the width/height of the SurfaceView to match the snapshot.
mAnimatingOutSurfaceView.getLayoutParams().width =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
index 8dc05de9..a525c2c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
@@ -68,6 +68,11 @@
void setLockedDisabled(boolean locked, boolean enabled);
/**
+ * Registers callback to notify WMShell when user tap shortcut to expand notification.
+ */
+ void registerEventCallback(OneHandedEventCallback callback);
+
+ /**
* Registers callback to be notified after {@link OneHandedDisplayAreaOrganizer}
* transition start or finish
*/
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 c275d50..b43daa0 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
@@ -43,6 +43,7 @@
import android.view.Surface;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
+import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -72,6 +73,7 @@
private static final String ONE_HANDED_MODE_GESTURAL_OVERLAY =
"com.android.internal.systemui.onehanded.gestural";
private static final int OVERLAY_ENABLED_DELAY_MS = 250;
+ private static final int DISPLAY_AREA_READY_RETRY_MS = 10;
static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
@@ -99,6 +101,7 @@
private final Handler mMainHandler;
private final OneHandedImpl mImpl = new OneHandedImpl();
+ private OneHandedEventCallback mEventCallback;
private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer;
@@ -288,7 +291,7 @@
mTimeoutObserver = getObserver(this::onTimeoutSettingChanged);
mTaskChangeExitObserver = getObserver(this::onTaskChangeExitSettingChanged);
mSwipeToNotificationEnabledObserver =
- getObserver(this::onSwipeToNotificationEnabledSettingChanged);
+ getObserver(this::onSwipeToNotificationEnabledChanged);
mDisplayController.addDisplayChangingController(mRotationController);
setupCallback();
@@ -358,14 +361,23 @@
Slog.d(TAG, "Temporary lock disabled");
return;
}
+
+ if (!mDisplayAreaOrganizer.isReady()) {
+ // Must wait until DisplayAreaOrganizer is ready for transitioning.
+ mMainExecutor.executeDelayed(this::startOneHanded, DISPLAY_AREA_READY_RETRY_MS);
+ return;
+ }
+
if (mState.isTransitioning() || mState.isInOneHanded()) {
return;
}
+
final int currentRotation = mDisplayAreaOrganizer.getDisplayLayout().rotation();
if (currentRotation != Surface.ROTATION_0 && currentRotation != Surface.ROTATION_180) {
Slog.w(TAG, "One handed mode only support portrait mode");
return;
}
+
mState.setState(STATE_ENTERING);
final int yOffSet = Math.round(
mDisplayAreaOrganizer.getDisplayLayout().height() * mOffSetFraction);
@@ -394,6 +406,10 @@
mOneHandedUiEventLogger.writeEvent(uiEvent);
}
+ void registerEventCallback(OneHandedEventCallback callback) {
+ mEventCallback = callback;
+ }
+
@VisibleForTesting
void registerTransitionCallback(OneHandedTransitionCallback callback) {
mDisplayAreaOrganizer.registerTransitionCallback(callback);
@@ -464,8 +480,29 @@
}
@VisibleForTesting
+ void notifyExpandNotification() {
+ mMainExecutor.execute(() -> mEventCallback.notifyExpandNotification());
+ }
+
+ @VisibleForTesting
+ void notifyUserConfigChanged(boolean success) {
+ if (!success) {
+ return;
+ }
+ // TODO Check UX if popup Toast to notify user when auto-enabled one-handed is good option.
+ Toast.makeText(mContext, R.string.one_handed_tutorial_title, Toast.LENGTH_LONG).show();
+ }
+
+ @VisibleForTesting
void onActivatedActionChanged() {
- if (mState.isTransitioning() || !isOneHandedEnabled()) {
+ if (!isOneHandedEnabled()) {
+ final boolean success = mOneHandedSettingsUtil.setOneHandedModeEnabled(
+ mContext.getContentResolver(), 1 /* Enabled for shortcut */, mUserId);
+ notifyUserConfigChanged(success);
+ }
+
+ if (isSwipeToNotificationEnabled()) {
+ notifyExpandNotification();
return;
}
@@ -494,11 +531,9 @@
setOneHandedEnabled(enabled);
// Also checks swipe to notification settings since they all need gesture overlay.
- // Enabled overlay package may affect the current animation(e.g:Settings switch),
- // so we delay 250ms to enabled overlay after switch animation finish
- mMainExecutor.executeDelayed(() -> setEnabledGesturalOverlay(
+ setEnabledGesturalOverlay(
enabled || mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
- mContext.getContentResolver(), mUserId)), OVERLAY_ENABLED_DELAY_MS);
+ mContext.getContentResolver(), mUserId), true /* DelayExecute */);
}
@VisibleForTesting
@@ -542,7 +577,7 @@
}
@VisibleForTesting
- void onSwipeToNotificationEnabledSettingChanged() {
+ void onSwipeToNotificationEnabledChanged() {
final boolean enabled =
mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
mContext.getContentResolver(), mUserId);
@@ -551,7 +586,7 @@
// Also checks one handed mode settings since they all need gesture overlay.
setEnabledGesturalOverlay(
enabled || mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
- mContext.getContentResolver(), mUserId));
+ mContext.getContentResolver(), mUserId), true /* DelayExecute */);
}
private void setupTimeoutListener() {
@@ -569,11 +604,19 @@
return mIsOneHandedEnabled;
}
+ @VisibleForTesting
+ boolean isSwipeToNotificationEnabled() {
+ return mIsSwipeToNotificationEnabled;
+ }
+
private void updateOneHandedEnabled() {
if (mState.getState() == STATE_ENTERING || mState.getState() == STATE_ACTIVE) {
mMainExecutor.execute(() -> stopOneHanded());
}
+ // Reset and align shortcut one_handed_mode_activated status with current mState
+ notifyShortcutState(mState.getState());
+
mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled);
if (!mIsOneHandedEnabled) {
@@ -608,12 +651,19 @@
if (info != null && !info.isEnabled()) {
// Enable the default gestural one handed overlay.
- setEnabledGesturalOverlay(true);
+ setEnabledGesturalOverlay(true /* enabled */, false /* delayExecute */);
}
}
@VisibleForTesting
- private void setEnabledGesturalOverlay(boolean enabled) {
+ private void setEnabledGesturalOverlay(boolean enabled, boolean delayExecute) {
+ if (mState.isTransitioning() || delayExecute) {
+ // Enabled overlay package may affect the current animation(e.g:Settings switch),
+ // so we delay 250ms to enabled overlay after switch animation finish, only delay once.
+ mMainExecutor.executeDelayed(() -> setEnabledGesturalOverlay(enabled, false),
+ OVERLAY_ENABLED_DELAY_MS);
+ return;
+ }
try {
mOverlayManager.setEnabled(ONE_HANDED_MODE_GESTURAL_OVERLAY, enabled, USER_CURRENT);
} catch (RemoteException e) {
@@ -628,6 +678,7 @@
if (enabled == isFeatureEnabled) {
return;
}
+
mLockedDisabled = locked && !enabled;
}
@@ -761,6 +812,13 @@
}
@Override
+ public void registerEventCallback(OneHandedEventCallback callback) {
+ mMainExecutor.execute(() -> {
+ OneHandedController.this.registerEventCallback(callback);
+ });
+ }
+
+ @Override
public void registerTransitionCallback(OneHandedTransitionCallback callback) {
mMainExecutor.execute(() -> {
OneHandedController.this.registerTransitionCallback(callback);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index b8da37f..03a90c6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -61,11 +61,12 @@
private DisplayLayout mDisplayLayout = new DisplayLayout();
- private float mLastVisualOffset = 0;
private final Rect mLastVisualDisplayBounds = new Rect();
private final Rect mDefaultDisplayBounds = new Rect();
private final OneHandedSettingsUtil mOneHandedSettingsUtil;
+ private boolean mIsReady;
+ private float mLastVisualOffset = 0;
private int mEnterExitAnimationDurationMs;
private ArrayMap<WindowContainerToken, SurfaceControl> mDisplayAreaTokenMap = new ArrayMap();
@@ -157,6 +158,7 @@
final DisplayAreaAppearedInfo info = displayAreaInfos.get(i);
onDisplayAreaAppeared(info.getDisplayAreaInfo(), info.getLeash());
}
+ mIsReady = true;
updateDisplayBounds();
return displayAreaInfos;
}
@@ -164,9 +166,14 @@
@Override
public void unregisterOrganizer() {
super.unregisterOrganizer();
+ mIsReady = false;
resetWindowsOffset();
}
+ boolean isReady() {
+ return mIsReady;
+ }
+
/**
* Handler for display rotation changes by {@link DisplayLayout}
*
@@ -184,8 +191,15 @@
myUserId())) {
return;
}
+
mDisplayLayout.rotateTo(context.getResources(), toRotation);
updateDisplayBounds();
+
+ if (mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ context.getContentResolver(), myUserId())) {
+ // If current settings is swipe notification, skip finishOffset.
+ return;
+ }
finishOffset(0, TRANSITION_DIRECTION_EXIT);
}
@@ -312,6 +326,8 @@
pw.println(mDisplayAreaTokenMap);
pw.print(innerPrefix + "mDefaultDisplayBounds=");
pw.println(mDefaultDisplayBounds);
+ pw.print(innerPrefix + "mIsReady=");
+ pw.println(mIsReady);
pw.print(innerPrefix + "mLastVisualDisplayBounds=");
pw.println(mLastVisualDisplayBounds);
pw.print(innerPrefix + "mLastVisualOffset=");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEventCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEventCallback.java
new file mode 100644
index 0000000..d07eea2
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEventCallback.java
@@ -0,0 +1,28 @@
+/*
+ * 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.onehanded;
+
+/**
+ * Additional callback interface for OneHanded events.
+ */
+public interface OneHandedEventCallback {
+ /**
+ * Called to notify expand notification shade.
+ */
+ default void notifyExpandNotification() {
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
index 90fc823..da53b35 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
@@ -105,6 +105,17 @@
}
/**
+ * Sets one handed enable or disable flag from Settings provider.
+ *
+ * @return true if the value was set, false on database errors
+ */
+ public boolean setOneHandedModeEnabled(ContentResolver resolver, int enabled, int userId) {
+ return Settings.Secure.putIntForUser(resolver,
+ Settings.Secure.ONE_HANDED_MODE_ENABLED, enabled, userId);
+ }
+
+
+ /**
* Queries taps app to exit config from Settings provider.
*
* @return enable or disable taps app exit.
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 6451b94..324a6e2 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
@@ -835,11 +835,14 @@
WindowContainerTransaction wct) {
// note that this can be called when swipe-to-home or fixed-rotation is happening.
// Skip this entirely if that's the case.
- if ((mInSwipePipToHomeTransition || mWaitForFixedRotation) && fromRotation) {
+ final boolean waitForFixedRotationOnEnteringPip = mWaitForFixedRotation
+ && (mState != State.ENTERED_PIP);
+ if ((mInSwipePipToHomeTransition || waitForFixedRotationOnEnteringPip) && fromRotation) {
if (DEBUG) {
Log.d(TAG, "Skip onMovementBoundsChanged on rotation change"
+ " mInSwipePipToHomeTransition=" + mInSwipePipToHomeTransition
- + " mWaitForFixedRotation=" + mWaitForFixedRotation);
+ + " mWaitForFixedRotation=" + mWaitForFixedRotation
+ + " mState=" + mState);
}
return;
}
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 f6b5889..bc8e1e7 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
@@ -278,6 +278,10 @@
return;
}
+ // Sync the menu bounds before showing it in case it is out of sync.
+ movePipMenu(null /* pipLeash */, null /* transaction */, stackBounds);
+ updateMenuBounds(stackBounds);
+
mPipMenuView.showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
showResizeHandle);
}
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 841edef..f0bd8a2 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
@@ -235,15 +235,20 @@
@VisibleForTesting
void onInputEvent(InputEvent ev) {
+ if (!mEnableDragCornerResize && !mEnablePinchResize) {
+ // No need to handle anything if neither form of resizing is enabled.
+ return;
+ }
+
// Don't allow resize when PiP is stashed.
if (mPipBoundsState.isStashed()) {
return;
}
if (ev instanceof MotionEvent) {
- if (mOngoingPinchToResize) {
+ if (mEnablePinchResize && mOngoingPinchToResize) {
onPinchResize((MotionEvent) ev);
- } else {
+ } else if (mEnableDragCornerResize) {
onDragCornerResize((MotionEvent) ev);
}
}
@@ -318,8 +323,8 @@
case MotionEvent.ACTION_POINTER_DOWN:
if (mEnablePinchResize && ev.getPointerCount() == 2) {
onPinchResize(ev);
- mOngoingPinchToResize = true;
- return true;
+ mOngoingPinchToResize = mAllowGesture;
+ return mAllowGesture;
}
break;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
index 1852279..47789b7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
@@ -74,6 +74,8 @@
@Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
@Mock
+ OneHandedEventCallback mMockEventCallback;
+ @Mock
OneHandedTouchHandler mMockTouchHandler;
@Mock
OneHandedTutorialHandler mMockTutorialHandler;
@@ -106,6 +108,7 @@
when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>());
+ when(mMockDisplayAreaOrganizer.isReady()).thenReturn(true);
when(mMockBackgroundOrganizer.getBackgroundSurface()).thenReturn(mMockLeash);
when(mMockSettingsUitl.getSettingsOneHandedModeEnabled(any(), anyInt())).thenReturn(
mDefaultEnabled);
@@ -241,7 +244,7 @@
@Test
public void testSettingsObserverUpdateSwipeToNotification() {
- mSpiedOneHandedController.onSwipeToNotificationEnabledSettingChanged();
+ mSpiedOneHandedController.onSwipeToNotificationEnabledChanged();
verify(mSpiedOneHandedController).setSwipeToNotificationEnabled(anyBoolean());
}
@@ -311,6 +314,7 @@
final DisplayLayout testDisplayLayout = new DisplayLayout(mDisplayLayout);
testDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180);
mSpiedTransitionState.setState(STATE_NONE);
+ when(mMockDisplayAreaOrganizer.isReady()).thenReturn(true);
when(mMockDisplayAreaOrganizer.getDisplayLayout()).thenReturn(testDisplayLayout);
mSpiedOneHandedController.setOneHandedEnabled(true);
mSpiedOneHandedController.setLockedDisabled(false /* locked */, false /* enabled */);
@@ -372,8 +376,7 @@
when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
mSpiedOneHandedController.onActivatedActionChanged();
- verify(mSpiedOneHandedController, never()).startOneHanded();
- verify(mSpiedOneHandedController, never()).stopOneHanded();
+ verify(mSpiedTransitionState, never()).setState(STATE_EXITING);
}
@Test
@@ -383,20 +386,20 @@
when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
mSpiedOneHandedController.onActivatedActionChanged();
- verify(mSpiedOneHandedController, never()).startOneHanded();
- verify(mSpiedOneHandedController, never()).stopOneHanded();
+ verify(mSpiedTransitionState, never()).setState(STATE_ENTERING);
}
@Test
- public void testOneHandedDisabled_shortcutEnabled_skipActions() {
+ public void testOneHandedDisabled_shortcutTrigger_thenAutoEnabled() {
when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(false);
when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
- when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
+ when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(false);
+ when(mMockSettingsUitl.setOneHandedModeEnabled(any(), anyInt(), anyInt())).thenReturn(
+ false);
mSpiedOneHandedController.onActivatedActionChanged();
- verify(mSpiedOneHandedController, never()).startOneHanded();
- verify(mSpiedOneHandedController, never()).stopOneHanded();
+ verify(mSpiedOneHandedController).notifyUserConfigChanged(anyBoolean());
}
@Test
@@ -408,4 +411,28 @@
verify(mSpiedTransitionState).addSListeners(mMockTutorialHandler);
}
+
+ @Test
+ public void testNotifyEventCallbackWithMainExecutor() {
+ when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(true);
+ when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
+ when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
+ when(mSpiedOneHandedController.isSwipeToNotificationEnabled()).thenReturn(true);
+ mSpiedOneHandedController.registerEventCallback(mMockEventCallback);
+ mSpiedOneHandedController.onActivatedActionChanged();
+
+ verify(mMockShellMainExecutor).execute(any());
+ }
+
+ @Test
+ public void testNotifyShortcutState_whenUpdateOneHandedEnabled() {
+ when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(false);
+ when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
+ when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
+ when(mSpiedOneHandedController.isSwipeToNotificationEnabled()).thenReturn(true);
+ mSpiedOneHandedController.registerEventCallback(mMockEventCallback);
+ mSpiedOneHandedController.setOneHandedEnabled(true);
+
+ verify(mSpiedOneHandedController).notifyShortcutState(anyInt());
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
index a27ed11..ef16fd3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
@@ -418,4 +418,18 @@
verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset();
}
+
+ @Test
+ public void testDisplayArea_notReadyForTransition() {
+ OneHandedDisplayAreaOrganizer testSpiedDisplayAreaOrganizer = spy(
+ new OneHandedDisplayAreaOrganizer(mContext,
+ mDisplayLayout,
+ mMockSettingsUitl,
+ mMockAnimationController,
+ mTutorialHandler,
+ mMockBackgroundOrganizer,
+ mMockShellMainExecutor));
+
+ assertThat(testSpiedDisplayAreaOrganizer.isReady()).isFalse();
+ }
}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 332f7e6..44c335f 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -455,8 +455,7 @@
if (hasLayer()) {
this->setLayerSurface(nullptr);
}
- mSnapshotResult.snapshot = nullptr;
- mTargetImageFilter = nullptr;
+
if (mDisplayList) {
mDisplayList.updateChildren([](RenderNode* child) { child->destroyLayers(); });
}
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 8595b6e..c770150 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -330,6 +330,11 @@
} else {
mSkiaLayer.reset();
}
+
+ // Clear out the previous snapshot and the image filter the previous
+ // snapshot was created with whenever the layer changes.
+ mSnapshotResult.snapshot = nullptr;
+ mTargetImageFilter = nullptr;
}
/**
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
index d9b9e24..92e20c4 100644
--- a/libs/hwui/WebViewFunctorManager.cpp
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -197,6 +197,8 @@
auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions();
mSurfaceControl = funcs.createFunc(rootSurfaceControl, "Webview Overlay SurfaceControl");
ASurfaceTransaction* transaction = funcs.transactionCreateFunc();
+ activeContext->prepareSurfaceControlForWebview();
+ funcs.transactionSetZOrderFunc(transaction, mSurfaceControl, -1);
funcs.transactionSetVisibilityFunc(transaction, mSurfaceControl,
ASURFACE_TRANSACTION_VISIBILITY_SHOW);
funcs.transactionApplyFunc(transaction);
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 602c32a..9ff2f46 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -71,6 +71,10 @@
} gASurfaceTransactionCallback;
struct {
+ jmethodID prepare;
+} gPrepareSurfaceControlForWebviewCallback;
+
+struct {
jmethodID onFrameDraw;
} gFrameDrawingCallback;
@@ -500,6 +504,28 @@
jobject mObject;
};
+class JWeakGlobalRefHolder {
+public:
+ JWeakGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm) {
+ mWeakRef = getenv(vm)->NewWeakGlobalRef(object);
+ }
+
+ virtual ~JWeakGlobalRefHolder() {
+ if (mWeakRef != nullptr) getenv(mVm)->DeleteWeakGlobalRef(mWeakRef);
+ mWeakRef = nullptr;
+ }
+
+ jobject ref() { return mWeakRef; }
+ JavaVM* vm() { return mVm; }
+
+private:
+ JWeakGlobalRefHolder(const JWeakGlobalRefHolder&) = delete;
+ void operator=(const JWeakGlobalRefHolder&) = delete;
+
+ JavaVM* mVm;
+ jobject mWeakRef;
+};
+
using TextureMap = std::unordered_map<uint32_t, sk_sp<SkImage>>;
struct PictureCaptureState {
@@ -633,19 +659,45 @@
} else {
JavaVM* vm = nullptr;
LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
- auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(
- vm, env->NewGlobalRef(aSurfaceTransactionCallback));
+ auto globalCallbackRef =
+ std::make_shared<JWeakGlobalRefHolder>(vm, aSurfaceTransactionCallback);
proxy->setASurfaceTransactionCallback(
[globalCallbackRef](int64_t transObj, int64_t scObj, int64_t frameNr) {
JNIEnv* env = getenv(globalCallbackRef->vm());
- env->CallVoidMethod(globalCallbackRef->object(),
- gASurfaceTransactionCallback.onMergeTransaction,
+ jobject localref = env->NewLocalRef(globalCallbackRef->ref());
+ if (CC_UNLIKELY(!localref)) {
+ return;
+ }
+ env->CallVoidMethod(localref, gASurfaceTransactionCallback.onMergeTransaction,
static_cast<jlong>(transObj), static_cast<jlong>(scObj),
static_cast<jlong>(frameNr));
+ env->DeleteLocalRef(localref);
});
}
}
+static void android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback(
+ JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ if (!callback) {
+ proxy->setPrepareSurfaceControlForWebviewCallback(nullptr);
+ } else {
+ JavaVM* vm = nullptr;
+ LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
+ auto globalCallbackRef =
+ std::make_shared<JWeakGlobalRefHolder>(vm, callback);
+ proxy->setPrepareSurfaceControlForWebviewCallback([globalCallbackRef]() {
+ JNIEnv* env = getenv(globalCallbackRef->vm());
+ jobject localref = env->NewLocalRef(globalCallbackRef->ref());
+ if (CC_UNLIKELY(!localref)) {
+ return;
+ }
+ env->CallVoidMethod(localref, gPrepareSurfaceControlForWebviewCallback.prepare);
+ env->DeleteLocalRef(localref);
+ });
+ }
+}
+
static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
jobject clazz, jlong proxyPtr, jobject frameCallback) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -944,6 +996,9 @@
{"nSetASurfaceTransactionCallback",
"(JLandroid/graphics/HardwareRenderer$ASurfaceTransactionCallback;)V",
(void*)android_view_ThreadedRenderer_setASurfaceTransactionCallback},
+ {"nSetPrepareSurfaceControlForWebviewCallback",
+ "(JLandroid/graphics/HardwareRenderer$PrepareSurfaceControlForWebviewCallback;)V",
+ (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback},
{"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
(void*)android_view_ThreadedRenderer_setFrameCallback},
{"nSetFrameCompleteCallback",
@@ -1011,6 +1066,11 @@
gASurfaceTransactionCallback.onMergeTransaction =
GetMethodIDOrDie(env, aSurfaceTransactionCallbackClass, "onMergeTransaction", "(JJJ)V");
+ jclass prepareSurfaceControlForWebviewCallbackClass = FindClassOrDie(
+ env, "android/graphics/HardwareRenderer$PrepareSurfaceControlForWebviewCallback");
+ gPrepareSurfaceControlForWebviewCallback.prepare =
+ GetMethodIDOrDie(env, prepareSurfaceControlForWebviewCallbackClass, "prepare", "()V");
+
jclass frameCallbackClass = FindClassOrDie(env,
"android/graphics/HardwareRenderer$FrameDrawingCallback");
gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 8bfc2c1..44d0038 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -174,16 +174,12 @@
ATRACE_CALL();
if (window) {
- int extraBuffers = 0;
- native_window_get_extra_buffer_count(window, &extraBuffers);
-
mNativeSurface = std::make_unique<ReliableSurface>(window);
mNativeSurface->init();
if (enableTimeout) {
// TODO: Fix error handling & re-shorten timeout
ANativeWindow_setDequeueTimeout(window, 4000_ms);
}
- mNativeSurface->setExtraBufferCount(extraBuffers);
} else {
mNativeSurface = nullptr;
}
@@ -197,6 +193,7 @@
if (surfaceControl == nullptr) {
setASurfaceTransactionCallback(nullptr);
+ setPrepareSurfaceControlForWebviewCallback(nullptr);
}
if (mSurfaceControl != nullptr) {
@@ -918,6 +915,12 @@
return true;
}
+void CanvasContext::prepareSurfaceControlForWebview() {
+ if (mPrepareSurfaceControlForWebviewCallback) {
+ std::invoke(mPrepareSurfaceControlForWebviewCallback);
+ }
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 4bdc251..a61c2bf 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -212,6 +212,12 @@
bool mergeTransaction(ASurfaceTransaction* transaction, ASurfaceControl* control);
+ void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback) {
+ mPrepareSurfaceControlForWebviewCallback = callback;
+ }
+
+ void prepareSurfaceControlForWebview();
+
static CanvasContext* getActiveContext();
private:
@@ -312,6 +318,8 @@
bool mExpectSurfaceStats = false;
std::function<void(int64_t, int64_t, int64_t)> mASurfaceTransactionCallback;
+ std::function<void()> mPrepareSurfaceControlForWebviewCallback;
+
void cleanupResources();
};
diff --git a/libs/hwui/renderthread/ReliableSurface.cpp b/libs/hwui/renderthread/ReliableSurface.cpp
index c29cc11..6df34be 100644
--- a/libs/hwui/renderthread/ReliableSurface.cpp
+++ b/libs/hwui/renderthread/ReliableSurface.cpp
@@ -278,7 +278,6 @@
int result = query(window, what, value);
if (what == ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS && result == OK) {
std::lock_guard _lock{rs->mMutex};
- *value += rs->mExtraBuffers;
rs->mExpectedBufferCount = *value + 2;
}
return result;
diff --git a/libs/hwui/renderthread/ReliableSurface.h b/libs/hwui/renderthread/ReliableSurface.h
index 41969e7..5959647 100644
--- a/libs/hwui/renderthread/ReliableSurface.h
+++ b/libs/hwui/renderthread/ReliableSurface.h
@@ -51,11 +51,6 @@
return ret;
}
- void setExtraBufferCount(size_t extraBuffers) {
- std::lock_guard _lock{mMutex};
- mExtraBuffers = extraBuffers;
- }
-
bool didSetExtraBuffers() const {
std::lock_guard _lock{mMutex};
return mDidSetExtraBuffers;
@@ -73,7 +68,6 @@
base::unique_fd mReservedFenceFd;
bool mHasDequeuedBuffer = false;
int mBufferQueueState = OK;
- size_t mExtraBuffers = 0;
size_t mExpectedBufferCount = 0;
bool mDidSetExtraBuffers = false;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 6fd644b..c47050c 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -319,6 +319,12 @@
[this, cb = callback]() { mContext->setASurfaceTransactionCallback(cb); });
}
+void RenderProxy::setPrepareSurfaceControlForWebviewCallback(
+ const std::function<void()>& callback) {
+ mRenderThread.queue().post(
+ [this, cb = callback]() { mContext->setPrepareSurfaceControlForWebviewCallback(cb); });
+}
+
void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) {
mDrawFrameTask.setFrameCallback(std::move(callback));
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 6d80949..d575aa7 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -124,6 +124,7 @@
void setPictureCapturedCallback(const std::function<void(sk_sp<SkPicture>&&)>& callback);
void setASurfaceTransactionCallback(
const std::function<void(int64_t, int64_t, int64_t)>& callback);
+ void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback);
void setFrameCallback(std::function<void(int64_t)>&& callback);
void setFrameCompleteCallback(std::function<void(int64_t)>&& callback);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 4ba7748..524407d 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -102,6 +102,10 @@
(AST_setVisibility)dlsym(handle_, "ASurfaceTransaction_setVisibility");
LOG_ALWAYS_FATAL_IF(transactionSetVisibilityFunc == nullptr,
"Failed to find required symbol ASurfaceTransaction_setVisibility!");
+
+ transactionSetZOrderFunc = (AST_setZOrder)dlsym(handle_, "ASurfaceTransaction_setZOrder");
+ LOG_ALWAYS_FATAL_IF(transactionSetZOrderFunc == nullptr,
+ "Failed to find required symbol ASurfaceTransaction_setZOrder!");
}
void RenderThread::frameCallback(int64_t frameTimeNanos, void* data) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index dd06009..c5e3746 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -96,6 +96,8 @@
typedef void (*AST_apply)(ASurfaceTransaction* transaction);
typedef void (*AST_setVisibility)(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, int8_t visibility);
+typedef void (*AST_setZOrder)(ASurfaceTransaction* transaction, ASurfaceControl* surface_control,
+ int32_t z_order);
struct ASurfaceControlFunctions {
ASurfaceControlFunctions();
@@ -112,6 +114,7 @@
AST_delete transactionDeleteFunc;
AST_apply transactionApplyFunc;
AST_setVisibility transactionSetVisibilityFunc;
+ AST_setZOrder transactionSetZOrderFunc;
};
class ChoreographerSource;
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index f446678..4cd3616 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -363,9 +363,9 @@
}
/**
- * Gets per-satellite sync state.
+ * Gets per-satellite-signal sync state.
*
- * <p>It represents the current sync state for the associated satellite.
+ * <p>It represents the current sync state for the associated satellite signal.
*
* <p>This value helps interpret {@link #getReceivedSvTimeNanos()}.
*/
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index 8de5074..6dc05ad 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -158,7 +158,8 @@
ICamera cameraUser = mUtils.getCameraService()
.connect(dummyCallbacks, cameraId, clientPackageName,
ICameraService.USE_CALLING_UID,
- ICameraService.USE_CALLING_PID);
+ ICameraService.USE_CALLING_PID,
+ getContext().getApplicationInfo().targetSdkVersion);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -262,7 +263,8 @@
mUtils.getCameraService().connectDevice(
dummyCallbacks, String.valueOf(cameraId),
clientPackageName, clientAttributionTag,
- ICameraService.USE_CALLING_UID, 0 /*oomScoreOffset*/);
+ ICameraService.USE_CALLING_UID, 0 /*oomScoreOffset*/,
+ getContext().getApplicationInfo().targetSdkVersion);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 408f2f8..0890346 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -244,7 +244,7 @@
mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
clientPackageName, clientAttributionTag, ICameraService.USE_CALLING_UID,
- /*oomScoreOffset*/0);
+ /*oomScoreOffset*/0, getContext().getApplicationInfo().targetSdkVersion);
assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
@@ -416,7 +416,8 @@
@SmallTest
public void testCameraCharacteristics() throws RemoteException {
- CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId);
+ CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId,
+ getContext().getApplicationInfo().targetSdkVersion);
assertFalse(info.isEmpty());
assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
diff --git a/packages/CtsShim/apk/arm/CtsShim.apk b/packages/CtsShim/apk/arm/CtsShim.apk
index bb6dfa3..da4ae56 100644
--- a/packages/CtsShim/apk/arm/CtsShim.apk
+++ b/packages/CtsShim/apk/arm/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/arm/CtsShimPriv.apk b/packages/CtsShim/apk/arm/CtsShimPriv.apk
index 2835d57..214d5c2 100644
--- a/packages/CtsShim/apk/arm/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/arm/CtsShimPriv.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShim.apk b/packages/CtsShim/apk/x86/CtsShim.apk
index bb6dfa3..da4ae56 100644
--- a/packages/CtsShim/apk/x86/CtsShim.apk
+++ b/packages/CtsShim/apk/x86/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShimPriv.apk b/packages/CtsShim/apk/x86/CtsShimPriv.apk
index 2e1a789..b4c625f 100644
--- a/packages/CtsShim/apk/x86/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/x86/CtsShimPriv.apk
Binary files differ
diff --git a/packages/PackageInstaller/res/values-de/strings.xml b/packages/PackageInstaller/res/values-de/strings.xml
index dab3fcb0..a782fd2 100644
--- a/packages/PackageInstaller/res/values-de/strings.xml
+++ b/packages/PackageInstaller/res/values-de/strings.xml
@@ -46,7 +46,7 @@
<string name="out_of_space_dlg_text" msgid="8727714096031856231">"<xliff:g id="APP_NAME">%1$s</xliff:g> konnte nicht installiert werden. Gib Speicherplatz frei und versuche es noch einmal."</string>
<string name="app_not_found_dlg_title" msgid="5107924008597470285">"App nicht gefunden"</string>
<string name="app_not_found_dlg_text" msgid="5219983779377811611">"Die App wurde nicht in der Liste der installierten Apps gefunden."</string>
- <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Nicht zulässig"</string>
+ <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Nicht zugelassen"</string>
<string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"Der aktuelle Nutzer ist nicht dazu berechtigt, diese Deinstallation auszuführen."</string>
<string name="generic_error_dlg_title" msgid="5863195085927067752">"Fehler"</string>
<string name="generic_error_dlg_text" msgid="5287861443265795232">"App konnte nicht deinstalliert werden."</string>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/layout-v31/settingslib_banner_message.xml b/packages/SettingsLib/BannerMessagePreference/res/layout-v31/settingslib_banner_message.xml
index 904b78c..6f504ef 100644
--- a/packages/SettingsLib/BannerMessagePreference/res/layout-v31/settingslib_banner_message.xml
+++ b/packages/SettingsLib/BannerMessagePreference/res/layout-v31/settingslib_banner_message.xml
@@ -15,7 +15,7 @@
limitations under the License.
-->
-<LinearLayout
+<com.android.settingslib.widget.BannerMessageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -23,6 +23,7 @@
style="@style/Banner.Preference.SettingsLib">
<RelativeLayout
+ android:id="@+id/top_row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
@@ -49,6 +50,7 @@
android:id="@+id/banner_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingTop="0dp"
android:paddingBottom="4dp"
android:textAppearance="@style/Banner.Title.SettingsLib"/>
@@ -56,6 +58,7 @@
android:id="@+id/banner_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingTop="0dp"
android:paddingBottom="4dp"
android:textAppearance="@style/Banner.Subtitle.SettingsLib"
android:visibility="gone"/>
@@ -87,4 +90,4 @@
android:layout_height="wrap_content"
style="@style/Banner.ButtonText.SettingsLib"/>
</LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</com.android.settingslib.widget.BannerMessageView>
\ No newline at end of file
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-af/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-af/strings.xml
new file mode 100644
index 0000000..d7e778f
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-af/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Weier"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-am/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-am/strings.xml
new file mode 100644
index 0000000..6701dea
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-am/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"አሰናብት"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ar/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ar/strings.xml
new file mode 100644
index 0000000..0f1b9ac
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ar/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"إغلاق"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-as/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-as/strings.xml
new file mode 100644
index 0000000..21dd94c
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-as/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"অগ্ৰাহ্য কৰক"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-az/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-az/strings.xml
new file mode 100644
index 0000000..7f91eb4
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-az/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Qapadın"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..ca16c3d
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Odbacite"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-be/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-be/strings.xml
new file mode 100644
index 0000000..b0980ea
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-be/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Адхіліць"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-bg/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-bg/strings.xml
new file mode 100644
index 0000000..cccbf96
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-bg/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Отхвърляне"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-bs/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-bs/strings.xml
new file mode 100644
index 0000000..5e46c6c
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-bs/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Odbacivanje"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ca/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ca/strings.xml
new file mode 100644
index 0000000..81bb048
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ca/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Ignora"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-cs/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-cs/strings.xml
new file mode 100644
index 0000000..ac7623e
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-cs/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Zavřít"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-da/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-da/strings.xml
new file mode 100644
index 0000000..8c185d9
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-da/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Luk"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-el/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-el/strings.xml
new file mode 100644
index 0000000..65843b2
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-el/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Παράβλεψη"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-en-rAU/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..418c1d5
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-en-rAU/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Dismiss"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-en-rCA/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..418c1d5
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-en-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Dismiss"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-en-rGB/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..418c1d5
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-en-rGB/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Dismiss"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-en-rIN/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..418c1d5
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-en-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Dismiss"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-en-rXC/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..e2dae5e
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-en-rXC/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Dismiss"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-es-rUS/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..4816be6
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-es-rUS/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Descartar"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-es/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-es/strings.xml
new file mode 100644
index 0000000..5e820238
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-es/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Cerrar"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-et/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-et/strings.xml
new file mode 100644
index 0000000..a688723
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-et/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Loobu"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-eu/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-eu/strings.xml
new file mode 100644
index 0000000..64dd1c5
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-eu/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Baztertu"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-fa/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-fa/strings.xml
new file mode 100644
index 0000000..bd8985f
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-fa/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"رد شدن"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-fi/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-fi/strings.xml
new file mode 100644
index 0000000..c384157
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-fi/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Ohita"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-fr-rCA/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..dd5889c
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-fr-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Fermer"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-fr/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-fr/strings.xml
new file mode 100644
index 0000000..dd5889c
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-fr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Fermer"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-gl/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-gl/strings.xml
new file mode 100644
index 0000000..d787626
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-gl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Ignorar"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-hi/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-hi/strings.xml
new file mode 100644
index 0000000..f66ee7f
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-hi/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"खारिज करें"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-hr/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-hr/strings.xml
new file mode 100644
index 0000000..f7e7cd0
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-hr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Odbaci"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-hu/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-hu/strings.xml
new file mode 100644
index 0000000..1551c84
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-hu/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Bezárás"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-hy/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-hy/strings.xml
new file mode 100644
index 0000000..e014cce
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-hy/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Փակել"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-in/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-in/strings.xml
new file mode 100644
index 0000000..607e811
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-in/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Tutup"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-is/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-is/strings.xml
new file mode 100644
index 0000000..4afc614
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-is/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Hunsa"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-it/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-it/strings.xml
new file mode 100644
index 0000000..81bb048
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-it/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Ignora"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ja/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ja/strings.xml
new file mode 100644
index 0000000..b42f6e6
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ja/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"閉じる"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ka/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ka/strings.xml
new file mode 100644
index 0000000..7bde8b6
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ka/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"უარყოფა"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-kk/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-kk/strings.xml
new file mode 100644
index 0000000..01235e0
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-kk/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Жабу"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-km/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-km/strings.xml
new file mode 100644
index 0000000..4e14820
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-km/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"ច្រានចោល"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-kn/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-kn/strings.xml
new file mode 100644
index 0000000..b9a5420
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-kn/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"ವಜಾಗೊಳಿಸಿ"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ko/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ko/strings.xml
new file mode 100644
index 0000000..9b51699
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ko/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"닫기"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ky/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ky/strings.xml
new file mode 100644
index 0000000..affb8ec
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ky/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Жабуу"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-lo/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-lo/strings.xml
new file mode 100644
index 0000000..7079f7c
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-lo/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"ປິດໄວ້"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-lt/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-lt/strings.xml
new file mode 100644
index 0000000..4cee14a
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-lt/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Atsisakyti"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-lv/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-lv/strings.xml
new file mode 100644
index 0000000..120a762
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-lv/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Nerādīt"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-mk/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-mk/strings.xml
new file mode 100644
index 0000000..76a4390
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-mk/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Отфрли"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ml/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ml/strings.xml
new file mode 100644
index 0000000..5a4e14c
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ml/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"ഡിസ്മിസ് ചെയ്യുക"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-mn/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-mn/strings.xml
new file mode 100644
index 0000000..3974470
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-mn/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Үл хэрэгсэх"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ms/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ms/strings.xml
new file mode 100644
index 0000000..290323b
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ms/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Ketepikan"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-my/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-my/strings.xml
new file mode 100644
index 0000000..52ecc49
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-my/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"ပယ်ရန်"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-nb/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-nb/strings.xml
new file mode 100644
index 0000000..c1e39a4
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-nb/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Lukk"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-nl/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-nl/strings.xml
new file mode 100644
index 0000000..920349f
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-nl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Sluiten"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-pa/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-pa/strings.xml
new file mode 100644
index 0000000..250ef2e
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-pa/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"ਖਾਰਜ ਕਰੋ"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-pl/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-pl/strings.xml
new file mode 100644
index 0000000..9ad630a
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-pl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Zamknij"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-pt-rBR/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..80b70ae
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-pt-rBR/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Dispensar"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-pt-rPT/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..d787626
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-pt-rPT/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Ignorar"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-pt/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-pt/strings.xml
new file mode 100644
index 0000000..80b70ae
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-pt/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Dispensar"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ro/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ro/strings.xml
new file mode 100644
index 0000000..18b6a0e
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ro/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Respingeți"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ru/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ru/strings.xml
new file mode 100644
index 0000000..b694657
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ru/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Закрыть"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-si/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-si/strings.xml
new file mode 100644
index 0000000..d818cf7
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-si/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"ඉවත ලන්න"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-sk/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-sk/strings.xml
new file mode 100644
index 0000000..4f59f85
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-sk/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Zavrieť"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-sl/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-sl/strings.xml
new file mode 100644
index 0000000..1ca68bf
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-sl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Opusti"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-sq/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-sq/strings.xml
new file mode 100644
index 0000000..dbe7927
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-sq/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Hiq"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-sr/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-sr/strings.xml
new file mode 100644
index 0000000..68a2d5b
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-sr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Одбаците"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-sv/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-sv/strings.xml
new file mode 100644
index 0000000..ef2df3c
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-sv/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Ignorera"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-sw/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-sw/strings.xml
new file mode 100644
index 0000000..ebb0c02
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-sw/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Ondoa"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ta/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ta/strings.xml
new file mode 100644
index 0000000..9b175c7
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ta/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"மூடும்"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-th/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-th/strings.xml
new file mode 100644
index 0000000..6546bfa
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-th/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"ปิด"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-tl/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-tl/strings.xml
new file mode 100644
index 0000000..9b944de
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-tl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"I-dismiss"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-tr/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-tr/strings.xml
new file mode 100644
index 0000000..96d49e9
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-tr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Kapat"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-uk/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-uk/strings.xml
new file mode 100644
index 0000000..f51b0e7
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-uk/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Закрити"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ur/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ur/strings.xml
new file mode 100644
index 0000000..ad3fafb
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ur/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"برخاست کریں"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-uz/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-uz/strings.xml
new file mode 100644
index 0000000..1e24745
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-uz/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Yopish"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-vi/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-vi/strings.xml
new file mode 100644
index 0000000..a30cdbf
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-vi/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Đóng"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-zh-rCN/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..a8f36e4
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-zh-rCN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"关闭"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-zh-rHK/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..b9ee658
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-zh-rHK/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"關閉"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-zh-rTW/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..b9ee658
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-zh-rTW/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"關閉"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-zu/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-zu/strings.xml
new file mode 100644
index 0000000..80faa17
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-zu/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Cashisa"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessageView.java b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessageView.java
new file mode 100644
index 0000000..5ca6fb6
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessageView.java
@@ -0,0 +1,111 @@
+/*
+ * 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.settingslib.widget;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.TouchDelegate;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+
+/**
+ * The view providing {@link BannerMessagePreference}.
+ *
+ * <p>Callers should not instantiate this view directly but rather through adding a
+ * {@link BannerMessagePreference} to a {@code PreferenceScreen}.
+ */
+public class BannerMessageView extends LinearLayout {
+ private Rect mTouchTargetForDismissButton;
+
+ public BannerMessageView(Context context) {
+ super(context);
+ }
+
+ public BannerMessageView(Context context,
+ @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public BannerMessageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public BannerMessageView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ setupIncreaseTouchTargetForDismissButton();
+ }
+
+ private void setupIncreaseTouchTargetForDismissButton() {
+ if (mTouchTargetForDismissButton != null) {
+ // Already set up
+ return;
+ }
+
+ // The dismiss button is in the 'top row' RelativeLayout for positioning, but this element
+ // does not have enough space to provide large touch targets. We therefore set the top
+ // target on this view.
+ View topRow = findViewById(R.id.top_row);
+ View dismissButton = findViewById(R.id.banner_dismiss_btn);
+ if (topRow == null || dismissButton == null || dismissButton.getVisibility() != VISIBLE) {
+ return;
+ }
+
+ int minimum =
+ getResources()
+ .getDimensionPixelSize(R.dimen.settingslib_preferred_minimum_touch_target);
+ int width = dismissButton.getWidth();
+ int height = dismissButton.getHeight();
+ int widthIncrease = width < minimum ? minimum - width : 0;
+ int heightIncrease = height < minimum ? minimum - height : 0;
+
+ // Compute the hit rect of dismissButton within the local co-orindate reference of this view
+ // (rather than it's direct parent topRow).
+ Rect hitRectWithinTopRow = new Rect();
+ dismissButton.getHitRect(hitRectWithinTopRow);
+ Rect hitRectOfTopRowWithinThis = new Rect();
+ topRow.getHitRect(hitRectOfTopRowWithinThis);
+ mTouchTargetForDismissButton = new Rect();
+ mTouchTargetForDismissButton.left =
+ hitRectOfTopRowWithinThis.left + hitRectWithinTopRow.left;
+ mTouchTargetForDismissButton.right =
+ hitRectOfTopRowWithinThis.left + hitRectWithinTopRow.right;
+ mTouchTargetForDismissButton.top =
+ hitRectOfTopRowWithinThis.top + hitRectWithinTopRow.top;
+ mTouchTargetForDismissButton.bottom =
+ hitRectOfTopRowWithinThis.top + hitRectWithinTopRow.bottom;
+
+ // Adjust the touch target rect to apply the necessary increase in width and height.
+ mTouchTargetForDismissButton.left -=
+ widthIncrease % 2 == 1 ? (widthIncrease / 2) + 1 : widthIncrease / 2;
+ mTouchTargetForDismissButton.top -=
+ heightIncrease % 2 == 1 ? (heightIncrease / 2) + 1 : heightIncrease / 2;
+ mTouchTargetForDismissButton.right += widthIncrease / 2;
+ mTouchTargetForDismissButton.bottom += heightIncrease / 2;
+
+ setTouchDelegate(new TouchDelegate(mTouchTargetForDismissButton, dismissButton));
+ }
+
+}
diff --git a/packages/SettingsLib/FooterPreference/res/values-af/strings.xml b/packages/SettingsLib/FooterPreference/res/values-af/strings.xml
new file mode 100644
index 0000000..c17f3ed
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-af/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Kom meer te wete"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-am/strings.xml b/packages/SettingsLib/FooterPreference/res/values-am/strings.xml
new file mode 100644
index 0000000..02e6131
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-am/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"የበለጠ ለመረዳት"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ar/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ar/strings.xml
new file mode 100644
index 0000000..1f279a6
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ar/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"مزيد من المعلومات"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-as/strings.xml b/packages/SettingsLib/FooterPreference/res/values-as/strings.xml
new file mode 100644
index 0000000..a34b474
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-as/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"অধিক জানক"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-az/strings.xml b/packages/SettingsLib/FooterPreference/res/values-az/strings.xml
new file mode 100644
index 0000000..b49036e
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-az/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Ətraflı məlumat"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/FooterPreference/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..993ec9a
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Saznajte više"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-be/strings.xml b/packages/SettingsLib/FooterPreference/res/values-be/strings.xml
new file mode 100644
index 0000000..f9d6129
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-be/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Даведацца больш"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-bg/strings.xml b/packages/SettingsLib/FooterPreference/res/values-bg/strings.xml
new file mode 100644
index 0000000..605663d
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-bg/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Научете повече"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-bs/strings.xml b/packages/SettingsLib/FooterPreference/res/values-bs/strings.xml
new file mode 100644
index 0000000..993ec9a
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-bs/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Saznajte više"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ca/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ca/strings.xml
new file mode 100644
index 0000000..7abf10f
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ca/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Més informació"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-cs/strings.xml b/packages/SettingsLib/FooterPreference/res/values-cs/strings.xml
new file mode 100644
index 0000000..decbb68e
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-cs/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Další informace"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-da/strings.xml b/packages/SettingsLib/FooterPreference/res/values-da/strings.xml
new file mode 100644
index 0000000..81d1c7c
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-da/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Få flere oplysninger"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-el/strings.xml b/packages/SettingsLib/FooterPreference/res/values-el/strings.xml
new file mode 100644
index 0000000..5a30833
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-el/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Μάθετε περισσότερα"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-en-rAU/strings.xml b/packages/SettingsLib/FooterPreference/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..924d735
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-en-rAU/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Learn more"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-en-rCA/strings.xml b/packages/SettingsLib/FooterPreference/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..924d735
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-en-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Learn more"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-en-rGB/strings.xml b/packages/SettingsLib/FooterPreference/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..924d735
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-en-rGB/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Learn more"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-en-rIN/strings.xml b/packages/SettingsLib/FooterPreference/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..924d735
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-en-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Learn more"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-en-rXC/strings.xml b/packages/SettingsLib/FooterPreference/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..bd12547
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-en-rXC/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Learn more"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-es-rUS/strings.xml b/packages/SettingsLib/FooterPreference/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..f31d9ea
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-es-rUS/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Más información"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-es/strings.xml b/packages/SettingsLib/FooterPreference/res/values-es/strings.xml
new file mode 100644
index 0000000..f31d9ea
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-es/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Más información"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-et/strings.xml b/packages/SettingsLib/FooterPreference/res/values-et/strings.xml
new file mode 100644
index 0000000..78b65ed
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-et/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Lisateave"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-eu/strings.xml b/packages/SettingsLib/FooterPreference/res/values-eu/strings.xml
new file mode 100644
index 0000000..cf7fa00
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-eu/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Lortu informazio gehiago"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-fa/strings.xml b/packages/SettingsLib/FooterPreference/res/values-fa/strings.xml
new file mode 100644
index 0000000..464c58e
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-fa/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"بیشتر بدانید"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-fi/strings.xml b/packages/SettingsLib/FooterPreference/res/values-fi/strings.xml
new file mode 100644
index 0000000..856b962
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-fi/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Lue lisää"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-fr-rCA/strings.xml b/packages/SettingsLib/FooterPreference/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..6d856ca
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-fr-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"En savoir plus"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-fr/strings.xml b/packages/SettingsLib/FooterPreference/res/values-fr/strings.xml
new file mode 100644
index 0000000..6d856ca
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-fr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"En savoir plus"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-gl/strings.xml b/packages/SettingsLib/FooterPreference/res/values-gl/strings.xml
new file mode 100644
index 0000000..cde57d8
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-gl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Máis información"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-hi/strings.xml b/packages/SettingsLib/FooterPreference/res/values-hi/strings.xml
new file mode 100644
index 0000000..95ae240
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-hi/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"ज़्यादा जानें"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-hr/strings.xml b/packages/SettingsLib/FooterPreference/res/values-hr/strings.xml
new file mode 100644
index 0000000..993ec9a
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-hr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Saznajte više"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-hu/strings.xml b/packages/SettingsLib/FooterPreference/res/values-hu/strings.xml
new file mode 100644
index 0000000..ae3c948
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-hu/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"További információ"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-hy/strings.xml b/packages/SettingsLib/FooterPreference/res/values-hy/strings.xml
new file mode 100644
index 0000000..de9137b
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-hy/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Իմանալ ավելին"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-in/strings.xml b/packages/SettingsLib/FooterPreference/res/values-in/strings.xml
new file mode 100644
index 0000000..4b5cb16
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-in/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Pelajari lebih lanjut"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-is/strings.xml b/packages/SettingsLib/FooterPreference/res/values-is/strings.xml
new file mode 100644
index 0000000..111094c
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-is/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Nánar"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-it/strings.xml b/packages/SettingsLib/FooterPreference/res/values-it/strings.xml
new file mode 100644
index 0000000..053c80c
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-it/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Scopri di più"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ja/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ja/strings.xml
new file mode 100644
index 0000000..3312cb4
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ja/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"詳細"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ka/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ka/strings.xml
new file mode 100644
index 0000000..67bb223
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ka/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"შეიტყვეთ მეტი"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-kk/strings.xml b/packages/SettingsLib/FooterPreference/res/values-kk/strings.xml
new file mode 100644
index 0000000..db11a76
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-kk/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Толығырақ"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-km/strings.xml b/packages/SettingsLib/FooterPreference/res/values-km/strings.xml
new file mode 100644
index 0000000..1977dd3
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-km/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"ស្វែងយល់បន្ថែម"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-kn/strings.xml b/packages/SettingsLib/FooterPreference/res/values-kn/strings.xml
new file mode 100644
index 0000000..47fa3d5
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-kn/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ko/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ko/strings.xml
new file mode 100644
index 0000000..d8d2200
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ko/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"자세히 알아보기"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ky/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ky/strings.xml
new file mode 100644
index 0000000..74c6a49
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ky/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Кеңири маалымат"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-lo/strings.xml b/packages/SettingsLib/FooterPreference/res/values-lo/strings.xml
new file mode 100644
index 0000000..2e4124b
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-lo/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"ສຶກສາເພີ່ມເຕີມ"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-lt/strings.xml b/packages/SettingsLib/FooterPreference/res/values-lt/strings.xml
new file mode 100644
index 0000000..2981c66
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-lt/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Sužinokite daugiau"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-lv/strings.xml b/packages/SettingsLib/FooterPreference/res/values-lv/strings.xml
new file mode 100644
index 0000000..9766305
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-lv/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Uzzināt vairāk"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-mk/strings.xml b/packages/SettingsLib/FooterPreference/res/values-mk/strings.xml
new file mode 100644
index 0000000..1f734c5
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-mk/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Дознајте повеќе"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ml/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ml/strings.xml
new file mode 100644
index 0000000..1cd466b
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ml/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"കൂടുതലറിയുക"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-mn/strings.xml b/packages/SettingsLib/FooterPreference/res/values-mn/strings.xml
new file mode 100644
index 0000000..8bac1eb
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-mn/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Нэмэлт мэдээлэл авах"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ms/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ms/strings.xml
new file mode 100644
index 0000000..cd1b17a
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ms/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Ketahui lebih lanjut"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-my/strings.xml b/packages/SettingsLib/FooterPreference/res/values-my/strings.xml
new file mode 100644
index 0000000..751a87a
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-my/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"ပိုမိုလေ့လာရန်"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-nb/strings.xml b/packages/SettingsLib/FooterPreference/res/values-nb/strings.xml
new file mode 100644
index 0000000..08de009
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-nb/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Finn ut mer"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-nl/strings.xml b/packages/SettingsLib/FooterPreference/res/values-nl/strings.xml
new file mode 100644
index 0000000..1564081
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-nl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Meer informatie"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-pa/strings.xml b/packages/SettingsLib/FooterPreference/res/values-pa/strings.xml
new file mode 100644
index 0000000..1ce2ef2
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-pa/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"ਹੋਰ ਜਾਣੋ"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-pl/strings.xml b/packages/SettingsLib/FooterPreference/res/values-pl/strings.xml
new file mode 100644
index 0000000..5709f3e
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-pl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Więcej informacji"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-pt-rBR/strings.xml b/packages/SettingsLib/FooterPreference/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..bc410ab
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-pt-rBR/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Saiba mais"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-pt-rPT/strings.xml b/packages/SettingsLib/FooterPreference/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..bc410ab
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-pt-rPT/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Saiba mais"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-pt/strings.xml b/packages/SettingsLib/FooterPreference/res/values-pt/strings.xml
new file mode 100644
index 0000000..bc410ab
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-pt/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Saiba mais"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ro/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ro/strings.xml
new file mode 100644
index 0000000..2b50117
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ro/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Aflați mai multe"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ru/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ru/strings.xml
new file mode 100644
index 0000000..bedde40
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ru/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Подробнее…"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-si/strings.xml b/packages/SettingsLib/FooterPreference/res/values-si/strings.xml
new file mode 100644
index 0000000..1a60601
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-si/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"තව දැන ගන්න"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-sk/strings.xml b/packages/SettingsLib/FooterPreference/res/values-sk/strings.xml
new file mode 100644
index 0000000..c1008e5
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-sk/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Ďalšie informácie"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-sl/strings.xml b/packages/SettingsLib/FooterPreference/res/values-sl/strings.xml
new file mode 100644
index 0000000..79e0a73
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-sl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Več o tem"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-sq/strings.xml b/packages/SettingsLib/FooterPreference/res/values-sq/strings.xml
new file mode 100644
index 0000000..0fea476c
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-sq/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Mëso më shumë"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-sr/strings.xml b/packages/SettingsLib/FooterPreference/res/values-sr/strings.xml
new file mode 100644
index 0000000..9a73269
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-sr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Сазнајте више"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-sv/strings.xml b/packages/SettingsLib/FooterPreference/res/values-sv/strings.xml
new file mode 100644
index 0000000..a78c3cb
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-sv/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Läs mer"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-sw/strings.xml b/packages/SettingsLib/FooterPreference/res/values-sw/strings.xml
new file mode 100644
index 0000000..52b1732
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-sw/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Pata maelezo zaidi"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ta/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ta/strings.xml
new file mode 100644
index 0000000..75fc7c1
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ta/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"மேலும் அறிக"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-th/strings.xml b/packages/SettingsLib/FooterPreference/res/values-th/strings.xml
new file mode 100644
index 0000000..025a2f0
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-th/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"ดูข้อมูลเพิ่มเติม"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-tl/strings.xml b/packages/SettingsLib/FooterPreference/res/values-tl/strings.xml
new file mode 100644
index 0000000..4b6f830
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-tl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Matuto pa"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-tr/strings.xml b/packages/SettingsLib/FooterPreference/res/values-tr/strings.xml
new file mode 100644
index 0000000..77d15130
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-tr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Daha fazla bilgi"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-uk/strings.xml b/packages/SettingsLib/FooterPreference/res/values-uk/strings.xml
new file mode 100644
index 0000000..cec933d
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-uk/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Докладніше"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ur/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ur/strings.xml
new file mode 100644
index 0000000..1dceea7
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ur/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"مزید جانیں"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-uz/strings.xml b/packages/SettingsLib/FooterPreference/res/values-uz/strings.xml
new file mode 100644
index 0000000..5823949
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-uz/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Batafsil"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-vi/strings.xml b/packages/SettingsLib/FooterPreference/res/values-vi/strings.xml
new file mode 100644
index 0000000..d6c4638
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-vi/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Tìm hiểu thêm"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-zh-rCN/strings.xml b/packages/SettingsLib/FooterPreference/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..446c8ce
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-zh-rCN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"了解详情"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-zh-rHK/strings.xml b/packages/SettingsLib/FooterPreference/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..8ab38c6
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-zh-rHK/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"瞭解詳情"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-zh-rTW/strings.xml b/packages/SettingsLib/FooterPreference/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..8ab38c6
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-zh-rTW/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"瞭解詳情"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-zu/strings.xml b/packages/SettingsLib/FooterPreference/res/values-zu/strings.xml
new file mode 100644
index 0000000..b53eb85
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-zu/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Funda kabanzi"</string>
+</resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml
index acbf359..ddcc83e 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml
@@ -18,4 +18,5 @@
<resources>
<dimen name="app_preference_padding_start">20dp</dimen>
<dimen name="app_icon_min_width">52dp</dimen>
+ <dimen name="settingslib_preferred_minimum_touch_target">48dp</dimen>
</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 366cb06..89bb9e8 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Bynaam"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Voeg gas by"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Verwyder gas"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gas"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Neem \'n foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Kies \'n prent"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 8a5da97..bc1bd16 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"ቅጽል ስም"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"እንግዳን አክል"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"እንግዳን አስወግድ"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"እንግዳ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ፎቶ አንሳ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ምስል ይምረጡ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 0eef43b..525a497 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -511,8 +511,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"المنبّهات والتذكيرات"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"السماح بضبط المنبّهات والتذكيرات"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"المنبّهات والتذكيرات"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"عليك السماح لهذا التطبيق بضبط المنبّهات وتحديد مواعيد للإجراءات الحساسة زمنيًا. يسمح هذا الأذن بتشغيل التطبيق في الخلفية، ما قد يستهلك المزيد من شحن البطارية.\n\nإذا كان هذا الإذن غير مسموح به، لن تعمل الأحداث المستندة إلى وقت والمنبّهات الحالية التي يحدِّد هذا التطبيق موعدها."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"جدول زمني، جدولة، منبّه، تذكير، ساعة"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"تفعيل"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"تفعيل ميزة \"عدم الإزعاج\""</string>
@@ -571,6 +570,8 @@
<string name="user_nickname" msgid="262624187455825083">"اللقب"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"إضافة ضيف"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"إزالة جلسة الضيف"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"ضيف"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"التقاط صورة"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"اختيار صورة"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index b8796fe..f04aaac 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"এলাৰ্ম আৰু ৰিমাইণ্ডাৰ"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"এলাৰ্ম আৰু ৰিমাইণ্ডাৰ ছেট কৰাৰ অনুমতি দিয়ক"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"এলাৰ্ম আৰু ৰিমাইণ্ডাৰ"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"এই এপ্টোক এলাৰ্ম ছেট কৰিবলৈ আৰু সময় সংবেদনশীল কাৰ্যৰ সময়সূচী নিৰ্ধাৰণ কৰিবলৈ দিয়ক। ই এপ্টোক নেপথ্যত চলি থকাৰ অনুমতি দিয়ে যাৰ ফলত অধিক বেটাৰী ব্যৱহাৰ হয়।\n\nএই অনুমতিটো অফ কৰা থাকিলে, ইতিমধ্যে ছেট কৰা এলাৰ্ম আৰু এই এপ্টোৱে সময়সূচী নিৰ্ধাৰণ কৰা সময় ভিত্তিক অনুষ্ঠানসমূহে কাম নকৰা হ’ব।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"সময়সূচী, এলাৰ্ম, ৰিমাইণ্ডাৰ, ঘড়ী"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"অন কৰক"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"অসুবিধা নিদিব অন কৰক"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"উপনাম"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ কৰক"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি আঁতৰাওক"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"এখন ফট’ তোলক"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"এখন প্ৰতিচ্ছবি বাছনি কৰক"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index a5a3321..b7cf11a 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Ləqəb"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Qonaq əlavə edin"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Qonağı silin"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Qonaq"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Foto çəkin"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Şəkil seçin"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 7903230..97c281a 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -567,6 +567,8 @@
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Slikaj"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberi sliku"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 0fb7178..2d1a362 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -509,8 +509,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Будзільнікі і напаміны"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Дазволіць усталёўваць будзільнікі і напаміны"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будзільнікі і напаміны"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Дазвольце гэтай праграме ўключаць будзільнікі і задаваць час дзеянняў. З такім дазволам праграма можа працаваць у фонавым рэжыме і ў выніку хутчэй разраджаць акумулятар.\n\nКалі вы не ўключыце гэты дазвол, існуючыя будзільнікі і запланаваны праграмай час падзей не будуць працаваць."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"расклад, будзільнік, напамін, гадзіннік"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Уключыць"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Уключэнне рэжыму \"Не турбаваць\""</string>
@@ -569,6 +568,8 @@
<string name="user_nickname" msgid="262624187455825083">"Псеўданім"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Дадаць госця"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Выдаліць госця"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Госць"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Зрабіць фота"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Выбраць відарыс"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 4d92282..09e5843 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Псевдоним"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Добавяне на гост"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Премахване на госта"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Гост"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Правене на снимка"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Избиране на изображение"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index b7fdef2..26ad54a 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"অ্যালার্ম এবং রিমাইন্ডার"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"অ্যালার্ম এবং রিমাইন্ডার সেট করার অনুমতি দিন"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"অ্যালার্ম এবং রিমাইন্ডার"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"অ্যালার্ম এবং সময়ের মধ্যে শেষ করতে হবে এমন অ্যাকশনের শিডিউল সেট করতে এই অ্যাপকে অনুমতি দিন। এর ফলে ব্যাকগ্রাউন্ডে অ্যাপ চলতে পারে, যার জন্য আরও ব্যাটারির চার্জ খরচ হতে পারে।\n\nএই অনুমতি বন্ধ করা থাকলে, আগে থেকে থাকা অ্যালার্ম এবং অ্যাপের মাধ্যমে শিডিউল করা সময় ভিত্তিক ইভেন্টের রিমাইন্ডার কাজ করবে না।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"শিডিউল, অ্যালার্ম, রিমাইন্ডার, ঘড়ি"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"চালু করুন"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'বিরক্ত করবে না\' মোড চালু করুন"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"বিশেষ নাম"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ করুন"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি সরান"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ফটো তুলুন"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"একটি ইমেজ বেছে নিন"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index d3049b1..88abe33 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -567,6 +567,8 @@
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Snimite fotografiju"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberite sliku"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index eab1cd2..f499ab6 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Àlies"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Afegeix un convidat"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Suprimeix el convidat"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Convidat"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fes una foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Tria una imatge"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 7376d7ee..4d07eff 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -568,6 +568,8 @@
<string name="user_nickname" msgid="262624187455825083">"Přezdívka"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Přidat hosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odstranit hosta"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Host"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Pořídit fotku"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Vybrat obrázek"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 1dc2d14..c169d76 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Kaldenavn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Tilføj gæst"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gæsten"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gæst"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tag et billede"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Vælg et billede"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index f092a51..5808b6d 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wecker und Erinnerungen"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Erlauben, Wecker und Erinnerungen einzurichten"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wecker und Erinnerungen"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dieser App erlauben, Wecker zu stellen und zeitgebundene Aktionen zu planen. Dadurch läuft die App im Hintergrund. Dies kann den Akkuverbrauch erhöhen. \n\nWenn diese Berechtigung deaktiviert ist, funktionieren bereits gestellte Wecker und zeitgebundene Ereignisse, die von dieser App geplant sind, nicht wie erwartet."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planen, Wecker, Erinnerung, Uhr"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivieren"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"„Bitte nicht stören“ aktivieren"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Alias"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Gast hinzufügen"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Gast entfernen"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gast"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Foto machen"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Bild auswählen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 5d4301c..98f5301 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Ξυπνητήρια και ειδοποιήσεις"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Να επιτρέπεται ο ορισμός ξυπνητ. και υπενθυμίσεων"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ξυπνητήρια και υπενθυμίσεις"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Επιτρέψτε σε αυτήν την εφαρμογή να ορίζει ξυπνητήρια και να προγραμματίζει ενέργειες που εξαρτώνται από τον χρόνο. Αυτό επιτρέπει στην εφαρμογή να εκτελείται στο παρασκήνιο και, ως εκ τούτου, μπορεί να καταναλώνει περισσότερη μπαταρία.\n\nΑν αυτή η άδεια δεν είναι ενεργή, τα υπάρχοντα ξυπνητήρια και συμβάντα βάσει χρόνου που έχουν προγραμματιστεί από αυτήν την εφαρμογή δεν θα λειτουργούν."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"χρονοδιάγραμμα, ξυπνητήρι, υπενθύμιση, ρολόι"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ενεργοποίηση"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ενεργοποίηση λειτουργίας \"Μην ενοχλείτε\""</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Ψευδώνυμο"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Προσθήκη επισκέπτη"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Κατάργηση επισκέπτη"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Επισκέπτης"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Λήψη φωτογραφίας"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Επιλογή εικόνας"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 02317ea..03004a1 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -566,6 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Reset guest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Guest"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index f15db49..42a714d 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -566,6 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Reset guest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Guest"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 02317ea..03004a1 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -566,6 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Reset guest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Guest"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 02317ea..03004a1 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -566,6 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Reset guest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Guest"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index ce5a6bc..fafc76d 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -566,6 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Reset guest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Guest"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index d050ff8..5d0a61a 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmas y recordatorios"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir configuración de alarmas y recordatorios"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas y recordatorios"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta app establezca alarmas y programe acciones para horarios específicos. De esta manera, la app puede ejecutarse en segundo plano, lo que podría aumentar el consumo de batería.\n\nSi se desactiva este permiso, no funcionarán las alarmas ni los eventos basados en el tiempo existentes que programe esta app."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarma, recordatorio, reloj"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activar No interrumpir"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Sobrenombre"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Agregar invitado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Invitado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tomar una foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Elegir una imagen"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 540a472..6ff4854 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Apodo"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Añadir invitado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Invitado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Hacer foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Seleccionar una imagen"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index f740cc5..ef7b7db 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Hüüdnimi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lisa külaline"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Eemalda külaline"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Külaline"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Pildistage"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Valige pilt"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 06e1abd..9350610 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Goitizena"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Gehitu gonbidatua"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Kendu gonbidatua"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gonbidatua"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Atera argazki bat"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Aukeratu irudi bat"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 92e624d..eb68f5f 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"نام مستعار"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"افزودن مهمان"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"حذف مهمان"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"مهمان"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"عکس گرفتن"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"انتخاب تصویر"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 11bcb3a..964162b 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Herätykset ja muistutukset"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Salli herätysten ja muistutusten lisääminen"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Herätykset ja muistutukset"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Anna sovelluksen lisätä herätyksiä ja ajoittaa kiireellisiä tapahtumia. Näin sovellus voi toimia taustalla, mikä voi kuluttaa enemmän virtaa.\n\nIlman tätä lupaa sovelluksen ajoittamat herätykset ja aikaan perustuvat tapahtumat eivät toimi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ajoitus, herätys, muistutus, kello"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ota käyttöön"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ota Älä häiritse ‑tila käyttöön"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Lempinimi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lisää vieras"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Poista vieras"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Vieras"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ota kuva"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Valitse kuva"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index a622385..551dc36 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Pseudo"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Supprimer l\'invité"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Invité"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Prendre une photo"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Sélectionner une image"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index c4797fc..5ade70f 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Pseudo"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Supprimer l\'invité"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Invité"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Prendre une photo"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Choisir une image"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 0d009de..73f98ec 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmas e recordatorios"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir axuste de alarmas e recordatorios"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas e recordatorios"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta aplicación defina alarmas e planifique accións que dependan da hora. Con este permiso, a aplicación pode executarse en segundo plano, o que pode provocar un maior consumo de batería.\n\nSe este permiso está desactivado, non funcionarán as alarmas que xa se definisen nin os eventos que dependan da hora planificados por esta aplicación."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planificar, alarma, recordatorio, reloxo"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activar modo Non molestar"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Alcume"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Engadir convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar convidado"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escoller imaxe"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index b8d8f35..b55a5a2 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"અલાર્મ અને રિમાઇન્ડર"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"અલાર્મ અને રિમાન્ડરના સેટિંગની મંજૂરી આપો"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"અલાર્મ અને રિમાઇન્ડર"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"આ ઍપને અલાર્મ સેટ કરવા અને સમય પ્રતિ સંવેદનશીલ ક્રિયાઓ શેડ્યૂલ કરવા માટે મંજૂરી આપો. આ ઍપને બૅકગ્રાઉન્ડમાં ચાલવા દે છે, જેને કારણે બૅટરીનો વધુ વપરાશ થઈ શકે છે.\n\nજો આ પરવાનગી બંધ હોય, તો આ ઍપ દ્વારા શેડ્યૂલ કરવામાં આવેલા વર્તમાન અલાર્મ અને સમય આધારિત ઇવેન્ટ કામ કરશે નહીં."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"શેડ્યૂલ, અલાર્મ, રિમાઇન્ડર, ઘડિયાળ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ચાલુ કરો"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"ખલેલ પાડશો નહીં ચાલુ કરો"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"ઉપનામ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"અતિથિ ઉમેરો"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"અતિથિને કાઢી નાખો"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"અતિથિ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ફોટો લો"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"છબી પસંદ કરો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 8abbfcf..5620d94 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"प्रचलित नाम"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"मेहमान जोड़ें"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"मेहमान हटाएं"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"मेहमान"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"फ़ोटो खींचें"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"कोई इमेज चुनें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 217ff15..0ff35f8 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -567,6 +567,8 @@
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodavanje gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Uklanjanje gosta"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotografiraj"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberi sliku"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index e75b0dd..9bd4d12 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Becenév"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Vendég hozzáadása"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Vendég munkamenet eltávolítása"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Vendég"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotó készítése"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Kép kiválasztása"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 44b322d..fcd3c87 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Կեղծանուն"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Ավելացնել հյուր"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Հեռացնել հյուրին"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Հյուր"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Լուսանկարել"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Ընտրել պատկեր"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 4bb4724..f67c068 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Nama panggilan"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Tambahkan tamu"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Hapus tamu"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Tamu"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ambil foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Pilih gambar"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index b224330..662a673 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Vekjarar og áminningar"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Leyfa stillingu vekjara og áminninga"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Vekjarar og áminningar"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Leyfa þessu forriti að stilla vekjara og áætla aðgerðir sem þurfa að eiga sér stað innan ákveðins tímaramma. Þetta leyfir forritinu að keyra í bakgrunninum sem getur notað meiri rafhlöðuorku.\n\nEf slökkt er á þessari heimild munu núverandi vekjarar og tímasettir viðburðir sem þetta forrit stillir ekki virka."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"áætlun, vekjari, áminning, klukka"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Kveikja"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Kveikja á „Ónáðið ekki“"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Gælunafn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Bæta gesti við"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjarlægja gest"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gestur"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Taka mynd"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Velja mynd"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 1d2295c..2c2d11f 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Aggiungi ospite"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Rimuovi ospite"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Ospite"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Scatta una foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Scegli un\'immagine"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 5c894a1..dc48362 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -568,6 +568,8 @@
<string name="user_nickname" msgid="262624187455825083">"כינוי"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"הוספת אורח"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"הסרת אורח/ת"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"אורח"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"צילום תמונה"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"לבחירת תמונה"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 3f23c75e..7e9949f 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"ニックネーム"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ゲストを追加"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ゲストを削除"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"ゲスト"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"写真を撮る"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"画像を選択"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 4723771..eef252a 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"მეტსახელი"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"სტუმრის დამატება"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"სტუმრის ამოშლა"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"სტუმარი"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ფოტოს გადაღება"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"აირჩიეთ სურათი"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index baae75b..ddae3c7 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Лақап ат"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Қонақ қосу"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Қонақты жою"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Қонақ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Фотосуретке түсіру"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Сурет таңдау"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index fdbcba4..d970e95 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"ឈ្មោះហៅក្រៅ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"បញ្ចូលភ្ញៀវ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ដកភ្ញៀវចេញ"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"ភ្ញៀវ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ថតរូប"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ជ្រើសរើសរូបភាព"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 21dce27..8bad320 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ಅಲಾರಾಮ್ಗಳು ಮತ್ತು ರಿಮೈಂಡರ್ಗಳು"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ಅಲಾರಂಗಳು ಮತ್ತು ರಿಮೈಂಡರ್ಗಳನ್ನು ಹೊಂದಿಸಲು ಅನುಮತಿಸಿ"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ಅಲಾರಂಗಳು ಮತ್ತು ರಿಮೈಂಡರ್ಗಳು"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ಅಲಾರಂಗಳನ್ನು ಹೊಂದಿಸಲು ಮತ್ತು ಸಮಯ-ಸೂಕ್ಷ್ಮವಾದ ಕ್ರಿಯೆಗಳನ್ನು ನಿಗದಿಪಡಿಸಲು ಈ ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸಿ. ಇದು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ, ಅದರಿಂದ ಹೆಚ್ಚು ಬ್ಯಾಟರಿ ಬಳಕೆಯಾಗಬಹುದು.\n\nಈ ಅನುಮತಿ ಆಫ್ ಆಗಿದ್ದರೆ, ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಅಲಾರಂಗಳು ಮತ್ತು ಈ ಆ್ಯಪ್ ನಿಗದಿಪಡಿಸಿದ ಸಮಯ-ಸೂಕ್ಷ್ಮ ಈವೆಂಟ್ಗಳು ಕೆಲಸ ಮಾಡುವುದಿಲ್ಲ."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ವೇಳಾಪಟ್ಟಿ, ಅಲಾರಂ, ರಿಮೈಂಡರ್, ಗಡಿಯಾರ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ಆನ್ ಮಾಡಿ"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಅನ್ನು ಆನ್ ಮಾಡಿ"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"ಅಡ್ಡ ಹೆಸರು"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ಅತಿಥಿಯನ್ನು ಸೇರಿಸಿ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ಅತಿಥಿಯನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"ಅತಿಥಿ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ಫೋಟೋ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ಚಿತ್ರವನ್ನು ಆರಿಸಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 6e6a5a7..5927071 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"닉네임"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"게스트 추가"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"게스트 삭제"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"게스트"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"사진 찍기"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"이미지 선택"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 140eb3b..618b7db 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Ылакап аты"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Конок кошуу"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Конокту өчүрүү"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Конок"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Сүрөткө тартуу"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Сүрөт тандаңыз"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index f4962f9..bf6c2a3 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ໂມງປຸກ ແລະ ການແຈ້ງເຕືອນ"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ອະນຸຍາດໃຫ້ຕັ້ງໂມງປຸກ ແລະ ການແຈ້ງເຕືອນ"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ໂມງປຸກ ແລະ ການແຈ້ງເຕືອນ"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ອະນຸຍາດໃຫ້ແອັບນີ້ຕັ້ງໂມງປຸກ ແລະ ກຳນົດເວລາຄຳສັ່ງທີ່ເນັ້ນເລື່ອງເວລາເປັນສຳຄັນໄດ້. ນີ້ຈະເຮັດໃຫ້ແອັບເຮັດວຽກໄດ້ໃນພື້ນຫຼັງ, ເຊິ່ງອາດໃຊ້ແບັດເຕີຣີຫຼາຍຂຶ້ນ.\n\nຫາກປິດການອະນຸຍາດນີ້ໄວ້, ໂມງປຸກທີ່ມີຢູ່ກ່ອນແລ້ວ ແລະ ເຫດການທີ່ອ້າງອີງເວລາທີ່ກຳນົດໄວ້ໂດຍແອັບນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ກຳນົດເວລາ, ໂມງປຸກ, ການແຈ້ງເຕືອນ, ໂມງ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ເປີດ"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"ເປີດໂໝດຫ້າມລົບກວນ"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"ຊື່ຫຼິ້ນ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ເພີ່ມແຂກ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ລຶບແຂກອອກ"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"ແຂກ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ຖ່າຍຮູບ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ເລືອກຮູບ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index e920b31..3383602 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -568,6 +568,8 @@
<string name="user_nickname" msgid="262624187455825083">"Slapyvardis"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pridėti svečią"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Pašalinti svečią"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Svečias"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotografuoti"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Pasirinkti vaizdą"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index c43d879..d655afc 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -567,6 +567,8 @@
<string name="user_nickname" msgid="262624187455825083">"Segvārds"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pievienot viesi"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Noņemt viesi"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Viesis"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Uzņemt fotoattēlu"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Izvēlēties attēlu"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 81f75c5..bd7f074 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Прекар"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додајте гостин"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Отстрани гостин"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Гостин"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Фотографирајте"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Одберете слика"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 9583b50..1e80ccd 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"വിളിപ്പേര്"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"അതിഥിയെ ചേർക്കുക"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"അതിഥിയെ നീക്കം ചെയ്യുക"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"അതിഥി"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ഒരു ഫോട്ടോ എടുക്കുക"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ഒരു ചിത്രം തിരഞ്ഞെടുക്കുക"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 955937b..40b65ef 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Хоч"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Зочин нэмэх"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Зочин хасах"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Зочин"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Зураг авах"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Зураг сонгох"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 8ddb298..6a46ede 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"अलार्म आणि रिमाइंडर"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म आणि रिमाइंडर सेट करण्याची अनुमती द्या"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म आणि रिमाइंडर"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"या ॲपला अलार्म सेट करण्याची किंवा वेळेनुसार संवेदनशील असलेल्या कृती शेड्युल करण्याची अनुमती द्या. हे ॲपला बॅकग्राउंडमध्ये रन होऊ देते, ज्यामुळे जास्त बॅटरी वापरली जाऊ शकते.\n\nही परवानगी बंद असल्यास, सध्याचे अलार्म आणि या ॲपद्वारे शेड्युल केलेले वेळेवर आधारित इव्हेंट काम करणार नाहीत."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"शेड्युल, अलार्म, रिमाइंडर, घड्याळ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"सुरू करा"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"व्यत्यय आणू नका सुरू करा"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"टोपणनाव"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"अतिथी जोडा"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"अतिथी काढून टाका"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"अतिथी"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"फोटो काढा"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"इमेज निवडा"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 13788c4..77006fc 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Nama panggilan"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Tambah tetamu"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Alih keluar tetamu"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Tetamu"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ambil foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Pilih imej"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index dac55c5..7156a8e 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"နာမည်ပြောင်"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ဧည့်သည့် ထည့်ရန်"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ဧည့်သည်ကို ဖယ်ထုတ်ရန်"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"ဧည့်သည်"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ဓာတ်ပုံရိုက်ရန်"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ပုံရွေးရန်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 769b468..bb93a29 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Kallenavn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Legg til en gjest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gjesten"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gjest"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ta et bilde"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Velg et bilde"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 0bf1a78..a54fc0c8 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"अलार्म र रिमाइन्डरहरू"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म तथा रिमाइन्डर सेट गर्न दिइयोस्"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"घडी तथा रिमाइन्डरहरू"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"यो एपलाई अलार्म सेट गर्ने र समयमै पूरा गर्नु पर्ने कारबाहीहरूको रुटिन तय गर्ने अनुमति दिनुहोस्। यो अनुमति दिइएको छ भने यो एप ब्याकग्राउन्डमा यसले चलेर धेरै ब्याट्री खपत गर्न सक्छ।\n\nयो अनुमति दिइएको छैन भने समय तोकिएका अलार्म र यो एपले तय गरेका समयअनुसार चल्ने कार्यक्रमले काम गर्दैन।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"समयतालिका, अलार्म, रिमाइन्डर, घडी"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"सक्रिय गर्नुहोस्"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"बाधा नपुऱ्याउनुहोस् नामक मोडलाई सक्रिय गर्नुहोस्"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"उपनाम"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"अतिथि थप्नुहोस्"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"अतिथि हटाउनुहोस्"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"अतिथि"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"फोटो खिच्नुहोस्"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"कुनै फोटो छनौट गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index ca4308c..a33bbf3 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Bijnaam"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Gast toevoegen"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Gast verwijderen"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gast"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Foto maken"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Afbeelding kiezen"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 21bd1ad..6cc3cc5 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ଆଲାରାମ୍ ଏବଂ ରିମାଇଣ୍ଡରଗୁଡ଼ିକ"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ଆଲାରାମ ଓ ରିମାଇଣ୍ଡରଗୁଡ଼ିକ ସେଟ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ଆଲାରାମ୍ ଏବଂ ରିମାଇଣ୍ଡରଗୁଡ଼ିକ"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ଏହି ଆପକୁ ଆଲାରାମ୍ ସେଟ୍ କରିବାକୁ ଏବଂ ସମୟ-ସମ୍ବେଦନଶୀଳ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ସିଡୁଲ୍ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ। ଏହା ଆପକୁ ପୃଷ୍ଠପଟରେ ଚାଲିବାକୁ ଦେଇଥାଏ, ଯାହା ଅଧିକ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରିପାରେ।\n\nଯଦି ଏହି ଅନୁମତି ବନ୍ଦ ଅଛି, ତେବେ ଏହି ଆପ୍ ଦ୍ୱାରା ସିଡୁଲ୍ କରାଯାଇଥିବା ପୂର୍ବରୁ ଥିବା ଆଲାରାମ୍ ଏବଂ ସମୟ-ଆଧାରିତ ଇଭେଣ୍ଟଗୁଡ଼ିକ କାମ କରିବ ନାହିଁ।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ସିଡୁଲ୍, ଆଲାରାମ୍, ରିମାଇଣ୍ଡର୍, ଘଣ୍ଟା"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ଚାଲୁ କରନ୍ତୁ"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ଅନ୍ କରନ୍ତୁ"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"ଡାକନାମ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ଅତିଥି ଯୋଗ କରନ୍ତୁ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ଅତିଥିଙ୍କୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"ଅତିଥି"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ଗୋଟିଏ ଫଟୋ ଉଠାନ୍ତୁ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ଏକ ଛବି ବାଛନ୍ତୁ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index aaa892a..0af4990 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ ਸੈੱਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ਇਸ ਐਪ ਨੂੰ ਅਲਾਰਮ ਸੈੱਟ ਕਰਨ ਜਾਂ ਹੋਰ ਸਮਾਂ-ਸੰਵੇਦਨਸ਼ੀਲ ਕਾਰਵਾਈਆਂ ਨੂੰ ਨਿਯਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ। ਇਸ ਨਾਲ ਐਪ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚਲਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਮਿਲਦੀ ਹੈ, ਜੋ ਵੱਧ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੀ ਹੈ।\n\nਜੇ ਇਹ ਇਜਾਜ਼ਤ ਬੰਦ ਹੈ, ਤਾਂ ਮੌਜੂਦਾ ਅਲਾਰਮ ਅਤੇ ਇਸ ਐਪ ਰਾਹੀਂ ਸਮਾਂ ਨਿਯਤ ਕੀਤੇ ਸਮਾਂ-ਆਧਾਰਿਤ ਇਵੈਂਟਾਂ ਕੰਮ ਨਹੀਂ ਕਰਨਗੇ।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ਸਮਾਂ-ਸੂਚੀ, ਅਲਾਰਮ, ਰਿਮਾਈਂਡਰ, ਘੜੀ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ਚਾਲੂ ਕਰੋ"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"ਉਪਨਾਮ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ਮਹਿਮਾਨ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ਮਹਿਮਾਨ ਹਟਾਓ"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"ਮਹਿਮਾਨ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ਇੱਕ ਫ਼ੋਟੋ ਖਿੱਚੋ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ਕੋਈ ਚਿੱਤਰ ਚੁਣੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 99faea7..5f410a8 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -568,6 +568,8 @@
<string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gościa"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Usuń gościa"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gość"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Zrób zdjęcie"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Wybierz obraz"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 021a75e..3c8d928 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Apelido"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index cdea8b2..fc98aa7 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Alcunha"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 021a75e..3c8d928 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Apelido"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index e02bada..4db2f31 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -567,6 +567,8 @@
<string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adăugați un invitat"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ștergeți invitatul"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Invitat"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Faceți o fotografie"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Alegeți o imagine"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 923917b..0bcdc23 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -568,6 +568,8 @@
<string name="user_nickname" msgid="262624187455825083">"Псевдоним"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Добавить гостя"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Удалить аккаунт гостя"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Гость"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Сделать снимок"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Выбрать фото"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 3c79bf3..a385055 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"අපනාමය"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"අමුත්තා එක් කරන්න"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"අමුත්තා ඉවත් කරන්න"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"අමුත්තා"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ඡායාරූපයක් ගන්න"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"රූපයක් තෝරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 5be0d99..ef12ad3 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -568,6 +568,8 @@
<string name="user_nickname" msgid="262624187455825083">"Prezývka"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pridať hosťa"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odobrať hosťa"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Hosť"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Odfotiť"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Vybrať obrázok"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 07e367b..cbdfefc 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -568,6 +568,8 @@
<string name="user_nickname" msgid="262624187455825083">"Vzdevek"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodajanje gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odstranitev gosta"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotografiranje"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Izberi sliko"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 1f30a02..ba744360 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmet dhe alarmet rikujtuese"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Lejo caktimin e alarmeve dhe alarmeve rikujtuese"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmet dhe alarmet rikujtuese"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lejo që ky aplikacion të caktojë alarmet dhe të planifikojë veprime që kanë një afat të caktuar. Kjo lejon që aplikacioni të ekzekutohet në sfond, gjë që mund të përdorë më shumë bateri.\n\nNëse kjo leje është caktuar si joaktive, alarmet ekzistuese dhe ngjarjet me bazë kohore të planifikuara nga ky apliikacion nuk do të funksionojnë."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planifiko, alarm, alarm rikujtues, ora"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivizo"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktivizo \"Mos shqetëso\""</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Pseudonimi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Shto të ftuar"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Hiq të ftuarin"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"I ftuar"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Bëj një fotografi"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Zgjidh një imazh"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 11adbe5..3859be9 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -567,6 +567,8 @@
<string name="user_nickname" msgid="262624187455825083">"Надимак"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додај госта"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Уклони госта"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Гост"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Сликај"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Одабери слику"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index f4b92af..7dcca0d 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Smeknamn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lägg till gäst"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ta bort gäst"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Gäst"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ta ett foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Välj en bild"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 2625a414..332cd9d 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Jina wakilishi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Ongeza mgeni"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ondoa mgeni"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Mgeni"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Piga picha"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Chagua picha"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 612fd70..7952a76 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -567,6 +567,8 @@
<string name="user_nickname" msgid="262624187455825083">"புனைப்பெயர்"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"கெஸ்ட்டைச் சேர்"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"கெஸ்ட்டை அகற்று"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"கெஸ்ட்"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"படமெடுங்கள்"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"படத்தைத் தேர்வுசெய்யுங்கள்"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 7f596e3..da0380d 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"అలారాలు, రిమైండర్లు"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"అలారాలు, రిమైండర్లను సెట్ చేయడానికి అనుమతించండి"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"అలారాలు & రిమైండర్లు"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"అలారాలను సెట్ చేయడానికి, సమయ-సునిశిత చర్యలను షెడ్యూల్ చేయడానికి ఈ యాప్ను అనుమతించండి. ఇది యాప్ను బ్యాక్గ్రౌండ్లో రన్ అవడానికి అనుమతిస్తుంది, ఇది ఎక్కువ బ్యాటరీని ఉపయోగించవచ్చు.\n\nఈ అనుమతిని ఆఫ్ చేస్తే, ఈ యాప్ ద్వారా షెడ్యూల్ చేసిన ఇప్పటికే ఉన్న అలారాలు, సమయ-ఆధారిత ఈవెంట్లు పనిచేయవు."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"షెడ్యూల్, అలారం, రిమైండర్, గడియారం"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ఆన్ చేయండి"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"అంతరాయం కలిగించవద్దును ఆన్ చేయండి"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"మారుపేరు"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"గెస్ట్ను జోడించండి"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"గెస్ట్ను తీసివేయండి"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"గెస్ట్"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ఒక ఫోటో తీయండి"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ఇమేజ్ను ఎంచుకోండి"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 3851ccb..b7aff72 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"ชื่อเล่น"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"เพิ่มผู้ใช้ชั่วคราว"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"นำผู้ใช้ชั่วคราวออก"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"ผู้ใช้ชั่วคราว"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ถ่ายรูป"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"เลือกรูปภาพ"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index a381c35..6d1f6ab 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Magdagdag ng bisita"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Alisin ang bisita"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Bisita"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Kumuha ng larawan"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Pumili ng larawan"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 03efe82..36144eb 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Takma ad"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Misafir ekle"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Misafir oturumunu kaldır"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Misafir"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotoğraf çek"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Resim seç"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index e737c7d..82e481b 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -568,6 +568,8 @@
<string name="user_nickname" msgid="262624187455825083">"Псевдонім"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додати гостя"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Видалити гостя"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Гість"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Зробити фотографію"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Вибрати зображення"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 45e9f4f..d0ed2ab 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -507,8 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"الارمز اور یاد دہانیاں"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"الارمز اور یاد دہانیاں سیٹ کرنے کی اجازت دیں"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"الارمز اور یاد دہانیاں"</string>
- <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
- <skip />
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"اس ایپ کو الارمز سیٹ کرنے اور متعین وقت کے لحاظ سے حساس کارروائیوں کو شیڈول کرنے کی اجازت دیں۔ یہ ایپ کو پس منظر میں چلنے دیتا ہے، جس میں زیادہ بیٹری استعمال ہو سکتی ہے۔\n\n اگر یہ اجازت آف ہے تو موجودہ الارمز اور اس ایپ کے ذریعے شیڈول کردہ وقت پر مبنی ایونٹس کام نہیں کریں گے۔"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"شیڈول، الارم، یاد دہانی، گھڑی"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"آن کریں"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'ڈسٹرب نہ کریں\' کو آن کریں"</string>
@@ -567,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"عرفی نام"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"مہمان کو شامل کریں"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"مہمان کو ہٹائیں"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"مہمان"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ایک تصویر لیں"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ایک تصویر منتخب کریں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 96b8853..7f4e30a 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Nik"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Mehmon kiritish"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Mehmonni olib tashlash"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Mehmon"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Suratga olish"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Rasm tanlash"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 4509430..0fba1ec 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Biệt hiệu"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Thêm khách"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Xóa phiên khách"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Khách"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Chụp ảnh"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Chọn một hình ảnh"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 3e6b3c2..d226f01 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -507,7 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"闹钟和提醒"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"允许设置闹钟和提醒"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"闹钟和提醒"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"允许该应用设置闹钟以及安排在特定时间执行某些操作。如此一来,该应用将在后台运行,而这可能会消耗更多电池电量。\n\n如果您关闭了此权限,该应用设置的现有闹钟将不会响起,而且该应用安排在特定时间执行的现有活动也不会执行。"</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"允许该应用设置闹钟以及安排在特定时间执行某些操作。这项权限开启后,该应用将在后台运行,可能会消耗更多电池电量。\n\n如果您关闭此权限,该应用设置的现有闹钟将不会响起,而且该应用安排在特定时间执行的现有活动也不会执行。"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"设置, 闹钟, 提醒, 时钟, schedule, alarm, reminder, clock"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"开启"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"开启勿扰模式"</string>
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"昵称"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"添加访客"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"移除访客"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"访客"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"拍摄照片"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"选择图片"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 42d95b7..642dd1d 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"暱稱"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"移除訪客"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"訪客"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"拍照"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"選擇圖片"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 20fa187..1cab0af 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"暱稱"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"移除訪客"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"訪客"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"拍照"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"選擇圖片"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index f49d3cc9..2fe791a 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -566,6 +566,8 @@
<string name="user_nickname" msgid="262624187455825083">"Isiteketiso"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Engeza isivakashi"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Susa isihambeli"</string>
+ <!-- no translation found for guest_reset_guest (6110013010356013758) -->
+ <skip />
<string name="guest_nickname" msgid="6332276931583337261">"Isihambeli"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Thatha isithombe"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Khetha isithombe"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 603d093..8651595 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1422,6 +1422,8 @@
<string name="guest_new_guest">Add guest</string>
<!-- Label for exiting and removing the guest session in the user switcher [CHAR LIMIT=35] -->
<string name="guest_exit_guest">Remove guest</string>
+ <!-- Label for resetting guest session in the user switcher, which will remove all data from the current guest session [CHAR LIMIT=35] -->
+ <string name="guest_reset_guest">Reset guest</string>
<!-- Name for the guest user [CHAR LIMIT=35] -->
<string name="guest_nickname">Guest</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.java
index a537394..0b3a519 100644
--- a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.java
@@ -16,8 +16,10 @@
package com.android.settingslib.enterprise;
+import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.Context;
+import android.content.DialogInterface;
import androidx.annotation.Nullable;
@@ -54,4 +56,13 @@
* Updates the enforced admin
*/
void updateEnforcedAdmin(RestrictedLockUtils.EnforcedAdmin admin, @UserIdInt int adminUserId);
+
+ /**
+ * Returns a listener for handling positive button clicks
+ */
+ @Nullable
+ default DialogInterface.OnClickListener getPositiveButtonListener(@NonNull Context context,
+ @NonNull RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
+ return null;
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java
index da42e33..44cafb1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java
@@ -20,6 +20,11 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.ParentalControlsUtilsInternal;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.text.TextUtils;
/**
* A factory that returns the relevant instance of {@link ActionDisabledByAdminController}.
@@ -30,10 +35,28 @@
* Returns the relevant instance of {@link ActionDisabledByAdminController}.
*/
public static ActionDisabledByAdminController createInstance(Context context,
- DeviceAdminStringProvider stringProvider) {
- return isFinancedDevice(context)
- ? new FinancedDeviceActionDisabledByAdminController(stringProvider)
- : new ManagedDeviceActionDisabledByAdminController(stringProvider);
+ String restriction, DeviceAdminStringProvider stringProvider) {
+ if (doesBiometricRequireParentalConsent(context, restriction)) {
+ return new BiometricActionDisabledByAdminController(stringProvider);
+ } else if (isFinancedDevice(context)) {
+ return new FinancedDeviceActionDisabledByAdminController(stringProvider);
+ } else {
+ return new ManagedDeviceActionDisabledByAdminController(stringProvider);
+ }
+ }
+
+ /**
+ * @return true if the restriction == UserManager.DISALLOW_BIOMETRIC and parental consent
+ * is required.
+ */
+ private static boolean doesBiometricRequireParentalConsent(Context context,
+ String restriction) {
+ if (!TextUtils.equals(UserManager.DISALLOW_BIOMETRIC, restriction)) {
+ return false;
+ }
+ DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ return ParentalControlsUtilsInternal.parentConsentRequired(context, dpm,
+ BiometricAuthenticator.TYPE_ANY_BIOMETRIC, new UserHandle(UserHandle.myUserId()));
}
private static boolean isFinancedDevice(Context context) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java
new file mode 100644
index 0000000..814d5d2
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java
@@ -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.settingslib.enterprise;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import com.android.settingslib.RestrictedLockUtils;
+
+public class BiometricActionDisabledByAdminController extends BaseActionDisabledByAdminController {
+
+ private static final String TAG = "BiometricActionDisabledByAdminController";
+
+ // These MUST not change, as they are the stable API between here and device admin specified
+ // by the component below.
+ private static final String ACTION_LEARN_MORE = "android.settings.LEARN_MORE";
+ private static final String EXTRA_FROM_BIOMETRIC_SETUP = "from_biometric_setup";
+
+ BiometricActionDisabledByAdminController(
+ DeviceAdminStringProvider stringProvider) {
+ super(stringProvider);
+ }
+
+ @Override
+ public void setupLearnMoreButton(Context context) {
+
+ }
+
+ @Override
+ public String getAdminSupportTitle(@Nullable String restriction) {
+ return mStringProvider.getDisabledBiometricsParentConsentTitle();
+ }
+
+ @Override
+ public CharSequence getAdminSupportContentString(Context context,
+ @Nullable CharSequence supportMessage) {
+ return mStringProvider.getDisabledBiometricsParentConsentContent();
+ }
+
+ @Override
+ public DialogInterface.OnClickListener getPositiveButtonListener(@NonNull Context context,
+ @NonNull RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
+ return (dialog, which) -> {
+ Log.d(TAG, "Positive button clicked, component: " + enforcedAdmin.component);
+ final Intent intent = new Intent(ACTION_LEARN_MORE)
+ .setComponent(enforcedAdmin.component)
+ .putExtra(EXTRA_FROM_BIOMETRIC_SETUP, true)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ };
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java
index c47d789..b83837e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java
@@ -72,4 +72,14 @@
* a financed device.
*/
String getDisabledByPolicyTitleForFinancedDevice();
+
+ /**
+ * Returns the dialog title for when biometrics require parental consent.
+ */
+ String getDisabledBiometricsParentConsentTitle();
+
+ /**
+ * Returns the dialog contents for when biometrics require parental consent.
+ */
+ String getDisabledBiometricsParentConsentContent();
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminControllerTest.java
new file mode 100644
index 0000000..766c2f5
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminControllerTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.settingslib.enterprise;
+
+import static com.android.settingslib.enterprise.ActionDisabledByAdminControllerTestUtils.ENFORCED_ADMIN;
+import static com.android.settingslib.enterprise.ActionDisabledByAdminControllerTestUtils.ENFORCEMENT_ADMIN_USER_ID;
+import static com.android.settingslib.enterprise.FakeDeviceAdminStringProvider.DEFAULT_DEVICE_ADMIN_STRING_PROVIDER;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.UserHandle;
+
+import com.android.settingslib.RestrictedLockUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class BiometricActionDisabledByAdminControllerTest {
+
+ private final ActionDisabledByAdminControllerTestUtils mTestUtils =
+ new ActionDisabledByAdminControllerTestUtils();
+ private final BiometricActionDisabledByAdminController mController =
+ new BiometricActionDisabledByAdminController(DEFAULT_DEVICE_ADMIN_STRING_PROVIDER);
+
+ @Before
+ public void setUp() {
+ mController.initialize(mTestUtils.createLearnMoreButtonLauncher());
+ mController.updateEnforcedAdmin(ENFORCED_ADMIN, ENFORCEMENT_ADMIN_USER_ID);
+ }
+
+ @Test
+ public void buttonClicked() {
+ Context context = mock(Context.class);
+ ComponentName componentName = mock(ComponentName.class);
+ RestrictedLockUtils.EnforcedAdmin enforcedAdmin = new RestrictedLockUtils.EnforcedAdmin(
+ componentName, new UserHandle(UserHandle.myUserId()));
+
+ DialogInterface.OnClickListener listener =
+ mController.getPositiveButtonListener(context, enforcedAdmin);
+ assertNotNull("Biometric Controller must supply a non-null listener", listener);
+ listener.onClick(mock(DialogInterface.class), 0 /* which */);
+
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(context).startActivity(intentCaptor.capture());
+ assertEquals("android.settings.LEARN_MORE",
+ intentCaptor.getValue().getAction());
+ assertTrue("from_biometric_setup", intentCaptor.getValue()
+ .getBooleanExtra("from_biometric_setup", false));
+ assertEquals(componentName, intentCaptor.getValue().getComponent());
+ }
+
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java
index be3e9fc..99e13c3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java
@@ -30,6 +30,8 @@
static final String DEFAULT_DISABLED_BY_POLICY_CONTENT = "default_disabled_by_policy_content";
static final String DEFAULT_DISABLED_BY_POLICY_TITLE_FINANCED_DEVICE =
"default_disabled_by_policy_title_financed_device";
+ static final String DEFAULT_BIOMETRIC_TITLE = "biometric_title";
+ static final String DEFAULT_BIOMETRIC_CONTENTS = "biometric_contents";
static final DeviceAdminStringProvider DEFAULT_DEVICE_ADMIN_STRING_PROVIDER =
new FakeDeviceAdminStringProvider(/* url = */ null);
@@ -88,4 +90,15 @@
public String getDisabledByPolicyTitleForFinancedDevice() {
return DEFAULT_DISABLED_BY_POLICY_TITLE_FINANCED_DEVICE;
}
+
+ @Override
+ public String getDisabledBiometricsParentConsentTitle() {
+ return DEFAULT_BIOMETRIC_TITLE;
+ }
+
+ @Override
+ public String getDisabledBiometricsParentConsentContent() {
+ return DEFAULT_BIOMETRIC_CONTENTS;
+ }
+
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java
index 6670ed3..0a48f19 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java
@@ -20,7 +20,10 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.robolectric.Robolectric.setupActivity;
+import static org.robolectric.Shadows.shadowOf;
+import android.app.Activity;
import android.content.Context;
import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
@@ -44,8 +47,8 @@
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowDrawable;
+import org.robolectric.shadows.ShadowTouchDelegate;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
@@ -58,6 +61,9 @@
private boolean mClickListenerCalled = false;
private final View.OnClickListener mClickListener = v -> mClickListenerCalled = true;
+ private final int mMinimumTargetSize =
+ RuntimeEnvironment.application.getResources()
+ .getDimensionPixelSize(R.dimen.settingslib_preferred_minimum_touch_target);
private static final int TEST_STRING_RES_ID =
R.string.accessibility_banner_message_dismiss;
@@ -81,6 +87,23 @@
}
@Test
+ public void onBindViewHolder_andOnLayoutView_dismissButtonTouchDelegate_isCorrectSize() {
+ assumeAndroidS();
+ mBannerPreference.setTitle("Title");
+ mBannerPreference.setDismissButtonOnClickListener(mClickListener);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+ setupActivity(Activity.class).setContentView(mRootView);
+
+ assertThat(mRootView.getTouchDelegate()).isNotNull();
+ ShadowTouchDelegate delegate = shadowOf(mRootView.getTouchDelegate());
+ assertThat(delegate.getBounds().width()).isAtLeast(mMinimumTargetSize);
+ assertThat(delegate.getBounds().height()).isAtLeast(mMinimumTargetSize);
+ assertThat(delegate.getDelegateView())
+ .isEqualTo(mRootView.findViewById(R.id.banner_dismiss_btn));
+ }
+
+ @Test
public void onBindViewHolder_whenSummarySet_shouldSetSummary() {
mBannerPreference.setSummary("test");
@@ -157,7 +180,7 @@
mBannerPreference.onBindViewHolder(mHolder);
ImageView mIcon = mRootView.findViewById(R.id.banner_icon);
- ShadowDrawable shadowDrawable = Shadows.shadowOf(mIcon.getDrawable());
+ ShadowDrawable shadowDrawable = shadowOf(mIcon.getDrawable());
assertThat(shadowDrawable.getCreatedFromResId())
.isEqualTo(R.drawable.settingslib_ic_cross);
}
@@ -168,7 +191,7 @@
mBannerPreference.onBindViewHolder(mHolder);
ImageView mIcon = mRootView.findViewById(R.id.banner_icon);
- ShadowDrawable shadowDrawable = Shadows.shadowOf(mIcon.getDrawable());
+ ShadowDrawable shadowDrawable = shadowOf(mIcon.getDrawable());
assertThat(shadowDrawable.getCreatedFromResId()).isEqualTo(R.drawable.ic_warning);
}
@@ -478,11 +501,15 @@
private void assumeAndroidR() {
ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", 30);
+ ReflectionHelpers.setStaticField(Build.VERSION.class, "CODENAME", "R");
+ ReflectionHelpers.setStaticField(BannerMessagePreference.class, "IS_AT_LEAST_S", false);
// Reset view holder to use correct layout.
}
private void assumeAndroidS() {
ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", 31);
+ ReflectionHelpers.setStaticField(Build.VERSION.class, "CODENAME", "S");
+ ReflectionHelpers.setStaticField(BannerMessagePreference.class, "IS_AT_LEAST_S", true);
// Re-inflate view to update layout.
setUpViewHolder();
}
diff --git a/packages/Shell/res/values-az/strings.xml b/packages/Shell/res/values-az/strings.xml
index 15853c2..23a1ad7 100644
--- a/packages/Shell/res/values-az/strings.xml
+++ b/packages/Shell/res/values-az/strings.xml
@@ -35,7 +35,7 @@
<string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Zip faylı üçün baq hesabat detalları əlavə edilmədi"</string>
<string name="bugreport_unnamed" msgid="2800582406842092709">"adsız"</string>
<string name="bugreport_info_action" msgid="2158204228510576227">"Detallar"</string>
- <string name="bugreport_screenshot_action" msgid="8677781721940614995">"displey görüntüsü"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Skrinşot"</string>
<string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Displey görüntüsü uğurla çəkildi."</string>
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Displey görüntüsü əlçatan deyil."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Baq hesabatı <xliff:g id="ID">#%d</xliff:g> detalları"</string>
diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml
index b975521..816fe3b 100644
--- a/packages/Shell/res/values-iw/strings.xml
+++ b/packages/Shell/res/values-iw/strings.xml
@@ -29,7 +29,7 @@
<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_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>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index 1c99e53..8550164 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -22,16 +22,16 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="514691256816366517">"Teklatu-babeslea"</string>
<string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Idatzi PIN kodea"</string>
- <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Idatzi SIM txartelaren PUKa eta PIN berria"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Idatzi SIMaren PUKa eta PIN kode berria"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM txartelaren PUK kodea"</string>
- <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"SIM txartelaren PIN berria"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"SIMaren PIN kode berria"</string>
<string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Pasahitza idazteko, sakatu hau"</font></string>
<string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Idatzi desblokeatzeko pasahitza"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Idatzi desblokeatzeko PINa"</string>
<string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Idatzi PINa"</string>
<string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Marraztu eredua"</string>
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Idatzi pasahitza"</string>
- <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PINa ez da zuzena."</string>
+ <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN kodea okerra da."</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Txartelak ez du balio."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Kargatuta"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hari gabe kargatzen"</string>
@@ -128,8 +128,8 @@
<string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Ez da ezagutu"</string>
<string name="kg_face_not_recognized" msgid="7903950626744419160">"Ez da ezagutu"</string>
<plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
- <item quantity="other">Idatzi SIM txartelaren PIN kodea. <xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu.</item>
- <item quantity="one">Idatzi SIM txartelaren PIN kodea. <xliff:g id="NUMBER_0">%d</xliff:g> saiakera geratzen zaizu; oker idatziz gero, operadoreari eskatu beharko diozu gailua desblokeatzeko.</item>
+ <item quantity="other">Idatzi SIMaren PINa. <xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu.</item>
+ <item quantity="one">Idatzi SIMaren PINa. <xliff:g id="NUMBER_0">%d</xliff:g> saiakera geratzen zaizu; oker idatziz gero, operadoreari eskatu beharko diozu gailua desblokeatzeko.</item>
</plurals>
<plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935">
<item quantity="other">Desgaitu egin da SIM txartela. Aurrera egiteko, idatzi PUK kodea. <xliff:g id="_NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu SIM txartela betiko erabilgaitz geratu aurretik. Xehetasunak lortzeko, jarri operadorearekin harremanetan.</item>
diff --git a/packages/SystemUI/res/layout/global_actions_change_panel.xml b/packages/SystemUI/res/layout/global_actions_change_panel.xml
index dffb0f0..bc9c203 100644
--- a/packages/SystemUI/res/layout/global_actions_change_panel.xml
+++ b/packages/SystemUI/res/layout/global_actions_change_panel.xml
@@ -14,8 +14,18 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ImageView
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/global_actions_change_button"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/global_actions_change_message"
+ android:layout_width="wrap_content"
+ android:visibility="gone"
+ android:layout_height="wrap_content"
+ android:text="@string/global_actions_change_description" />
+ <ImageView
+ android:id="@+id/global_actions_change_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml
index 4765b44..3f4baaf 100644
--- a/packages/SystemUI/res/layout/long_screenshot.xml
+++ b/packages/SystemUI/res/layout/long_screenshot.xml
@@ -99,6 +99,7 @@
app:handleThickness="@dimen/screenshot_crop_handle_thickness"
app:handleColor="?androidprv:attr/colorAccentPrimary"
app:scrimColor="@color/screenshot_crop_scrim"
+ app:containerBackgroundColor="?android:colorBackgroundFloating"
tools:background="?android:colorBackground"
tools:minHeight="100dp"
tools:minWidth="100dp" />
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
index c88703d..5b9ca1b 100644
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
@@ -59,11 +59,16 @@
android:visibility="gone"
/>
- <LinearLayout
+ <FrameLayout
android:id="@+id/rightLayout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:gravity="center_vertical|end"
+ android:gravity="end"
+ >
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical|end"
>
<com.android.systemui.statusbar.phone.StatusIconContainer
android:id="@+id/statusIcons"
@@ -80,4 +85,6 @@
android:paddingEnd="2dp" />
</LinearLayout>
+ </FrameLayout>
+
</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 2149371..f8d06ce 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Voeg gebruiker by"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nuwe gebruiker"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Verwyder gas?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Stel gassessie terug?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle programme en data in hierdie sessie sal uitgevee word."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Verwyder"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Stel terug"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welkom terug, gas!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Wiil jy jou sessie voortsit?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Begin van voor af"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Vergroot \'n deel van die skerm"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Wissel"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Toeganklikheidknoppie het die toeganklikheidgebaar vervang\n\n"<annotation id="link">"Bekyk instellings"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Jy kan van die toeganklikheidsgebaar na \'n -knoppie oorskakel\n\n"<annotation id="link">"Instellings"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Skuif knoppie na kant om dit tydelik te versteek"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Beweeg na links bo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Beweeg na regs bo"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index fe3cc8e..4736adb 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"ተጠቃሚ አክል"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"አዲስ ተጠቃሚ"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"እንግዳ ይወገድ?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"በዚህ ክፍለ-ጊዜ ውስጥ ያሉ ሁሉም መተግበሪያዎች እና ውሂብ ይሰረዛሉ።"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"አስወግድ"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"እንኳን በደህና ተመለሱ እንግዳ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ክፍለ-ጊዜዎን መቀጠል ይፈልጋሉ?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"እንደገና ጀምር"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"የማያ ገጹን ክፍል አጉላ"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ማብሪያ/ማጥፊያ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"የተደራሽነት አዝራር የተደራሽነት ምልክትን ተክቷል\n\n"<annotation id="link">" ቅንብሮችን አሳይ"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"ከተደራሽነት ምልክቱ ወደ አንድ አዝራር መቀየር ይችላሉ።\n\n"<annotation id="link">"ከተደ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ለጊዜው ለመደበቅ አዝራሩን ወደ ጠርዝ ያንቀሳቅሱ"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ወደ ላይኛው ግራ አንቀሳቅስ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ወደ ላይኛው ቀኝ አንቀሳቅስ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 83b483e..b493d89 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -488,8 +488,12 @@
<string name="user_add_user" msgid="4336657383006913022">"إضافة مستخدم"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"مستخدم جديد"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"هل تريد إزالة جلسة الضيف؟"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"سيتم حذف كل التطبيقات والبيانات في هذه الجلسة."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"إزالة"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"مرحبًا بك مجددًا في جلسة الضيف"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"هل تريد متابعة جلستك؟"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"البدء من جديد"</string>
@@ -1054,6 +1058,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"تكبير جزء من الشاشة"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"تبديل"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"تم استبدال \"زر أدوات تسهيل الاستخدام\" بإيماءة تسهيل الاستخدام.\n\n"<annotation id="link">"الاطّلاع على الإعدادات"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"يمكنك التبديل من إيماءة تسهيل الاستخدام إلى استخدام زرّ\n\n"<annotation id="link">"الإعدادات"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"يمكنك نقل الزر إلى الحافة لإخفائه مؤقتًا."</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"نقل إلى أعلى يمين الشاشة"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"نقل إلى أعلى يسار الشاشة"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 50d866d..fa528fd 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"ব্যৱহাৰকাৰী যোগ কৰক"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"নতুন ব্যৱহাৰকাৰী"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"অতিথি আঁতৰাবনে?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"অতিথিৰ ছেশ্বন ৰিছেট কৰিবনে?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই ছেশ্বনৰ সকলো এপ্ আৰু ডেটা মচা হ\'ব।"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"আঁতৰাওক"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"ৰিছেট কৰক"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"অতিথি, আপোনাক পুনৰ স্বাগতম!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"আপুনি আপোনাৰ ছেশ্বন অব্যাহত ৰাখিব বিচাৰেনে?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"আকৌ আৰম্ভ কৰক"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"স্ক্ৰীনৰ কিছু অংশ বিবৰ্ধন কৰক"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ছুইচ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"সাধ্য সুবিধাৰ বুটামটোৱে সাধ্য সুবিধাৰ নিৰ্দেশ সলনি কৰিছে\n\n"<annotation id="link">"ছেটিং চাওক"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"আপুনি সাধ্য-সুবিধাৰ নিৰ্দেশটোৰ পৰা এটা বুটামলৈ সলনি কৰিব পাৰে\n\n"<annotation id="link">"ছেটিং"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"বুটামটোক সাময়িকভাৱে লুকুৱাবলৈ ইয়াক একেবাৰে কাষলৈ লৈ যাওক"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"শীৰ্ষৰ বাওঁফালে নিয়ক"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"শীৰ্ষৰ সোঁফালে নিয়ক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 9784d53..c3b96a4 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -89,7 +89,7 @@
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Skrinşot çəkməyə tətbiq və ya təşkilat tərəfindən icazə verilmir"</string>
<string name="screenshot_edit_label" msgid="8754981973544133050">"Redaktə edin"</string>
<string name="screenshot_edit_description" msgid="3333092254706788906">"Skrinşota düzəliş edin"</string>
- <string name="screenshot_scroll_label" msgid="2930198809899329367">"Daha çoxunu əhatə edin"</string>
+ <string name="screenshot_scroll_label" msgid="2930198809899329367">"Genişləndirin"</string>
<string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ekran şəklini ötürün"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran şəklinə önbaxış"</string>
<string name="screenshot_top_boundary_pct" msgid="2520148599096479332">"Yuxarı sərhəd <xliff:g id="PERCENT">%1$d</xliff:g> faiz"</string>
@@ -100,7 +100,7 @@
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran çəkilişi emal edilir"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Yazmağa başlanılsın?"</string>
- <string name="screenrecord_description" msgid="1123231719680353736">"Yazarkən Android Sistemi ekranınızda görünən və ya cihazınızda göstərilən istənilən həssas məlumatı qeydə ala bilər. Buraya parollar, ödəniş məlumatı, fotolar, mesajlar və audio daxildir."</string>
+ <string name="screenrecord_description" msgid="1123231719680353736">"Ekranda görünən və ya cihazda oxudulan şəxsi məlumat (parol, bank hesabı, mesaj, fotoşəkil və sair) videoyazıya düşə bilər."</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Audio yazın"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Cihaz audiosu"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Cihazınızdan gələn musiqi, zənglər və zəng melodiyaları kimi səslər"</string>
@@ -109,7 +109,7 @@
<string name="screenrecord_start" msgid="330991441575775004">"Başlayın"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Ekran yazılır"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Ekran və audio yazılır"</string>
- <string name="screenrecord_taps_label" msgid="1595690528298857649">"Ekranda toxunuşları göstərin"</string>
+ <string name="screenrecord_taps_label" msgid="1595690528298857649">"Ekrana toxunuş göstərilsin"</string>
<string name="screenrecord_stop_text" msgid="6549288689506057686">"Dayandırmaq üçün toxunun"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Dayandırın"</string>
<string name="screenrecord_pause_label" msgid="6004054907104549857">"Dayandırın"</string>
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"İstifadəçi əlavə edin"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Yeni istifadəçi"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Qonaq silinsin?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Qonaq sessiyası sıfırlansın?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu sessiyada bütün tətbiqlər və data silinəcək."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Yığışdır"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Sıfırlayın"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Xoş gəlmisiniz!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Sessiya davam etsin?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Yenidən başlayın"</string>
@@ -605,15 +607,15 @@
<string name="accessibility_output_chooser" msgid="7807898688967194183">"Çıxış cihazına keçin"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Tətbiq bərkidilib"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri və İcmal düymələrinə basıb saxlayın."</string>
- <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri və Əsas səhifə düymələrinə basıb saxlayın."</string>
- <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Bu, onu çıxarana qədər görünəcək. Çıxarmaq üçün yuxarı sürüşdürün & basıb saxlayın."</string>
- <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri düyməsinə basıb saxlayın."</string>
- <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Əsas səhifə düyməsinə basıb saxlayın."</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Şəxsi məlumatlar (məsələn, kontaktlar və e-poçt məzmunu) əlçatan ola bilər."</string>
+ <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"\"Geri\" və \"Əsas ekran\" düymələrinin davamlı basılması ilə çıxarılana qədər tətbiq göz önündə qalır."</string>
+ <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Yuxarı sürüşdürülüb saxlanılana ilə çıxarılana qədər tətbiq göz önündə qalır."</string>
+ <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"\"İcmal\" düyməsinin davamlı basılması ilə çıxarılana qədər tətbiq göz önündə qalır."</string>
+ <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"\"Əsas ekran\" düyməsinin davamlı basılması ilə çıxarılana qədər tətbiq göz önündə qalır."</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Şəxsi məlumatlar (məsələn, kontaktlar və e-poçt məzmunu) ekranda görünə bilər."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Bərkidilmiş tətbiq digər tətbiqləri aça bilər."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"Bu tətbiqi çıxarmaq üçün Geri və İcmal düymələrinə basıb saxlayın"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Bu tətbiqi çıxarmaq üçün Geri və Əsas ekran düymələrinə basıb saxlayın"</string>
- <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Bu tətbiqi çıxarmaq üçün yuxarı sürüşdürüb saxlayın"</string>
+ <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Tətbiqi çıxarmaq üçün yuxarı sürüşdürüb saxlayın"</string>
<string name="screen_pinning_positive" msgid="3285785989665266984">"Anladım!"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"Yox, çox sağ olun"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"Tətbiq bərkidildi"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekran hissəsinin böyüdülməsi"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Dəyişdirici"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Əlçatımlılıq düyməsi əlçatımlılıq jestini əvəz etdi\n\n"<annotation id="link">"Ayarlara baxın"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Əlçatımlılıq jestindən düymə\n\n"<annotation id="link">"Ayarlarına"</annotation>" keçə bilərsiniz"</string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Düyməni müvəqqəti gizlətmək üçün kənara çəkin"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Yuxarıya sola köçürün"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Yuxarıya sağa köçürün"</string>
@@ -1043,7 +1046,7 @@
<string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Kənara daşıyıb göstərin"</string>
<string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"keçirin"</string>
<string name="quick_controls_title" msgid="7095074621086860062">"Əsas səhifə nizamlayıcıları"</string>
- <string name="controls_providers_title" msgid="6879775889857085056">"Nizamlayıcıları əlavə etmək üçün tətbiq seçin"</string>
+ <string name="controls_providers_title" msgid="6879775889857085056">"Kontrol əlavə etmək üçün tətbiq seçin"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
<item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> nizamlayıcı əlavə edilib.</item>
<item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> nizamlayıcı əlavə edilib.</item>
@@ -1057,8 +1060,8 @@
<string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> mövqeyinə keçirin"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"Nizamlayıcılar"</string>
<string name="controls_favorite_subtitle" msgid="6481675111056961083">"Sürətli Ayarlardan giriş üçün nizamlayıcıları seçin"</string>
- <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Nizamlayıcıları yenidən tənzimləmək üçün tutub sürüşdürün"</string>
- <string name="controls_favorite_removed" msgid="5276978408529217272">"Bütün nizamlayıcılar silindi"</string>
+ <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Vidcetləri daşıyaraq yerini dəyişin"</string>
+ <string name="controls_favorite_removed" msgid="5276978408529217272">"Kontrol vidcetləri silindi"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Dəyişikliklər yadda saxlanmadı"</string>
<string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Digər tətbiqlərə baxın"</string>
<string name="controls_favorite_load_error" msgid="5126216176144877419">"Nizamlayıcıları yükləmək mümkün olmadı. <xliff:g id="APP">%s</xliff:g> tətbiqinə toxunaraq tətbiq ayarlarının dəyişmədiyinə əmin olun."</string>
@@ -1100,8 +1103,8 @@
<string name="controls_error_failed" msgid="960228639198558525">"Xəta, yenidən cəhd edin"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Davam edir"</string>
<string name="controls_added_tooltip" msgid="5866098408470111984">"Yeni nizamlayıcılara baxmaq üçün Sürətli Ayarları açın"</string>
- <string name="controls_menu_add" msgid="4447246119229920050">"Nizamlayıcılar əlavə edin"</string>
- <string name="controls_menu_edit" msgid="890623986951347062">"Nizamlayıcıları redaktə edin"</string>
+ <string name="controls_menu_add" msgid="4447246119229920050">"Vidcet əlavə edin"</string>
+ <string name="controls_menu_edit" msgid="890623986951347062">"Vidcetlərə düzəliş edin"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Nəticələri əlavə edin"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Qrup"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçilib"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 677bfb2..fe89267 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -482,8 +482,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Dodaj korisnika"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novi korisnik"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Želite li da uklonite gosta?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji će biti izbrisani."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ukloni"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Dobro došli nazad, goste!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li da nastavite sesiju?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni iz početka"</string>
@@ -1039,6 +1043,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Uvećajte deo ekrana"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Pređi"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Dugme Pristupačnost je zamenilo pokret za pristupačnost\n\n"<annotation id="link">"Prikaži podešavanja"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Možete da pređete sa pokreta za pristupačnost na dugme\n\n"<annotation id="link">"Podešavanja"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Pomerite dugme do ivice da biste ga privremeno sakrili"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Premesti gore levo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Premesti gore desno"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 6576a92..2e98ad9 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -484,8 +484,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Дадаць карыстальніка"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Новы карыстальнік"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Выдаліць госця?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усе праграмы і даныя гэтага сеанса будуць выдалены."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Выдаліць"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"З вяртаннем, госць!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Хочаце працягнуць сеанс?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Пачаць зноў"</string>
@@ -1044,6 +1048,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Павялічыць частку экрана"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Пераключальнік"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Замест жэста спецыяльных магчымасцей будзе выкарыстоўвацца кнопка\n\n"<annotation id="link">"Праглядзець налады"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Вы можаце пераключыцца з жэста спецыяльных магчымасцей на кнопку\n\n"<annotation id="link">"Налады"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Каб часова схаваць кнопку, перамясціце яе на край"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перамясціць лявей і вышэй"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Перамясціць правей і вышэй"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index d51bc7b..3f9269a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Добавяне на потребител"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Нов потребител"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Да се премахне ли гостът?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Да се нулира ли сесията като гост?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Всички приложения и данни в тази сесия ще бъдат изтрити."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Премахване"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Нулиране"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Добре дошли отново в сесията като гост!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Искате ли да продължите сесията си?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Започване отначало"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увеличаване на част от екрана"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Превключване"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Жестът за достъпност бе заменен от бутон\n\n"<annotation id="link">"Преглед на настройките"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Вместо жеста за достъпност можете да използвате бутон\n\n"<annotation id="link">"Настройки"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Преместете бутона до края, за да го скриете временно"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Преместване горе вляво"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Преместване горе вдясно"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index b402402..9f71f43 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"ব্যবহারকারী জুড়ুন"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"নতুন ব্যবহারকারী"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"অতিথি সরাবেন?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই সেশনের সব অ্যাপ ও ডেটা মুছে ফেলা হবে।"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"সরান"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"অতিথি, আপনি ফিরে আসায় আপনাকে স্বাগত!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"আপনি কি আপনার সেশনটি চালিয়ে যেতে চান?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"আবার শুরু করুন"</string>
@@ -1034,6 +1038,8 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"স্ক্রিনের কিছুটা অংশ বড় করুন"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"বদল করুন"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"অ্যাক্সেসিবিলিটি জেসচার পরিবর্তন করে অ্যাক্সেসেবিলিটি বোতাম করা হয়েছে\n\n"<annotation id="link">"সেটিংস দেখুন"</annotation></string>
+ <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
+ <skip />
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"এটি অস্থায়ীভাবে লুকাতে বোতামটি কোণে সরান"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"উপরে বাঁদিকে সরান"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"উপরে ডানদিকে সরান"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index cfcceb69..17dbbe9 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -482,8 +482,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Dodaj korisnika"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novi korisnik"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Ukloniti gosta?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci iz ove sesije će se izbrisati."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ukloni"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Zdravo! Lijepo je opet vidjeti goste."</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li nastaviti sesiju?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni ispočetka"</string>
@@ -1039,6 +1043,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Uvećavanje dijela ekrana"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Prekidač"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Dugme za pristupačnost je zamijenilo pokret za pristupačnost\n\n"<annotation id="link">"Prikaži postavke"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Možete prebaciti s pokreta za pristupačnost na dugme\n\n"<annotation id="link">"Postavke"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Premjestite dugme do ivice da ga privremeno sakrijete"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Pomjeranje gore lijevo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Pomjeranje gore desno"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 925a293..2428d55 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Afegeix un usuari"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Usuari nou"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vols suprimir el convidat?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Totes les aplicacions i les dades d\'aquesta sessió se suprimiran."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Suprimeix"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Benvingut de nou, convidat."</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vols continuar amb la sessió?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Torna a començar"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Amplia una part de la pantalla"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Canvia"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"El gest d\'accessibilitat s\'ha substituït pel botó d\'accessibilitat\n\n"<annotation id="link">"Mostra la configuració"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Pots canviar del gest d\'accessibilitat a un botó\n\n"<annotation id="link">"Configuració"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mou el botó a l\'extrem per amagar-lo temporalment"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mou a dalt a l\'esquerra"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mou a dalt a la dreta"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f3d64ab..d8e0a6a1 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -484,8 +484,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Přidat uživatele"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nový uživatel"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Odstranit hosta?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Veškeré aplikace a data v této relaci budou vymazána."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Odstranit"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Vítejte zpět v relaci hosta!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcete v relaci pokračovat?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Začít znovu"</string>
@@ -1044,6 +1048,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zvětšit část obrazovky"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Přepnout"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Tlačítko přístupnosti bylo nahrazeno gestem přístupnosti\n\n"<annotation id="link">"Zobrazit nastavení"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Z gesta přístupnosti můžete přejít na tlačítko\n\n"<annotation id="link">"Nastavení"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Přesunutím tlačítka k okraji ho dočasně skryjete"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Přesunout vlevo nahoru"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Přesunout vpravo nahoru"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 0c7a743..ca44f0a 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Tilføj bruger"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Ny bruger"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vil du fjerne gæsten?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps og data i denne session slettes."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Fjern"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkommen tilbage, gæst!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vil du fortsætte din session?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start forfra"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Forstør en del af skærmen"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Skift"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Knappen Hjælpefunktioner har erstattet bevægelsen for hjælpefunktioner\n\n"<annotation id="link">"Se indstillinger"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Hvis du ikke vil bruge bevægelsen til hjælpefunktioner, kan du skifte til knappen\n\n"<annotation id="link">"Indstillinger"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Flyt knappen til kanten for at skjule den midlertidigt"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Flyt op til venstre"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Flyt op til højre"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 0f18757..274ca3a 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Nutzer hinzufügen"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Neuer Nutzer"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Gast entfernen?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle Apps und Daten in dieser Sitzung werden gelöscht."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Entfernen"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Willkommen zurück im Gastmodus"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Möchtest du deine Sitzung fortsetzen?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Neu starten"</string>
@@ -1034,6 +1038,8 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Teil des Bildschirms vergrößern"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Schalter"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Die Schaltfläche „Bedienungshilfen“ ersetzt die Touch-Geste für Bedienungshilfen\n\n"<annotation id="link">"Einstellungen aufrufen"</annotation></string>
+ <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
+ <skip />
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Durch Ziehen an den Rand wird die Schaltfläche zeitweise ausgeblendet"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Nach oben links verschieben"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Nach rechts oben verschieben"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 9525f99..7b135a3 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Προσθήκη χρήστη"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Νέος χρήστης"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Κατάργηση επισκέπτη;"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Όλες οι εφαρμογές και τα δεδομένα αυτής της περιόδου σύνδεσης θα διαγραφούν."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Κατάργηση"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Kαλώς ορίσατε ξανά!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Θέλετε να συνεχίσετε την περίοδο σύνδεσής σας;"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Έναρξη από την αρχή"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Μεγέθυνση μέρους της οθόνης"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Εναλλαγή"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Το κουμπί προσβασιμότητας αντικατέστησε την κίνηση προσβασιμότητας\n\n"<annotation id="link">"Προβολή ρυθμίσεων"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Μπορείτε να κάνετε εναλλαγή από την κίνηση προσβασιμότητας σε ένα κουμπί\n\n"<annotation id="link">"Ρυθμίσεις"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Μετακινήστε το κουμπί στο άκρο για προσωρινή απόκρυψη"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Μετακίνηση επάνω αριστερά"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Μετακίνηση επάνω δεξιά"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index c346bbe..d7b39e2 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Add user"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"New user"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remove guest?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Reset guest?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remove"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Reset"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome back, guest!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Accessibility button replaced the accessibility gesture\n\n"<annotation id="link">"View settings"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"You can switch from the accessibility gesture to a button\n\n"<annotation id="link">"Settings"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Move button to the edge to hide it temporarily"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Move top left"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Move top right"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index b588e86..0a49742 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Add user"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"New user"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remove guest?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Reset guest?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remove"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Reset"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome back, guest!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Accessibility button replaced the accessibility gesture\n\n"<annotation id="link">"View settings"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"You can switch from the accessibility gesture to a button\n\n"<annotation id="link">"Settings"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Move button to the edge to hide it temporarily"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Move top left"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Move top right"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index c346bbe..d7b39e2 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Add user"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"New user"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remove guest?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Reset guest?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remove"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Reset"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome back, guest!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Accessibility button replaced the accessibility gesture\n\n"<annotation id="link">"View settings"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"You can switch from the accessibility gesture to a button\n\n"<annotation id="link">"Settings"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Move button to the edge to hide it temporarily"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Move top left"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Move top right"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index c346bbe..d7b39e2 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Add user"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"New user"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remove guest?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Reset guest?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remove"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Reset"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome back, guest!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Accessibility button replaced the accessibility gesture\n\n"<annotation id="link">"View settings"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"You can switch from the accessibility gesture to a button\n\n"<annotation id="link">"Settings"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Move button to the edge to hide it temporarily"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Move top left"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Move top right"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index a73c387..ca3d72f 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Add user"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"New user"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remove guest?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Reset guest?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remove"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Reset"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome back, guest!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start over"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Accessibility button replaced the accessibility gesture\n\n"<annotation id="link">"View settings"</annotation>""</string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"You can switch from the accessibility gesture to a button\n\n"<annotation id="link">"Settings"</annotation>""</string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Move button to the edge to hide it temporarily"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Move top left"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Move top right"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 051c0dd..0479ad0 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Agregar usuario"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Usuario nuevo"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"¿Quitar invitado?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán las aplicaciones y los datos de esta sesión."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Quitar"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"¡Hola de nuevo, invitado!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"¿Quieres retomar la sesión?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Volver a empezar"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte de la pantalla"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Botón"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"El botón de accesibilidad reemplaza el gesto de accesibilidad\n\n"<annotation id="link">"Ver configuración"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Puedes cambiar de un gesto a un botón de accesibilidad\n\n"<annotation id="link">"Configuración"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mueve el botón hacia el borde para ocultarlo temporalmente"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover arriba a la izquierda"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover arriba a la derecha"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index d04fd45..6564815 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Añadir usuario"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nuevo usuario"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"¿Quitar invitado?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán todas las aplicaciones y datos de esta sesión."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Quitar"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Hola de nuevo, invitado"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"¿Quieres continuar con la sesión?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Volver a empezar"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte de la pantalla"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Cambiar"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"El botón Accesibilidad ha reemplazado el gesto de accesibilidad\n\nVer ajustes"<annotation id="link"></annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Puedes cambiar el gesto de accesibilidad por un botón\n\n"<annotation id="link">"Ajustes"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mueve el botón hacia el borde para ocultarlo temporalmente"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover arriba a la izquierda"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover arriba a la derecha"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 00d98c2..6622821 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Lisa kasutaja"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Uus kasutaja"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Kas eemaldada külaline?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Seansi kõik rakendused ja andmed kustutatakse."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Eemalda"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Tere tulemast tagasi, külaline!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Kas soovite seansiga jätkata?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Alusta uuesti"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekraanikuva osa suurendamine"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Vaheta"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Juurdepääsetavuse nupp asendas juurdepääsuliigutuse\n\n"<annotation id="link">"Vaadake seadeid"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Saate juurdepääsuliigutuselt nupule lülituda.\n\n"<annotation id="link">"Seaded"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Teisaldage nupp serva, et see ajutiselt peita"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Teisalda üles vasakule"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Teisalda üles paremale"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 78eb728..6d8a8fd 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -160,7 +160,7 @@
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Erabili PINa"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Erabili eredua"</string>
<string name="biometric_dialog_use_password" msgid="3445033859393474779">"Erabili pasahitza"</string>
- <string name="biometric_dialog_wrong_pin" msgid="1878539073972762803">"PIN kodea ez da zuzena"</string>
+ <string name="biometric_dialog_wrong_pin" msgid="1878539073972762803">"PINa ez da zuzena"</string>
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Eredua ez da zuzena"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Pasahitza ez da zuzena"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Saiakera oker gehiegi egin dituzu.\nSaiatu berriro <xliff:g id="NUMBER">%d</xliff:g> segundo barru."</string>
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Gehitu erabiltzaile bat"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Erabiltzaile berria"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Gonbidatua kendu nahi duzu?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Saioko aplikazio eta datu guztiak ezabatuko dira."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Kendu"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Ongi etorri berriro, gonbidatu hori!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Saioarekin jarraitu nahi duzu?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Hasi berriro"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Handitu pantailaren zati bat"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Botoia"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Erabilerraztasuna botoiak erabilerraztasun-keinua ordezkatu du\n\n"<annotation id="link">"Ikusi ezarpenak"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Erabilerraztasun-keinua erabiltzeari utz diezaiokezu eta botoi bat erabiltzen has zaitezke\n\n"<annotation id="link">"Ezarpenak"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Eraman botoia ertzera aldi baterako ezkutatzeko"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Eraman goialdera, ezkerretara"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Eraman goialdera, eskuinetara"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 10e95f4..ce3e676 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"افزودن کاربر"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"کاربر جدید"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"مهمان حذف شود؟"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"همه برنامهها و دادههای این جلسه حذف خواهد شد."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"حذف"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"مهمان گرامی، بازگشتتان را خوش آمد میگوییم!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"آیا میخواهید جلسهتان را ادامه دهید؟"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"شروع مجدد"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"درشتنمایی بخشی از صفحه"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"کلید"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"دکمه دسترسپذیری جایگزین اشاره دسترسپذیری شد\n\n"<annotation id="link">"مشاهده تنظیمات"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"میتوانید بهجای اشاره دسترسپذیری از دکمه استفاده کنید\n\n"<annotation id="link">"تنظیمات"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"برای پنهان کردن موقتی دکمه، آن را به لبه ببرید"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"انتقال به بالا سمت راست"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"انتقال به بالا سمت چپ"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 51b73df..90f47ef 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Lisää käyttäjä"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Uusi käyttäjä"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Poistetaaanko vieras?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Kaikki sovellukset ja tämän istunnon tiedot poistetaan."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Poista"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Tervetuloa takaisin!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Haluatko jatkaa istuntoa?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Aloita alusta"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Suurenna osa näytöstä"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Vaihda"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Esteettömyyspainike on korvannut esteettömyyseleen\n\n"<annotation id="link">"Katso asetukset"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Voit vaihtaa käyttämään esteettömyyseleen sijaan painiketta\n\n"<annotation id="link">"Asetukset"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Piilota painike tilapäisesti siirtämällä se reunaan"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Siirrä vasempaan yläreunaan"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Siirrä oikeaan yläreunaan"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index e657308..0304280 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Ajouter un utilisateur"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nouvel utilisateur"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Supprimer l\'invité?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Supprimer"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Bienvenue à nouveau dans la session Invité"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Voulez-vous poursuivre la session?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recommencer"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Agrandir une partie de l\'écran"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Commutateur"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Le bouton d\'accessibilité a remplacé le geste d\'accessibilité\n\n"<annotation id="link">"Voir les paramètres"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Vous pouvez passer du geste d\'accessibilité au bouton\n\n"<annotation id="link">"Paramètres"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Déplacez le bouton vers le bord pour le masquer temporairement"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Déplacer dans coin sup. gauche"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Déplacer dans coin sup. droit"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 04f7692..c402261 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Ajouter un utilisateur"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nouvel utilisateur"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Supprimer l\'invité ?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Supprimer"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Bienvenue à nouveau dans la session Invité"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Voulez-vous poursuivre la dernière session ?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Non, nouvelle session"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Agrandir une partie de l\'écran"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Changer"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Le bouton Accessibilité a remplacé le geste d\'accessibilité\n\n"<annotation id="link">"Afficher les paramètres"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Vous pouvez passer du geste d\'accessibilité à un bouton\n\n"<annotation id="link">"Paramètres"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Déplacer le bouton vers le bord pour le masquer temporairement"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Déplacer en haut à gauche"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Déplacer en haut à droite"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 52c6e33..e7b3e92 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Engadir usuario"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novo usuario"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Queres quitar o convidado?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Eliminaranse todas as aplicacións e datos desta sesión."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Quitar"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Benvido de novo, convidado"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Queres continuar coa túa sesión?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Comezar de novo"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Amplía parte da pantalla"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Cambiar"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"O botón de accesibilidade substituíu o xesto de accesibilidade\n\n"<annotation id="link">"Ver configuración"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Podes cambiar do xesto de accesibilidade a un botón\n\n"<annotation id="link">"Configuración"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Para ocultar temporalmente o botón, móveo ata o bordo"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover á parte super. esquerda"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover á parte superior dereita"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index c06826b..a99558e 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"વપરાશકર્તા ઉમેરો"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"નવો વપરાશકર્તા"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"અતિથિ દૂર કરીએ?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"અતિથિ સત્રને રીસેટ કરીએ?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"આ સત્રમાંની તમામ ઍપ અને ડેટા કાઢી નાખવામાં આવશે."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"દૂર કરો"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"રીસેટ કરો"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ફરી સ્વાગત છે, અતિથિ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"શું તમે તમારું સત્ર ચાલુ રાખવા માંગો છો?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"શરૂ કરો"</string>
@@ -1034,6 +1036,8 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"સ્ક્રીનનો કોઈ ભાગ મોટો કરો"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"સ્વિચ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ઍક્સેસિબિલિટી સંકેતને ઍક્સેસિબિલિટી બટન વડે બદલવામાં આવ્યા છે\n\n"<annotation id="link">"સેટિંગ જુઓ"</annotation></string>
+ <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
+ <skip />
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"તેને હંગામી રૂપે ખસેડવા માટે બટનને કિનારી પર ખસેડો"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ઉપર ડાબે ખસેડો"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ઉપર જમણે ખસેડો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index cdead41..4196b1f 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"उपयोगकर्ता जोड़ें"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"नया उपयोगकर्ता"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"क्या आप मेहमान को हटाना चाहते हैं?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"इस सत्र के सभी ऐप्लिकेशन और डेटा को हटा दिया जाएगा."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"निकालें"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"मेहमान, आपका फिर से स्वागत है!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"क्या आप अपना सत्र जारी रखना चाहते हैं?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"फिर से शुरू करें"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीन के किसी हिस्से को ज़ूम करें"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"स्विच"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"सुलभता वाले हाथ के जेस्चर (हाव-भाव) को सुलभता बटन से बदल दिया गया है\n\n"<annotation id="link">"सेटिंग देखें"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"आप सुलभता वाले हाथ के जेस्चर (हाव-भाव) के बजाय, बटन का इस्तेमाल कर सकते हैं\n\n"<annotation id="link">"सेटिंग"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"बटन को कुछ समय छिपाने के लिए, उसे किनारे पर ले जाएं"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"सबसे ऊपर बाईं ओर ले जाएं"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"सबसे ऊपर दाईं ओर ले जाएं"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 14250a7..6f7aee2 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -482,8 +482,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Dodavanje korisnika"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novi korisnik"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Ukloniti gosta?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji bit će izbrisani."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ukloni"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Dobro došli natrag, gostu!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li nastaviti sesiju?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni ispočetka"</string>
@@ -1039,6 +1043,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Povećaj dio zaslona"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Prebacivanje"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Gumb za Pristupačnost zamijenio je pokret pristupačnosti\n\n"<annotation id="link">"Prikaz postavki"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Možete prijeći s pokreta za pristupačnost na gumb\n\n"<annotation id="link">"Postavke"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Pomaknite gumb do ruba da biste ga privremeno sakrili"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Premjesti u gornji lijevi kut"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Premjesti u gornji desni kut"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2022281..800c9dc 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Felhasználó hozzáadása"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Új felhasználó"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Eltávolítja a vendég munkamenetet?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"A munkamenetben található összes alkalmazás és adat törlődni fog."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Eltávolítás"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Örülünk, hogy visszatért, vendég!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Folytatja a munkamenetet?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Újrakezdés"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Képernyő bizonyos részének nagyítása"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Váltás"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"A kisegítő kézmozdulat helyébe a Kisegítő lehetőségek gomb lépett\n\n"<annotation id="link">"Beállítások megtekintése"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Átválthat kisegítő kézmozdulatról gomb használatára\n\n"<annotation id="link">"Beállítások"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"A gombot a szélre áthelyezve ideiglenesen elrejtheti"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Áthelyezés fel és balra"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Áthelyezés fel és jobbra"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 4fb191f..deeeb20 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Ավելացնել օգտատեր"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Նոր օգտատեր"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Հեռացնե՞լ հյուրին"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Այս աշխատաշրջանի բոլոր ծրագրերն ու տվյալները կջնջվեն:"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Հեռացնել"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Բարի վերադարձ, հյուր"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Շարունակե՞լ աշխատաշրջանը։"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Վերսկսել"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Խոշորացնել էկրանի որոշակի հատվածը"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Փոխել"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Հատուկ գործառույթների ժեստը փոխարինվել է կոճակով\n\n"<annotation id="link">"Բացել կարգավորումները"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Դուք հատուկ գործառույթի ժեստի փոխարեն կարող եք անցնել համապատասխան կոճակի օգտագործմանը\n\n"<annotation id="link">"Կարգավորումներ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Կոճակը ժամանակավորապես թաքցնելու համար այն տեղափոխեք էկրանի եզր"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Տեղափոխել վերև՝ ձախ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Տեղափոխել վերև՝ աջ"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 7e4ba76..a6cb798 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Tambahkan pengguna"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Pengguna baru"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Hapus tamu?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data di sesi ini akan dihapus."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Hapus"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Selamat datang kembali, tamu!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Lanjutkan sesi Anda?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Mulai ulang"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Perbesar sebagian layar"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Alihkan"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Tombol aksesibilitas menggantikan gestur aksesibilitas\n\n"<annotation id="link">"Tampilkan setelan"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Anda dapat beralih dari gestur aksesibilitas ke tombol\n\n"<annotation id="link">"Setelan"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Pindahkan tombol ke tepi agar tersembunyi untuk sementara"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Pindahkan ke kiri atas"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Pindahkan ke kanan atas"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 229bcbb..01bad1c 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Bæta notanda við"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nýr notandi"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Fjarlægja gest?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Öllum forritum og gögnum í þessari lotu verður eytt."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Fjarlægja"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkominn aftur, gestur!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Viltu halda áfram með lotuna?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Byrja upp á nýtt"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Stækka hluta skjásins"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Rofi"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Aðgengishnappur kom í stað aðgengisbendingar\n\n"<annotation id="link">"Skoða stillingar"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Þú getur skipt úr aðgengisbendingu yfir í hnapp\n\n"<annotation id="link">"Stillingar"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Færðu hnappinn að brúninni til að fela hann tímabundið"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Færa efst til vinstri"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Færa efst til hægri"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 6c1ef8a..066cd93 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Aggiungi utente"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nuovo utente"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Rimuovere l\'ospite?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tutte le app e i dati di questa sessione verranno eliminati."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Rimuovi"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Ti ridiamo il benvenuto alla sessione Ospite."</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vuoi continuare la sessione?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Ricomincia"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ingrandisci parte dello schermo"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Opzione"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Il pulsante Accessibilità ha sostituito il gesto di accessibilità\n\n"<annotation id="link">"Visualizza le impostazioni"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Puoi passare dal gesto di accessibilità a un pulsante\n\n"<annotation id="link">"Impostazioni"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Sposta il pulsante fino al bordo per nasconderlo temporaneamente"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Sposta in alto a sinistra"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Sposta in alto a destra"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index aae58cb..b2f0fd2 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -484,8 +484,12 @@
<string name="user_add_user" msgid="4336657383006913022">"הוספת משתמש"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"משתמש חדש"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"להסיר אורח?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"כל האפליקציות והנתונים בסשן הזה יימחקו."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"הסרה"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"שמחים לראותך שוב!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"האם ברצונך להמשיך בפעילות באתר?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"סשן חדש"</string>
@@ -909,7 +913,7 @@
<string-array name="clock_options">
<item msgid="3986445361435142273">"הצגת שעות, דקות ושניות"</item>
<item msgid="1271006222031257266">"הצגת שעות ודקות (ברירת מחדל)"</item>
- <item msgid="6135970080453877218">"לא להציג את הסמל הזה"</item>
+ <item msgid="6135970080453877218">"בלי הסמל הזה"</item>
</string-array>
<string-array name="battery_options">
<item msgid="7714004721411852551">"תמיד להציג באחוזים"</item>
@@ -1044,6 +1048,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"הגדלת חלק מהמסך"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"מעבר"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"לחצן הנגישות החליף את תנועת הנגישות\n\n"<annotation id="link">"להצגת ההגדרות"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"ניתן להחליף את תנועת הנגישות בלחצן\n\n"<annotation id="link">"הגדרות"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"כדי להסתיר זמנית את הלחצן, יש להזיז אותו לקצה"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"העברה לפינה השמאלית העליונה"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"העברה לפינה הימנית העליונה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 2ba73b3..b173653 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"ユーザーを追加"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"新しいユーザー"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ゲストを削除しますか?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"このセッションでのアプリとデータはすべて削除されます。"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"削除"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"おかえりなさい、ゲストさん"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"セッションを続行しますか?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"最初から開始"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"画面の一部を拡大します"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"スイッチ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ユーザー補助ジェスチャーに代わって、ユーザー補助機能ボタンが導入されました\n\n"<annotation id="link">"設定を表示"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"ユーザー補助操作からボタンに切り替えることができます\n\n"<annotation id="link">"設定"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ボタンを一時的に非表示にするには、端に移動させてください"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"左上に移動"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"右上に移動"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 1f071a2..06af42a 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"მომხმარებლის დამატება"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ახალი მომხმარებელი"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"სტუმრის ამოშლა?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"გადაყენდეს სტუმარი?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ამ სესიის ყველა აპი და მონაცემი წაიშლება."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ამოშლა"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"გადაყენება"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"სტუმარო, გვიხარია, რომ დაბრუნდით!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"გსურთ, თქვენი სესიის გაგრძელება?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ხელახლა დაწყება"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ეკრანის ნაწილის გადიდება"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"გადართვა"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"მარტივი წვდომის ღილაკმა ჩაანაცვლა მარტივი წვდომის ჟესტი\n\n"<annotation id="link">"პარამეტრების ნახვა"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"შეგიძლიათ, გადართოთ მარტივი წვდომის ჟესტიდან ღილაკის\n\n"<annotation id="link">"პარამეტრებზე"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"გადაიტანეთ ღილაკი კიდეში, რათა დროებით დამალოთ ის"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ზევით და მარცხნივ გადატანა"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ზევით და მარჯვნივ გადატანა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 9ab5d80..09d5f9f 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Пайдаланушы қосу"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Жаңа пайдаланушы"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Қонақты жою керек пе?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Осы сеанстағы барлық қолданбалар мен деректер жойылады."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Алып тастау"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Қош келдіңіз, қонақ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансты жалғастыру керек пе?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Қайта бастау"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Экранның бөлігін ұлғайту"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Ауысу"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Арнайы мүмкіндіктер қимылының орнына \"Арнайы мүмкіндіктер\" түймесі болады.\n\n"<annotation id="link">"Параметрлерді көру"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Арнайы мүмкіндіктер қимылынан арнайы мүмкіндіктер түймесіне ауысуыңызға болады.\n\n"<annotation id="link">"Параметрлер"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Түймені уақытша жасыру үшін оны шетке қарай жылжытыңыз."</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Жоғарғы сол жаққа жылжыту"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Жоғарғы оң жаққа жылжыту"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 6ce7300..065a499 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"បញ្ចូលអ្នកប្រើ"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"អ្នកប្រើថ្មី"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ដកភ្ញៀវចេញឬ?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"កម្មវិធី និងទិន្នន័យទាំងអស់ក្នុងវគ្គនេះនឹងត្រូវលុប។"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ដកចេញ"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"សូមស្វាគមន៍ការត្រឡប់មកវិញ, ភ្ញៀវ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"តើអ្នកចង់បន្តវគ្គរបស់អ្នកទេ?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ចាប់ផ្ដើមសាជាថ្មី"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ពង្រីកផ្នែកនៃអេក្រង់"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ប៊ូតុងបិទបើក"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ប៊ូតុងភាពងាយស្រួលបានជំនួសចលនាភាពងាយស្រួល\n\n"<annotation id="link">"មើលការកំណត់"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"អ្នកអាចប្ដូរពីចលនាភាពងាយស្រួលទៅប៊ូតុង\n\n"<annotation id="link">"ការកំណត់"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ផ្លាស់ទីប៊ូតុងទៅគែម ដើម្បីលាក់វាជាបណ្ដោះអាសន្ន"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ផ្លាស់ទីទៅខាងលើផ្នែកខាងឆ្វេង"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ផ្លាស់ទីទៅខាងលើផ្នែកខាងស្ដាំ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 78d086f..0b21c0f 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿ"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ಹೊಸ ಬಳಕೆದಾರರು"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ಅತಿಥಿಯನ್ನು ತೆಗೆದುಹಾಕುವುದೇ?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ಈ ಸೆಷನ್ನಲ್ಲಿನ ಎಲ್ಲ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ತೆಗೆದುಹಾಕಿ"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ಮತ್ತೆ ಸುಸ್ವಾಗತ, ಅತಿಥಿ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ನಿಮ್ಮ ಸೆಷನ್ ಮುಂದುವರಿಸಲು ಇಚ್ಚಿಸುವಿರಾ?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ಪ್ರಾರಂಭಿಸಿ"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ಸ್ಕ್ರೀನ್ನ ಅರ್ಧಭಾಗವನ್ನು ಝೂಮ್ ಮಾಡಿ"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ಸ್ವಿಚ್"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ಪ್ರವೇಶಿಸುವಿಕೆ ಬಟನ್, ಪ್ರವೇಶಿಸುವಿಕೆ ಗೆಸ್ಚರ್ ಅನ್ನು ಬದಲಾಯಿಸಿದೆ\n\n"<annotation id="link">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"ನೀವು ಪ್ರವೇಶಿಸುವಿಕೆ ಗೆಸ್ಚರ್ನಿಂದ ಬಟನ್ಗೆ ಬದಲಾಯಿಸಬಹುದು\n\n"<annotation id="link">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ಅದನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ಮರೆಮಾಡಲು ಅಂಚಿಗೆ ಬಟನ್ ಸರಿಸಿ"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ಎಡ ಮೇಲ್ಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ಬಲ ಮೇಲ್ಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 819250c4..80415d5 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"사용자 추가"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"신규 사용자"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"게스트를 삭제하시겠습니까?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"이 세션에 있는 모든 앱과 데이터가 삭제됩니다."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"삭제"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"게스트 세션 진행"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"세션을 계속 진행하시겠습니까?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"다시 시작"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"화면 일부 확대"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"전환"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"접근성 동작이 접근성 버튼으로 대체되었습니다\n\n"<annotation id="link">"설정 보기"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"접근성 동작을 버튼으로 전환할 수 있습니다.\n\n"<annotation id="link">"설정"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"버튼을 가장자리로 옮겨서 일시적으로 숨기세요"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"왼쪽 상단으로 이동"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"오른쪽 상단으로 이동"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index b5bbf21..2474fe1 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Колдонуучу кошуу"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Жаңы колдонуучу"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Конокту алып саласызбы?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана маалыматтар өчүрүлөт."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Өчүрүү"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Кайтып келишиңиз менен!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансыңызды улантасызбы?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Кайра баштоо"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Экрандын бир бөлүгүн чоңойтуу"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Которулуу"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Атайын мүмкүнчүлүктөр жаңсоосунун ордуна атайын мүмкүнчүлүктөр баскычы колдонулмакчы\n\n"<annotation id="link">"Жөндөөлөрдү көрүү"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Атайын мүмкүнчүлүктөр жаңсоосунан баскычка которула аласыз\n\n"<annotation id="link">"Жөндөөлөр"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Баскычты убактылуу жашыра туруу үчүн экрандын четине жылдырыңыз"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Жогорку сол жакка жылдыруу"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Жогорку оң жакка жылдырыңыз"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index ca4122e..106f7f2 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"ເພີ່ມຜູ້ໃຊ້"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ຜູ່ໃຊ້ໃໝ່"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ລຶບແຂກບໍ?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ແອັບຯແລະຂໍ້ມູນທັງໝົດໃນເຊດຊັນນີ້ຈະຖືກລຶບອອກ."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ລຶບ"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ຍິນດີຕ້ອນຮັບກັບມາ, ຜູ້ຢ້ຽມຢາມ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ທ່ານຕ້ອງການສືບຕໍ່ເຊດຊັນຂອງທ່ານບໍ່?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ເລີ່ມຕົ້ນໃຫມ່"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ຂະຫຍາຍບາງສ່ວນຂອງໜ້າຈໍ"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ສະຫຼັບ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ປຸ່ມການຊ່ວຍເຂົ້າເຖິງຖືກແທນທີ່ທ່າທາງຊ່ວຍເຂົ້າເຖິງແລ້ວ\n\n"<annotation id="link">"ເບິ່ງການຕັ້ງຄ່າ"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"ທ່ານສາມາດສະຫຼັບທ່າທາງການຊ່ວຍເຂົ້າເຖິງເປັນປຸ່ມໄດ້\n\n"<annotation id="link">"ການຕັ້ງຄ່າ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ຍ້າຍປຸ່ມໄປໃສ່ຂອບເພື່ອເຊື່ອງມັນຊົ່ວຄາວ"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ຍ້າຍຊ້າຍເທິງ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ຍ້າຍຂວາເທິງ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 65a41bb..44dc8bb 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -484,8 +484,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Pridėti naudotoją"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Naujas naudotojas"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Pašalinti svečią?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bus ištrintos visos šios sesijos programos ir duomenys."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Pašalinti"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Sveiki sugrįžę, svety!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Ar norite tęsti sesiją?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Pradėti iš naujo"</string>
@@ -1044,6 +1048,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Didinti ekrano dalį"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Perjungti"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Pritaikomumo gestas pakeistas pritaikomumo mygtuku\n\n"<annotation id="link">"Žr. nustatymus"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Galite pereiti nuo pritaikomumo gesto prie mygtuko.\n\n"<annotation id="link">"Nustatymai"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Perkelkite mygtuką prie krašto, kad laikinai jį paslėptumėte"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Perkelti į viršų kairėje"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Perkelti į viršų dešinėje"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 13de036..b846be4 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -482,8 +482,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Lietotāja pievienošana"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Jauns lietotājs"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vai noņemt viesi?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tiks dzēstas visas šīs sesijas lietotnes un dati."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Noņemt"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Laipni lūdzam atpakaļ, viesi!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vai vēlaties turpināt savu sesiju?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Sākt no sākuma"</string>
@@ -1039,6 +1043,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Palielināt ekrāna daļu"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Pārslēgt"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Pieejamības žests ir aizstāts ar pieejamības pogu\n\n"<annotation id="link">"Skatīt iestatījumus"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Varat pārslēgties no pieejamības žesta uz pogu.\n\n"<annotation id="link">"Iestatījumi"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Lai īslaicīgi paslēptu pogu, pārvietojiet to uz malu"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Pārvietot augšpusē pa kreisi"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Pārvietot augšpusē pa labi"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index b70e2e5..535da7a 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Додај корисник"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Нов корисник"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Да се отстрани гостинот?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Сите апликации и податоци во сесијата ќе се избришат."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Отстрани"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Добре дојде пак, гостине!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Дали сакате да продолжите со сесијата?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Почни одново"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Зголемувајте дел од екранот"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Префрли"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Копчето за пристапност го замени движењето за пристапност\n\n"<annotation id="link">"Прикажи поставки"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Може да го смените движењето за пристапност во копче\n\n"<annotation id="link">"Поставки"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Преместете го копчето до работ за да го сокриете привремено"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Премести горе лево"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Премести горе десно"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 746d6f4..74d087c 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"ഉപയോക്താവിനെ ചേര്ക്കുക"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"പുതിയ ഉപയോക്താവ്"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"അതിഥിയെ നീക്കംചെയ്യണോ?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ഈ സെഷനിലെ എല്ലാ ആപ്പുകളും ഡാറ്റയും ഇല്ലാതാക്കും."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"നീക്കംചെയ്യുക"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"അതിഥി, വീണ്ടും സ്വാഗതം!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"നിങ്ങളുടെ സെഷൻ തുടരണോ?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"പുനരാംരംഭിക്കുക"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"സ്ക്രീനിന്റെ ഭാഗം മാഗ്നിഫൈ ചെയ്യുക"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"മാറുക"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ഉപയോഗസഹായി ജെസ്ച്ചറിനെ മാറ്റി പകരം ഉപയോഗസഹായി ബട്ടൺ വന്നു\n\n"<annotation id="link">"ക്രമീകരണം കാണുക"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"നിങ്ങൾക്ക് ഉപയോഗസഹായി ജെസ്ച്ചറിൽ നിന്ന് ഒരു ബട്ടണിലേക്ക് മാറാനാകും\n\n"<annotation id="link">"ക്രമീകരണം"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"തൽക്കാലം മറയ്ക്കുന്നതിന് ബട്ടൺ അരുകിലേക്ക് നീക്കുക"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"മുകളിൽ ഇടതുഭാഗത്തേക്ക് നീക്കുക"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"മുകളിൽ വലതുഭാഗത്തേക്ക് നീക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 9732fbd..8dae31d 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Хэрэглэгч нэмэх"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Шинэ хэрэглэгч"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Зочныг хасах уу?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Энэ харилцан үйлдлийн бүх апп болон дата устах болно."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Хасах"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Эргэн тавтай морилно уу!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Та үргэлжлүүлэхийг хүсэж байна уу?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Дахин эхлүүлэх"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Дэлгэцийн нэг хэсгийг томруулах"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Сэлгэх"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Хандалтын товчлуурыг хандалтын зангаагаар сольсон\n\n"<annotation id="link">"Тохиргоо харах"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Та хандалтын зангаанаас товчлуур луу сэлгэх боломжтой\n\n"<annotation id="link">"Тохиргоо"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Үүнийг түр нуухын тулд товчлуурыг зах руу зөөнө үү"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Зүүн дээш зөөх"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Баруун дээш зөөх"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index cc7f740..3aae064 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"वापरकर्ता जोडा"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"नवीन वापरकर्ता"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"अतिथी काढायचे?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"या सत्रातील सर्व अॅप्स आणि डेटा हटवला जाईल."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"काढा"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"अतिथी, तुमचे पुन्हा स्वागत आहे!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"तुम्ही तुमचे सत्र सुरू ठेवू इच्छिता?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"येथून सुरू करा"</string>
@@ -1034,6 +1038,8 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीनचा काही भाग मॅग्निफाय करा"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"स्विच करा"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"अॅक्सेसिबिलिटी जेश्चर हे आता अॅक्सेसिबिलिटी बटण आहे \n\n"<annotation id="link">"सेटिंग्ज पाहा"</annotation></string>
+ <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
+ <skip />
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"बटण तात्पुरते लपवण्यासाठी ते कोपर्यामध्ये हलवा"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"वर डावीकडे हलवा"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"वर उजवीकडे हलवा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 1f97ef6..f3838c4 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Tambah pengguna"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Pengguna baharu"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Alih keluar tetamu?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua apl dan data dalam sesi ini akan dipadam."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Alih keluar"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Selamat kembali, tetamu!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Adakah anda ingin meneruskan sesi anda?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Mulakan semula"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Besarkan sebahagian skrin"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Tukar"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Butang kebolehaksesan menggantikan gerak isyarat kebolehaksesan\n\n"<annotation id="link">"Lihat tetapan"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Anda boleh beralih daripada gerak isyarat kebolehaksesan kepada butang\n\n"<annotation id="link">"Tetapan"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Gerakkan butang ke tepi untuk disembunyikan buat sementara waktu"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Alihkan ke atas sebelah kiri"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Alihkan ke atas sebelah kanan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 78bc991..9a8fc20 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"အသုံးပြုသူ ထည့်ရန်"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"အသုံးပြုသူ အသစ်"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ဧည့်သည်ကို ဖယ်မလား။"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ဒီချိတ်ဆက်မှု ထဲက အက်ပ်များ အားလုံး နှင့် ဒေတာကို ဖျက်ပစ်မည်။"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ဖယ်ထုတ်ပါ"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ဧည့်သည်ကို ပြန်လည် ကြိုဆိုပါသည်။"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"သင်၏ စက်ရှင်ကို ဆက်လုပ်လိုပါသလား။"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ပြန်စပါ"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ဖန်သားပြင် တစ်စိတ်တစ်ပိုင်းကို ချဲ့ပါ"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ခလုတ်"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"အများသုံးစွဲနိုင်မှုခလုတ်က အများသုံးစွဲနိုင်မှုလက်ဟန်ကို အစားထိုးသည်\n\n"<annotation id="link">"ဆက်တင်များကို ကြည့်ပါ"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"အများသုံးစွဲနိုင်မှု လက်ဟန်မှ ခလုတ်သို့ ပြောင်းနိုင်သည်\n\n"<annotation id="link">"ဆက်တင်များ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ခလုတ်ကို ယာယီဝှက်ရန် အစွန်းသို့ရွှေ့ပါ"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ဘယ်ဘက်ထိပ်သို့ ရွှေ့ရန်"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ညာဘက်ထိပ်သို့ ရွှေ့ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index c181089..71ae672 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Legg til brukere"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Ny bruker"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vil du fjerne gjesten?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle appene og all informasjon i denne økten slettes."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Fjern"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkommen tilbake, gjest!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vil du fortsette økten?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start på nytt"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Forstørr en del av skjermen"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Bytt"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Tilgjengelighet-knappen har erstattet tilgjengelighetsbevegelsen\n\n"<annotation id="link">"Se innstillingene"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Du kan bytte fra tilgjengelighetsbevegelsen til en knapp\n\n"<annotation id="link">"Innstillinger"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Flytt knappen til kanten for å skjule den midlertidig"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Flytt til øverst til venstre"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Flytt til øverst til høyre"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index a69be5d..0006f7f 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"प्रयोगकर्ता थप्नुहोस्"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"नयाँ प्रयोगकर्ता"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"अतिथि हटाउने हो?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"यो सत्रमा भएका सबै एपहरू र डेटा मेटाइने छ।"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"हटाउनुहोस्"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"तपाईंलाई फेरि स्वागत छ, अतिथि"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"तपाईं आफ्नो सत्र जारी गर्न चाहनुहुन्छ?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"सुरु गर्नुहोस्"</string>
@@ -1034,6 +1038,8 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रिनको केही भाग म्याग्निफाइ गर्नुहोस्"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"बदल्नुहोस्"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"एक्सेसिबिलिटी इसाराका स्थानमा एक्सेसिबिलिटी बटन प्रयोग हुन थालेको छ\n\n"<annotation id="link">"सेटिङ हेर्नुहोस्"</annotation></string>
+ <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
+ <skip />
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"यो बटन केही बेर नदेखिने पार्न किनारातिर सार्नुहोस्"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"सिरानको बायाँतिर सार्नुहोस्"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"सिरानको दायाँतिर सार्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index e91f0a0..944753a 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Gebruiker toevoegen"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nieuwe gebruiker"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Gast verwijderen?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps en gegevens in deze sessie worden verwijderd."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Verwijderen"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welkom terug, gast!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Wil je doorgaan met je sessie?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Opnieuw starten"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Deel van het scherm vergroten"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Schakelen"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"De knop Toegankelijkheid vervangt het toegankelijkheidsgebaar\n\n"<annotation id="link">"Instellingen bekijken"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Je kunt overschakelen van het toegankelijkheidsgebaar naar een knop\n\n"<annotation id="link">"Instellingen"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Knop naar de rand verplaatsen om deze tijdelijk te verbergen"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Naar linksboven verplaatsen"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Naar rechtsboven verplaatsen"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 739885d..1dcb143 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଯୋଗ କରନ୍ତୁ"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ଅତିଥିଙ୍କୁ କାଢ଼ିଦେବେ?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ଏହି ସେସନର ସମସ୍ତ ଆପ୍ ଓ ଡାଟା ଡିଲିଟ୍ ହୋଇଯିବ।"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"କାଢ଼ିଦିଅନ୍ତୁ"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ପୁଣି ସ୍ୱାଗତ, ଅତିଥି!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ଆପଣ ନିଜର ସେସନ୍ ଜାରି ରଖିବାକୁ ଚାହାଁନ୍ତି କି?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
@@ -1034,6 +1038,8 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ସ୍କ୍ରିନର ଅଂଶ ମାଗ୍ନିଫାଏ କରନ୍ତୁ"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ସ୍ୱିଚ୍ କରନ୍ତୁ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ଆକ୍ସେସିବିଲିଟୀ ଜେଶ୍ଚରକୁ ଆକ୍ସେସିବିଲିଟୀ ବଟନରେ ପରିବର୍ତ୍ତନ କରାଯାଇଛି\n\n"<annotation id="link">"ସେଟିଂସ୍ ଦେଖନ୍ତୁ"</annotation></string>
+ <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
+ <skip />
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ବଟନକୁ ଅସ୍ଥାୟୀ ଭାବେ ଲୁଚାଇବା ପାଇଁ ଏହାକୁ ଗୋଟିଏ ଧାରକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ଶୀର୍ଷ ବାମକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ଶୀର୍ଷ ଡାହାଣକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index deca3ff..0f687a1 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ਕੀ ਮਹਿਮਾਨ ਹਟਾਉਣਾ ਹੈ?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ਇਸ ਸੈਸ਼ਨ ਵਿੱਚ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਏਗਾ।"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ਹਟਾਓ"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ਮਹਿਮਾਨ, ਫਿਰ ਤੁਹਾਡਾ ਸੁਆਗਤ ਹੈ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ਕੀ ਤੁਸੀਂ ਆਪਣਾ ਸੈਸ਼ਨ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ਮੁੜ-ਸ਼ੁਰੂ ਕਰੋ"</string>
@@ -742,7 +746,7 @@
<string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"<b>ਸਥਿਤੀ:</b> ਦਰਜਾ ਵਧਾਇਆ ਗਿਆ"</string>
<string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>ਸਥਿਤੀ:</b> ਦਰਜਾ ਘਟਾਇਆ ਗਿਆ"</string>
<string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"ਗੱਲਬਾਤ ਸੂਚਨਾਵਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਵਜੋਂ ਦਿਖਾਉਂਦਾ ਹੈ"</string>
- <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"ਗੱਲਬਾਤ ਸੂਚਨਾਵਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ, ਬਬਲ ਵਜੋਂ ਦਿਖਾਉਂਦਾ ਹੈ"</string>
+ <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"ਗੱਲਬਾਤ ਸੂਚਨਾਵਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਵਜੋਂ ਦਿਖਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ, ਜੋ ਕਿ ਬਬਲ ਵਜੋਂ ਦਿਸਦੀਆਂ ਹਨ"</string>
<string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"ਗੱਲਬਾਤ ਸੂਚਨਾਵਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਵਜੋਂ ਦਿਖਾਉਂਦਾ ਹੈ, \'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਸੁਵਿਧਾ ਵਿੱਚ ਵੀ ਵਿਘਨ ਪੈ ਸਕਦਾ ਹੈ"</string>
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"ਗੱਲਬਾਤ ਸੂਚਨਾਵਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ, ਬਬਲ ਵਜੋਂ ਦਿਖਾਉਂਦਾ ਹੈ, \'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਸੁਵਿਧਾ ਵਿੱਚ ਵੀ ਵਿਘਨ ਪੈ ਸਕਦਾ ਹੈ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ਸੈਟਿੰਗਾਂ"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ਸਕ੍ਰੀਨ ਦੇ ਹਿੱਸੇ ਨੂੰ ਵੱਡਾ ਕਰੋ"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ਸਵਿੱਚ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨੂੰ ਪਹੁੰਚਯੋਗਤਾ ਸੰਕੇਤ ਨਾਲ ਬਦਲ ਦਿੱਤਾ ਗਿਆ\n\n"<annotation id="link">"ਸੈਟਿੰਗਾਂ ਦੇਖੋ"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"ਤੁਸੀਂ ਪਹੁੰਚਯੋਗਤਾ ਇਸ਼ਾਰੇ ਤੋਂ ਬਟਨ \'ਤੇ ਸਵਿੱਚ ਕਰ ਸਕਦੇ ਹੋ\n\n"<annotation id="link">"ਸੈਟਿੰਗਾਂ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ਬਟਨ ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਲੁਕਾਉਣ ਲਈ ਕਿਨਾਰੇ \'ਤੇ ਲਿਜਾਓ"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ਉੱਪਰ ਵੱਲ ਖੱਬੇ ਲਿਜਾਓ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ਉੱਪਰ ਵੱਲ ਸੱਜੇ ਲਿਜਾਓ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 217b2f2..e822d93 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -484,8 +484,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Dodaj użytkownika"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nowy użytkownik"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Usunąć gościa?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wszystkie aplikacje i dane w tej sesji zostaną usunięte."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Usuń"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Witaj ponownie, Gościu!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcesz kontynuować sesję?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Rozpocznij nową"</string>
@@ -1044,6 +1048,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Powiększ część ekranu"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Przełącz"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Przycisk ułatwień dostępu zastąpił gest ułatwień dostępu\n\n"<annotation id="link">"Wyświetl ustawienia"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Możesz przełączyć się z gestu na przycisk ułatwień dostępu.\n\n"<annotation id="link">"Ustawienia"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Przesuń przycisk do krawędzi, aby ukryć go tymczasowo"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Przenieś w lewy górny róg"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Przenieś w prawy górny róg"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 6077c54..ad41e55 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Adicionar usuário"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novo usuário"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remover visitante?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remover"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Você voltou, visitante!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Quer continuar a sessão?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte da tela"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Trocar"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"O botão de acessibilidade substituiu o gesto de acessibilidade\n\n"<annotation id="link">"Veja as configurações"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Você pode mudar do gesto de acessibilidade para um botão\n\n"<annotation id="link">"Configurações"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mova o botão para a borda para ocultá-lo temporariamente"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover para o canto superior esquerdo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover para o canto superior direito"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 2e7c629..738e916 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Adicionar utilizador"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novo utilizador"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remover o convidado?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todas as apps e dados desta sessão serão eliminados."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remover"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Bem-vindo de volta, convidado!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Pretende continuar a sessão?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte do ecrã"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Mudar"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"O botão Acessibilidade substituiu o gesto de acessibilidade\n\n"<annotation id="link">"Ver definições"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Pode mudar de um gesto de acessibilidade para um botão\n\n"<annotation id="link">"Definições"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mova o botão para a extremidade para o ocultar temporariamente"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover p/ parte sup. esquerda"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover parte superior direita"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 6077c54..ad41e55 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Adicionar usuário"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novo usuário"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remover visitante?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remover"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Você voltou, visitante!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Quer continuar a sessão?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte da tela"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Trocar"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"O botão de acessibilidade substituiu o gesto de acessibilidade\n\n"<annotation id="link">"Veja as configurações"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Você pode mudar do gesto de acessibilidade para um botão\n\n"<annotation id="link">"Configurações"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mova o botão para a borda para ocultá-lo temporariamente"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover para o canto superior esquerdo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover para o canto superior direito"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index d6c3756..3f9a576 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -482,8 +482,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Adăugați un utilizator"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Utilizator nou"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Ștergeți invitatul?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toate aplicațiile și datele din această sesiune vor fi șterse."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ștergeți"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Bine ați revenit în sesiunea pentru invitați!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vreți să continuați sesiunea?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Începeți din nou"</string>
@@ -1039,6 +1043,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Măriți o parte a ecranului"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Comutator"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Butonul de accesibilitate a înlocuit gestul de accesibilitate\n\n"<annotation id="link">"Vedeți setările"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Puteți trece de la gestul de accesibilitate la un buton\n\n"<annotation id="link">"Setări"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mutați butonul spre margine pentru a-l ascunde temporar"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mutați în stânga sus"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mutați în dreapta sus"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 33f47de..67091b9 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -484,8 +484,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Добавить пользователя"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Новый пользователь"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Удалить аккаунт гостя?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Все приложения и данные этого профиля будут удалены."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Удалить"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Рады видеть вас снова!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Продолжить сеанс?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Начать заново"</string>
@@ -1044,6 +1048,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увеличить часть экрана"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Переключить"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Жест заменен на кнопку специальных возможностей\n\n"<annotation id="link">"Открыть настройки"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Вы можете использовать кнопку вместо жеста.\n\n"<annotation id="link">"Настройки"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Чтобы временно скрыть кнопку, переместите ее к краю экрана"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перенести в левый верхний угол"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Перенести в правый верхний угол"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index cc27dfb..3a8b51c 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"පරිශීලකයෙක් එක් කරන්න"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"නව පරිශීලකයා"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"අමුත්තාන් ඉවත් කරන්නද?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"මෙම සැසියේ සියළුම යෙදුම් සහ දත්ත මකාවී."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ඉවත් කරන්න"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"නැවත සාදරයෙන් පිළිගනිමු, අමුත්තා!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ඔබගේ සැසිය දිගටම කරගෙන යෑමට ඔබට අවශ්යද?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"යළි මුල සිට අරඹන්න"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"තිරයේ කොටසක් විශාලනය කරන්න"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ස්විචය"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ප්රවේශ්යතා බොත්තම ප්රවේශ්යතා ඉංගිතය ප්රතිස්ථාපනය කළේය\n\n"<annotation id="link">"සැකසීම් බලන්න"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"ඔබට ප්රවේශ්යතා ඉංගිතයෙන් බොත්තම් \n\n"<annotation id="link">"සැකසීම්වලට"</annotation>" මාරු විය හැකිය"</string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"එය තාවකාලිකව සැඟවීමට බොත්තම දාරයට ගෙන යන්න"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ඉහළ වමට ගෙන යන්න"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ඉහළ දකුණට ගෙන යන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 0b74313..19a871e 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -484,8 +484,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Pridať používateľa"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nový používateľ"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Odstrániť hosťa?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Všetky aplikácie a údaje v tejto relácii budú odstránené."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Odstrániť"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Hosť, vitajte späť!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcete v relácii pokračovať?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Začať odznova"</string>
@@ -1044,6 +1048,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zväčšiť časť obrazovky"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Prepnúť"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Tlačidlo dostupnosti nahradilo gesto dostupnosti\n\n"<annotation id="link">"Zobraziť nastavenia"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Môžete prepnúť z gesta dostupnosti na tlačidlo\n\n"<annotation id="link">"Nastavenia"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Ak chcete tlačidlo dočasne skryť, presuňte ho k okraju"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Presunúť doľava nahor"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Presunúť doprava nahor"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index b4729f4..c58343a 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -484,8 +484,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Dodajanje uporabnika"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nov uporabnik"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Želite odstraniti gosta?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Vse aplikacije in podatki v tej seji bodo izbrisani."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Odstrani"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Znova pozdravljeni, gost!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite nadaljevati sejo?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Začni znova"</string>
@@ -1044,6 +1048,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Povečava dela zaslona"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Stikalo"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Gumb za funkcije za ljudi s posebnimi potrebami je zamenjal pripadajočo potezo.\n\n"<annotation id="link">"Ogled nastavitev"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Preklopite lahko s poteze na gumb za funkcije z ljudmi za posebne potrebe.\n\n"<annotation id="link">"Nastavitve"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Če želite gumb začasno skriti, ga premaknite ob rob."</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Premakni zgoraj levo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Premakni zgoraj desno"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 3ec14ea..334b2ed 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Shto përdorues"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Përdorues i ri"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Të hiqet i ftuari?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Të gjitha aplikacionet dhe të dhënat në këtë sesion do të fshihen."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Hiq"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Mirë se erdhe, i ftuar!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Dëshiron ta vazhdosh sesionin tënd?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Fillo nga e para"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zmadho një pjesë të ekranit"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Ndërro"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Butoni i qasshmërisë zëvendësoi gjestin e qasshmërisë\n\n"<annotation id="link">"Shiko cilësimet"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Mund të kalosh nga gjesti i qasshmërisë te një buton\n\n"<annotation id="link">"Cilësimet"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Zhvendose butonin në skaj për ta fshehur përkohësisht"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Zhvendos lart majtas"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Zhvendos lart djathtas"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 70fcb26..e4a1bea 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -482,8 +482,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Додај корисника"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Нови корисник"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Желите ли да уклоните госта?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Све апликације и подаци у овој сесији ће бити избрисани."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Уклони"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Добро дошли назад, госте!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Желите ли да наставите сесију?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Почни из почетка"</string>
@@ -1039,6 +1043,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увећајте део екрана"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Пређи"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Дугме Приступачност је заменило покрет за приступачност\n\n"<annotation id="link">"Прикажи подешавања"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Можете да пређете са покрета за приступачност на дугме\n\n"<annotation id="link">"Подешавања"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Померите дугме до ивице да бисте га привремено сакрили"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Премести горе лево"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Премести горе десно"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 6233370..3ceef49 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Lägg till användare"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Ny användare"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vill du ta bort gästen?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alla appar och data i denna session kommer att raderas."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ta bort"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Välkommen tillbaka som gäst!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vill du fortsätta sessionen?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Börja om"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Förstora en del av skärmen"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Reglage"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Tillgänglighetsknappen har ersatt tillgänglighetsrörelsen\n\n"<annotation id="link">"Visa inställningarna"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Du kan byta från tillgänglighetsrörelsen till en knapp\n\n"<annotation id="link">"Inställningar"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Flytta knappen till kanten för att dölja den tillfälligt"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Flytta högst upp till vänster"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Flytta högst upp till höger"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index f7e50ef..0a4e059 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Ongeza mtumiaji"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Mtumiaji mpya"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Ungependa kumwondoa mgeni?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Data na programu zote katika kipindi hiki zitafutwa."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ondoa"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Karibu tena mgeni!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Je, unataka kuendelea na kipindi chako?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Anza upya"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Kuza sehemu ya skrini"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Swichi"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Kitufe cha zana za ufikivu kimechukua nafasi ya ishara ya ufikivu\n\n"<annotation id="link">"Angalia mipangilio"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Unaweza kubadilisha uache kutumia ishara ya ufikivu ili utumie kitufe\n\n"<annotation id="link">"Mipangilio"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Sogeza kitufe kwenye ukingo ili ukifiche kwa muda"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Sogeza juu kushoto"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Sogeza juu kulia"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index df52b0e..5dc1581 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"பயனரைச் சேர்"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"புதியவர்"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"கெஸ்ட்டை அகற்றவா?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"இந்த அமர்வின் எல்லா ஆப்ஸும் தரவும் நீக்கப்படும்."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"அகற்று"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"நல்வரவு!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"உங்கள் அமர்வைத் தொடர விருப்பமா?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"மீண்டும் தொடங்கு"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"திரையின் ஒரு பகுதியைப் பெரிதாக்கும்"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ஸ்விட்ச்"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"அணுகல்தன்மை பட்டன் இப்போது அணுகல்தன்மை சைகையாக மாற்றப்பட்டுள்ளது\n\n"<annotation id="link">"அமைப்புகளில் காண்க"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"அணுகல்தன்மை சைகையிலிருந்து பட்டனுக்கு மாறிக்கொள்ளலாம்\n\n"<annotation id="link">"அமைப்புகள்"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"பட்டனைத் தற்காலிகமாக மறைக்க ஓரத்திற்கு நகர்த்தும்"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"மேலே இடதுபுறத்திற்கு நகர்த்து"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"மேலே வலதுபுறத்திற்கு நகர்த்து"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 84b33a9..348c37a 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"యూజర్ను జోడించండి"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"కొత్త వినియోగదారు"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"గెస్ట్ను తీసివేయాలా?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ఈ సెషన్లోని అన్ని యాప్లు మరియు డేటా తొలగించబడతాయి."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"తీసివేయి"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"గెస్ట్కు తిరిగి స్వాగతం!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"మీరు మీ సెషన్ని కొనసాగించాలనుకుంటున్నారా?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"మొదటి నుండి ప్రారంభించు"</string>
@@ -1034,6 +1038,8 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"స్క్రీన్లో భాగాన్ని మాగ్నిఫై చేయండి"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"స్విచ్ చేయి"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"యాక్సెసిబిలిటీ బటన్, యాక్సెసిబిలిటీ సంజ్ఞను భర్తీ చేసింది\n\n"<annotation id="link">"సెట్టింగ్లను చూడండి"</annotation></string>
+ <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
+ <skip />
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"తాత్కాలికంగా దానిని దాచడానికి బటన్ను చివరకు తరలించండి"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ఎగువ ఎడమ వైపునకు తరలించు"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ఎగువ కుడి వైపునకు తరలించు"</string>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 70bd850..2f0957c 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -33,6 +33,7 @@
<item>com.android.systemui.statusbar.tv.notifications.TvNotificationPanel</item>
<item>com.android.systemui.statusbar.tv.notifications.TvNotificationHandler</item>
<item>com.android.systemui.statusbar.tv.VpnStatusObserver</item>
+ <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
<item>com.android.systemui.usb.StorageNotification</item>
<item>com.android.systemui.power.PowerUI</item>
<item>com.android.systemui.media.RingtonePlayer</item>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 2b7bc58..d6eec3f 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"เพิ่มผู้ใช้"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ผู้ใช้ใหม่"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ต้องการนำผู้ใช้ชั่วคราวออกไหม"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ระบบจะลบแอปและข้อมูลทั้งหมดในเซสชันนี้"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"นำออก"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ยินดีต้อนรับผู้เข้าร่วมกลับมาอีกครั้ง"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"คุณต้องการอยู่ในเซสชันต่อไปไหม"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"เริ่มต้นใหม่"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ขยายบางส่วนของหน้าจอ"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"เปลี่ยน"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ปุ่มการช่วยเหลือพิเศษแทนที่ท่าทางสัมผัสการช่วยเหลือพิเศษแล้ว\n\n"<annotation id="link">"ดูการตั้งค่า"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"คุณสลับจากท่าทางสัมผัสเพื่อการเข้าถึงพิเศษไปที่ปุ่ม\n\n"<annotation id="link">"การตั้งค่า"</annotation>"ได้"</string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ย้ายปุ่มไปที่ขอบเพื่อซ่อนชั่วคราว"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ย้ายไปด้านซ้ายบน"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ย้ายไปด้านขวาบน"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 8db4e9e..0a7bdac 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Magdagdag ng user"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Bagong user"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Alisin ang bisita?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ide-delete ang lahat ng app at data sa session na ito."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Alisin"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome ulit, bisita!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Gusto mo bang ipagpatuloy ang iyong session?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Magsimulang muli"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"I-magnify ang isang bahagi ng screen"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Pinalitan ng button ng accessibility ang galaw ng accessibility\n\n"<annotation id="link">"Tingnan ang mga setting"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Puwede kang lumipat sa button mula sa galaw para sa accessibility\n\n"<annotation id="link">"Mga Setting"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Ilipat ang button sa gilid para pansamantala itong itago"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Ilipat sa kaliwa sa itaas"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Ilipat sa kanan sa itaas"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 568be8a..80e29fb 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Kullanıcı ekle"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Yeni kullanıcı"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Misafir oturumu kaldırılsın mı?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu oturumdaki tüm uygulamalar ve veriler silinecek."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Kaldır"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Misafir kullanıcı, tekrar hoşgeldiniz"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Oturumunuza devam etmek istiyor musunuz?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Baştan başla"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekranın bir parçasını büyütün"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Geç"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Erişilebilirlik hareketi, Erişilebilirlik düğmesi ile değiştirildi\n\n"<annotation id="link">"Ayarları görüntüle"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Erişilebilirlik hareketi yerine bir düğme kullanmaya geçebilirsiniz\n\n"<annotation id="link">"Ayarlar"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Düğmeyi geçici olarak gizlemek için kenara taşıyın"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Sol üste taşı"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Sağ üste taşı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 7aef252..89be129 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -484,8 +484,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Додати користувача"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Новий користувач"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Видалити гостя?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Скинути сеанс у режимі \"Гість\"?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усі додатки й дані з цього сеансу буде видалено."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Вийти"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Скинути"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"З поверненням!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Продовжити сеанс?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Почати знову"</string>
@@ -1044,6 +1046,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Збільшити частину екрана"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Перемкнути"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Замість жесту спеціальних можливостей тепер використовується кнопка\n\n"<annotation id="link">"Переглянути налаштування"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Ви можете використовувати кнопку замість жесту спеціальних можливостей\n\n"<annotation id="link">"Налаштування"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Щоб тимчасово сховати кнопку, перемістіть її на край екрана"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перемістити ліворуч угору"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Перемістити праворуч угору"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index b8911fd..930bb05 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"صارف کو شامل کریں"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"نیا صارف"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"مہمان کو ہٹائیں؟"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"اس سیشن میں موجود سبھی ایپس اور ڈیٹا کو حذف کر دیا جائے گا۔"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ہٹائیں"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"مہمان، پھر سے خوش آمدید!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"کیا آپ اپنا سیشن جاری رکھنا چاہتے ہیں؟"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"دوبارہ شروع کریں"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"اسکرین کا حصہ بڑا کریں"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"سوئچ کریں"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"ایکسیسبیلٹی بٹن کو ایکسیسبیلٹی اشارے سے بدل دیا گیا\n\n"<annotation id="link">"ترتیبات دیکھیں"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"آپ ایکسیسبیلٹی اشارے سے بٹن پر سوئچ کر سکتے ہیں\n\n"<annotation id="link">"ترتیبات"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"عارضی طور پر بٹن کو چھپانے کے لئے اسے کنارے پر لے جائیں"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"اوپر بائیں جانب لے جائیں"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"اوپر دائیں جانب لے جائيں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index f411938..df7f7cd 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -480,8 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Foydalanuvchi"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Yangi foydalanuvchi"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Mehmon olib tashlansinmi?"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Mehmon seansi tiklansinmi?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ushbu seansdagi barcha ilovalar va ma’lumotlar o‘chirib tashlanadi."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Olib tashlash"</string>
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Tiklash"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Xush kelibsiz, mehmon!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Seansni davom ettirmoqchimisiz?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Boshidan boshlansin"</string>
@@ -1034,6 +1036,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekran qismini kattalashtirish"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Almashtirish"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Maxsus imkoniyatlar tugmasi maxsus imkoniyatlar ishorasini almashtirdi\n\n"<annotation id="link">"Sozlamalarni ochish"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Siz maxsus imkoniyatlar ishorasi oʻrniga \n\n"<annotation id="link">"Sozlamalar"</annotation>" tugmasidan foydalanishingiz mumkin"</string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Vaqtinchalik berkitish uchun tugmani qirra tomon suring"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Yuqori chapga surish"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Yuqori oʻngga surish"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 1e10496..241cfb2 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Thêm người dùng"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Người dùng mới"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Xóa phiên khách?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tất cả ứng dụng và dữ liệu trong phiên này sẽ bị xóa."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Xóa"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Chào mừng bạn trở lại!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Bạn có muốn tiếp tục phiên của mình không?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Bắt đầu lại"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Phóng to một phần màn hình"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Chuyển"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Nút hỗ trợ tiếp cận đã thay thế cử chỉ hỗ trợ tiếp cận\n\n"<annotation id="link">"Xem chế độ cài đặt"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Bạn có thể chuyển từ cử chỉ hỗ trợ tiếp cận sang nút hỗ trợ tiếp cận\n\n"<annotation id="link">"Cài đặt"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Di chuyển nút sang cạnh để ẩn nút tạm thời"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Chuyển lên trên cùng bên trái"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Chuyển lên trên cùng bên phải"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 9272b8a..25cc331d 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"添加用户"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"新用户"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"要移除访客吗?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"此会话中的所有应用和数据都将被删除。"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"移除"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"访客,欢迎回来!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"要继续您的会话吗?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新开始"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大部分屏幕"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"切换"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"“无障碍”按钮已取代无障碍手势\n\n"<annotation id="link">"查看设置"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"您可以从使用无障碍手势改为使用按钮\n\n"<annotation id="link">"设置"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"将按钮移到边缘,即可暂时将其隐藏"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"移至左上角"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"移至右上角"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index fff99e4..5c58081 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"加入使用者"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"新使用者"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"移除訪客?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會被刪除。"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"移除"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"訪客您好,歡迎回來!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"您要繼續您的工作階段嗎?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新開始"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大部分螢幕畫面"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"切換"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"無障礙功能按鈕已取代無障礙手勢\n\n"<annotation id="link">"查看設定"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"您可以從無障礙手勢改為使用按鈕\n\n"<annotation id="link">"設定"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"將按鈕移到邊緣即可暫時隱藏"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"移去左上方"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"移去右上方"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 9a278fd..5c4c3b15 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"新增使用者"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"新使用者"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"移除訪客?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會遭到刪除。"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"移除"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"訪客你好,歡迎回來!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"你要繼續這個工作階段嗎?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新開始"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大局部螢幕畫面"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"切換"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"無障礙工具按鈕已取代無障礙手勢\n\n"<annotation id="link">"查看設定"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"你可以從無障礙手勢改為使用按鈕\n\n"<annotation id="link">"設定"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"將按鈕移到邊緣處即可暫時隱藏"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"移到左上方"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"移到右上方"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index a11c5a8..647102a 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -480,8 +480,12 @@
<string name="user_add_user" msgid="4336657383006913022">"Engeza umsebenzisi"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Umsebenzisi omusha"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Susa isivakashi?"</string>
+ <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
+ <skip />
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Zonke izinhlelo zokusebenza nedatha kulesi sikhathi zizosuswa."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Susa"</string>
+ <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
+ <skip />
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Siyakwamukela futhi, sivakashi!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Ingabe ufuna ukuqhubeka ngesikhathi sakho?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Qala phansi"</string>
@@ -1034,6 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Khulisa ingxenye eyesikrini"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Iswishi"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Inkinobho yokufinyeleleka ishintshaniswe ngokuthinta kokufinyeleleka\n\n"<annotation id="link">"Buka amasethingi"</annotation></string>
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Ungashintsha kusuka kunzwa yokufinyeleleka ukuya kunkinobho\n\n"<annotation id="link">"Amasethingi"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Hambisa inkinobho onqenqemeni ukuze uyifihle okwesikhashana"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Hamba phezulu kwesokunxele"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Hamba phezulu ngakwesokudla"</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 067d56f..d2ed601 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -143,6 +143,7 @@
<attr name="handleThickness" format="dimension" />
<attr name="handleColor" format="color" />
<attr name="scrimColor" format="color" />
+ <attr name="containerBackgroundColor" format="color" />
<attr name="isVertical" format="boolean" />
@@ -178,6 +179,7 @@
<attr name="handleThickness" />
<attr name="handleColor" />
<attr name="scrimColor" />
+ <attr name="containerBackgroundColor" />
</declare-styleable>
<declare-styleable name="MagnifierView">
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 82ce881..9678aff 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -426,7 +426,7 @@
<!-- Whether or not the dividing lines should be shown when the container is expanding and
collapsing. If this value is true, then the lines will only show when the container has
been completely expanded. -->
- <bool name="config_hideDividersDuringExpand">false</bool>
+ <bool name="config_hideDividersDuringExpand">true</bool>
<!-- Whether or not child notifications that are part of a group will have shadows. -->
<bool name="config_enableShadowOnChildNotifications">true</bool>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 91301df..83dbad1 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1148,12 +1148,18 @@
<!-- Title of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
<string name="guest_exit_guest_dialog_title">Remove guest?</string>
+ <!-- Title of the confirmation dialog when resetting guest session [CHAR LIMIT=NONE] -->
+ <string name="guest_reset_guest_dialog_title">Reset guest?</string>
+
<!-- Message of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
<string name="guest_exit_guest_dialog_message">All apps and data in this session will be deleted.</string>
<!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] -->
<string name="guest_exit_guest_dialog_remove">Remove</string>
+ <!-- Label for button in confirmation dialog when resetting guest session [CHAR LIMIT=35] -->
+ <string name="guest_reset_guest_dialog_remove">Reset</string>
+
<!-- Title of the notification when resuming an existing guest session [CHAR LIMIT=NONE] -->
<string name="guest_wipe_session_title">Welcome back, guest!</string>
@@ -2979,6 +2985,8 @@
<!-- Content description for a chip in the status bar showing that the user is currently on a phone call. [CHAR LIMIT=NONE] -->
<string name="ongoing_phone_call_content_description">Ongoing phone call</string>
+ <!-- Placeholder for string describing changes in global actions -->
+ <string name="global_actions_change_description" translatable="false"><xliff:g>%1$s</xliff:g></string>
<!-- URL for more information about changes in global actions -->
<string name="global_actions_change_url" translatable="false"></string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 97273a8..7a5a348 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -883,5 +883,6 @@
<style name="Wallet.Theme" parent="@android:style/Theme.DeviceDefault">
<item name="android:colorBackground">@android:color/system_neutral1_900</item>
+ <item name="android:itemBackground">@android:color/system_neutral1_800</item>
</style>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
index 42d2333..44271687 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
@@ -17,6 +17,7 @@
package com.android.systemui.shared.system;
import android.annotation.IntDef;
+import android.os.Build;
import android.view.View;
import com.android.internal.jank.InteractionJankMonitor;
@@ -58,23 +59,48 @@
public @interface CujType {
}
- public static boolean begin(View v, @CujType int cujType) {
- return InteractionJankMonitor.getInstance().begin(v, cujType);
+ /**
+ * Begin a trace session.
+ *
+ * @param v an attached view.
+ * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+ */
+ public static void begin(View v, @CujType int cujType) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
+ InteractionJankMonitor.getInstance().begin(v, cujType);
}
- public static boolean begin(View v, @CujType int cujType, long timeout) {
+ /**
+ * Begin a trace session.
+ *
+ * @param v an attached view.
+ * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+ * @param timeout duration to cancel the instrumentation in ms
+ */
+ public static void begin(View v, @CujType int cujType, long timeout) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
Configuration.Builder builder =
new Configuration.Builder(cujType)
.setView(v)
.setTimeout(timeout);
- return InteractionJankMonitor.getInstance().begin(builder);
+ InteractionJankMonitor.getInstance().begin(builder);
}
- public static boolean end(@CujType int cujType) {
- return InteractionJankMonitor.getInstance().end(cujType);
+ /**
+ * End a trace session.
+ *
+ * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+ */
+ public static void end(@CujType int cujType) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
+ InteractionJankMonitor.getInstance().end(cujType);
}
- public static boolean cancel(@CujType int cujType) {
- return InteractionJankMonitor.getInstance().cancel(cujType);
+ /**
+ * Cancel the trace session.
+ */
+ public static void cancel(@CujType int cujType) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
+ InteractionJankMonitor.getInstance().cancel(cujType);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f3a6d63..38f8f7a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -249,6 +249,16 @@
public void onStateChanged(int newState) {
mStatusBarState = newState;
}
+
+ @Override
+ public void onExpandedChanged(boolean isExpanded) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onShadeExpandedChanged(isExpanded);
+ }
+ }
+ }
};
HashMap<Integer, SimData> mSimDatas = new HashMap<>();
@@ -775,6 +785,9 @@
if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
|| msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
mFingerprintLockedOut = true;
+ if (isUdfpsEnrolled()) {
+ updateFingerprintListeningState();
+ }
}
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -2115,7 +2128,8 @@
|| (!getUserCanSkipBouncer(getCurrentUser())
&& !isEncryptedOrLockdown(getCurrentUser())
&& !userNeedsStrongAuth()
- && userDoesNotHaveTrust);
+ && userDoesNotHaveTrust
+ && !mFingerprintLockedOut);
return shouldListenKeyguardState && shouldListenUserState && shouldListenBouncerState
&& shouldListenUdfpsState;
}
@@ -3244,6 +3258,7 @@
pw.println(" strongAuthFlags=" + Integer.toHexString(strongAuthFlags));
pw.println(" trustManaged=" + getUserTrustIsManaged(userId));
pw.println(" udfpsEnrolled=" + isUdfpsEnrolled());
+ pw.println(" mFingerprintLockedOut=" + mFingerprintLockedOut);
pw.println(" enabledByUser=" + mBiometricEnabledForUser.get(userId));
if (isUdfpsEnrolled()) {
pw.println(" shouldListenForUdfps=" + shouldListenForFingerprint(true));
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index e561a5a..9849a7e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -333,4 +333,8 @@
*/
public void onRequireUnlockForNfc() { }
+ /**
+ * Called when the notification shade is expanded or collapsed.
+ */
+ public void onShadeExpandedChanged(boolean expanded) { }
}
diff --git a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
index 45a0ea1..0ae89bc 100644
--- a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
@@ -27,15 +27,14 @@
import android.content.pm.UserInfo;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
-import android.view.WindowManagerGlobal;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.qs.QSUserSwitcherEvent;
import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
/**
* Manages notification when a guest session is resumed.
@@ -47,9 +46,12 @@
private static final String SETTING_GUEST_HAS_LOGGED_IN = "systemui.guest_has_logged_in";
private Dialog mNewSessionDialog;
+ private final UserSwitcherController mUserSwitcherController;
private final UiEventLogger mUiEventLogger;
- public GuestResumeSessionReceiver(UiEventLogger uiEventLogger) {
+ public GuestResumeSessionReceiver(UserSwitcherController userSwitcherController,
+ UiEventLogger uiEventLogger) {
+ mUserSwitcherController = userSwitcherController;
mUiEventLogger = uiEventLogger;
}
@@ -90,7 +92,8 @@
int notFirstLogin = Settings.System.getIntForUser(
cr, SETTING_GUEST_HAS_LOGGED_IN, 0, userId);
if (notFirstLogin != 0) {
- mNewSessionDialog = new ResetSessionDialog(context, mUiEventLogger, userId);
+ mNewSessionDialog = new ResetSessionDialog(context, mUserSwitcherController,
+ mUiEventLogger, userId);
mNewSessionDialog.show();
} else {
Settings.System.putIntForUser(
@@ -99,54 +102,6 @@
}
}
- /**
- * Wipes the guest session.
- *
- * The guest must be the current user and its id must be {@param userId}.
- */
- private static void wipeGuestSession(Context context, int userId) {
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- UserInfo currentUser;
- try {
- currentUser = ActivityManager.getService().getCurrentUser();
- } catch (RemoteException e) {
- Log.e(TAG, "Couldn't wipe session because ActivityManager is dead");
- return;
- }
- if (currentUser.id != userId) {
- Log.w(TAG, "User requesting to start a new session (" + userId + ")"
- + " is not current user (" + currentUser.id + ")");
- return;
- }
- if (!currentUser.isGuest()) {
- Log.w(TAG, "User requesting to start a new session (" + userId + ")"
- + " is not a guest");
- return;
- }
-
- boolean marked = userManager.markGuestForDeletion(currentUser.id);
- if (!marked) {
- Log.w(TAG, "Couldn't mark the guest for deletion for user " + userId);
- return;
- }
- UserInfo newGuest = userManager.createGuest(context, currentUser.name);
-
- try {
- if (newGuest == null) {
- Log.e(TAG, "Could not create new guest, switching back to system user");
- ActivityManager.getService().switchUser(UserHandle.USER_SYSTEM);
- userManager.removeUser(currentUser.id);
- WindowManagerGlobal.getWindowManagerService().lockNow(null /* options */);
- return;
- }
- ActivityManager.getService().switchUser(newGuest.id);
- userManager.removeUser(currentUser.id);
- } catch (RemoteException e) {
- Log.e(TAG, "Couldn't wipe session because ActivityManager or WindowManager is dead");
- return;
- }
- }
-
private void cancelDialog() {
if (mNewSessionDialog != null && mNewSessionDialog.isShowing()) {
mNewSessionDialog.cancel();
@@ -160,10 +115,12 @@
private static final int BUTTON_WIPE = BUTTON_NEGATIVE;
private static final int BUTTON_DONTWIPE = BUTTON_POSITIVE;
+ private final UserSwitcherController mUserSwitcherController;
private final UiEventLogger mUiEventLogger;
private final int mUserId;
- ResetSessionDialog(Context context, UiEventLogger uiEventLogger, int userId) {
+ ResetSessionDialog(Context context, UserSwitcherController userSwitcherController,
+ UiEventLogger uiEventLogger, int userId) {
super(context);
setTitle(context.getString(R.string.guest_wipe_session_title));
@@ -175,6 +132,7 @@
setButton(BUTTON_DONTWIPE,
context.getString(R.string.guest_wipe_session_dontwipe), this);
+ mUserSwitcherController = userSwitcherController;
mUiEventLogger = uiEventLogger;
mUserId = userId;
}
@@ -183,7 +141,7 @@
public void onClick(DialogInterface dialog, int which) {
if (which == BUTTON_WIPE) {
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_WIPE);
- wipeGuestSession(getContext(), mUserId);
+ mUserSwitcherController.removeGuestUser(mUserId, UserHandle.USER_NULL);
dismiss();
} else if (which == BUTTON_DONTWIPE) {
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_CONTINUE);
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 64a683e..a68f796 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -130,10 +130,7 @@
.getBounds();
mHeight = window.height();
mWidth = window.width();
- mMiniBitmap = null;
- if (mWorker != null && mWorker.getThreadHandler() != null) {
- mWorker.getThreadHandler().post(this::updateMiniBitmap);
- }
+ mRenderer.setOnBitmapChanged(this::updateMiniBitmap);
}
EglHelper getEglHelperInstance() {
@@ -177,20 +174,19 @@
mPageOffset = (1 - imgWidth) / (float) (mPages - 1);
}
- private void updateMiniBitmap() {
- mRenderer.useBitmap(b -> {
- int size = Math.min(b.getWidth(), b.getHeight());
- float scale = 1.0f;
- if (size > MIN_SURFACE_WIDTH) {
- scale = (float) MIN_SURFACE_WIDTH / (float) size;
- }
- mImgHeight = b.getHeight();
- mImgWidth = b.getWidth();
- mMiniBitmap = Bitmap.createScaledBitmap(b, (int) Math.max(scale * b.getWidth(), 1),
- (int) Math.max(scale * b.getHeight(), 1), false);
- computeAndNotifyLocalColors(mLocalColorsToAdd, mMiniBitmap);
- mLocalColorsToAdd.clear();
- });
+ private void updateMiniBitmap(Bitmap b) {
+ if (b == null) return;
+ int size = Math.min(b.getWidth(), b.getHeight());
+ float scale = 1.0f;
+ if (size > MIN_SURFACE_WIDTH) {
+ scale = (float) MIN_SURFACE_WIDTH / (float) size;
+ }
+ mImgHeight = b.getHeight();
+ mImgWidth = b.getWidth();
+ mMiniBitmap = Bitmap.createScaledBitmap(b, (int) Math.max(scale * b.getWidth(), 1),
+ (int) Math.max(scale * b.getHeight(), 1), false);
+ computeAndNotifyLocalColors(mLocalColorsToAdd, mMiniBitmap);
+ mLocalColorsToAdd.clear();
}
private void updateSurfaceSize() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index cf577a3..77cca2e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -24,9 +24,13 @@
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.settingslib.Utils
+import com.android.systemui.statusbar.CircleReveal
+import com.android.systemui.statusbar.LiftReveal
+import com.android.systemui.statusbar.LightRevealEffect
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
+import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.StatusBar
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
@@ -49,10 +53,12 @@
private val commandRegistry: CommandRegistry,
private val notificationShadeWindowController: NotificationShadeWindowController,
private val bypassController: KeyguardBypassController,
+ private val biometricUnlockController: BiometricUnlockController,
rippleView: AuthRippleView?
) : ViewController<AuthRippleView>(rippleView) {
var fingerprintSensorLocation: PointF? = null
private var faceSensorLocation: PointF? = null
+ private var circleReveal: LightRevealEffect? = null
@VisibleForTesting
public override fun onViewAttached() {
@@ -96,15 +102,47 @@
private fun showRipple() {
notificationShadeWindowController.setForcePluginOpen(true, this)
- mView.startRipple(Runnable {
- notificationShadeWindowController.setForcePluginOpen(false, this)
- })
+ val biometricUnlockMode = biometricUnlockController.mode
+ val useCircleReveal = circleReveal != null &&
+ (biometricUnlockMode == BiometricUnlockController.MODE_WAKE_AND_UNLOCK ||
+ biometricUnlockMode == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING ||
+ biometricUnlockMode == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM)
+ val lightRevealScrim = statusBar.lightRevealScrim
+ if (useCircleReveal) {
+ lightRevealScrim?.revealEffect = circleReveal!!
+ }
+
+ mView.startRipple(
+ /* end runnable */
+ Runnable {
+ notificationShadeWindowController.setForcePluginOpen(false, this)
+ if (useCircleReveal) {
+ lightRevealScrim?.revealEffect = LiftReveal
+ }
+ },
+ /* circleReveal */
+ if (useCircleReveal) {
+ lightRevealScrim
+ } else {
+ null
+ }
+ )
}
fun updateSensorLocation() {
fingerprintSensorLocation = authController.fingerprintSensorLocation
faceSensorLocation = authController.faceAuthSensorLocation
- statusBar.updateCircleReveal()
+ fingerprintSensorLocation?.let {
+ circleReveal = CircleReveal(
+ it.x,
+ it.y,
+ 0f,
+ Math.max(
+ Math.max(it.x, statusBar.displayWidth - it.x),
+ Math.max(it.y, statusBar.displayHeight - it.y)
+ )
+ )
+ }
}
private fun updateRippleColor() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 75373ab..dd73c4f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -31,6 +31,7 @@
import android.view.View
import android.view.animation.PathInterpolator
import com.android.internal.graphics.ColorUtils
+import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.charging.RippleShader
private const val RIPPLE_ANIMATION_DURATION: Long = 1533
@@ -70,51 +71,79 @@
.toFloat()
}
- fun startRipple(onAnimationEnd: Runnable?) {
+ fun startRipple(onAnimationEnd: Runnable?, lightReveal: LightRevealScrim?) {
if (rippleInProgress) {
return // Ignore if ripple effect is already playing
}
- val animator = ValueAnimator.ofFloat(0f, 1f)
- animator.interpolator = PathInterpolator(0.4f, 0f, 0f, 1f)
- animator.duration = RIPPLE_ANIMATION_DURATION
- animator.addUpdateListener { animator ->
- val now = animator.currentPlayTime
- rippleShader.progress = animator.animatedValue as Float
- rippleShader.time = now.toFloat()
- rippleShader.distortionStrength = 1 - rippleShader.progress
- invalidate()
- }
- val alphaInAnimator = ValueAnimator.ofInt(0, 127)
- alphaInAnimator.duration = 167
- alphaInAnimator.addUpdateListener { alphaInAnimator ->
- rippleShader.color = ColorUtils.setAlphaComponent(rippleShader.color,
- alphaInAnimator.animatedValue as Int)
- invalidate()
- }
- val alphaOutAnimator = ValueAnimator.ofInt(127, 0)
- alphaOutAnimator.startDelay = 417
- alphaOutAnimator.duration = 1116
- alphaOutAnimator.addUpdateListener { alphaOutAnimator ->
- rippleShader.color = ColorUtils.setAlphaComponent(rippleShader.color,
- alphaOutAnimator.animatedValue as Int)
- invalidate()
+ val rippleAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
+ interpolator = PathInterpolator(0.4f, 0f, 0f, 1f)
+ duration = RIPPLE_ANIMATION_DURATION
+ addUpdateListener { animator ->
+ val now = animator.currentPlayTime
+ rippleShader.progress = animator.animatedValue as Float
+ rippleShader.time = now.toFloat()
+
+ lightReveal?.revealAmount = animator.animatedValue as Float
+ invalidate()
+ }
}
- val animatorSet = AnimatorSet()
- animatorSet.playTogether(animator, alphaInAnimator, alphaOutAnimator)
- animatorSet.addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- onAnimationEnd?.run()
- rippleInProgress = false
- visibility = GONE
+ val revealAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
+ interpolator = rippleAnimator.interpolator
+ startDelay = 10
+ duration = rippleAnimator.duration
+ addUpdateListener { animator ->
+ lightReveal?.revealAmount = animator.animatedValue as Float
}
- })
+ }
+
+ val alphaInAnimator = ValueAnimator.ofInt(0, 127).apply {
+ duration = 167
+ addUpdateListener { animator ->
+ rippleShader.color = ColorUtils.setAlphaComponent(
+ rippleShader.color,
+ animator.animatedValue as Int
+ )
+ invalidate()
+ }
+ }
+
+ val alphaOutAnimator = ValueAnimator.ofInt(127, 0).apply {
+ startDelay = 417
+ duration = 1116
+ addUpdateListener { animator ->
+ rippleShader.color = ColorUtils.setAlphaComponent(
+ rippleShader.color,
+ animator.animatedValue as Int
+ )
+ invalidate()
+ }
+ }
+
+ val animatorSet = AnimatorSet().apply {
+ playTogether(
+ rippleAnimator,
+ revealAnimator,
+ alphaInAnimator,
+ alphaOutAnimator
+ )
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationStart(animation: Animator?) {
+ rippleInProgress = true
+ visibility = VISIBLE
+ }
+
+ override fun onAnimationEnd(animation: Animator?) {
+ onAnimationEnd?.run()
+ rippleInProgress = false
+ visibility = GONE
+ }
+ })
+ }
// TODO (b/185124905): custom haptic TBD
// vibrate()
animatorSet.start()
- visibility = VISIBLE
- rippleInProgress = true
}
fun setColor(color: Int) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsSurfaceView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsSurfaceView.java
index 6a6f57a..f8be35a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsSurfaceView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsSurfaceView.java
@@ -55,6 +55,7 @@
@NonNull private final SurfaceHolder mHolder;
@NonNull private final Paint mSensorPaint;
@NonNull private final SimpleDrawable mIlluminationDotDrawable;
+ private final int mOnIlluminatedDelayMs;
private final @HbmType int mHbmType;
@NonNull private RectF mSensorRect;
@@ -82,6 +83,9 @@
canvas.drawOval(mSensorRect, mSensorPaint);
};
+ mOnIlluminatedDelayMs = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_udfps_illumination_transition_ms);
+
if (Build.IS_ENG || Build.IS_USERDEBUG) {
mHbmType = Settings.Secure.getIntForUser(mContext.getContentResolver(),
SETTING_HBM_TYPE, DEFAULT_HBM_TYPE, UserHandle.USER_CURRENT);
@@ -107,9 +111,8 @@
}
if (onIlluminatedRunnable != null) {
// No framework API can reliably tell when a frame reaches the panel. A timeout
- // is the safest solution. The frame should be displayed within 3 refresh
- // cycles, which on a 60 Hz panel equates to 50 milliseconds.
- postDelayed(onIlluminatedRunnable, 50 /* delayMillis */);
+ // is the safest solution.
+ postDelayed(onIlluminatedRunnable, mOnIlluminatedDelayMs);
} else {
Log.w(TAG, "startIllumination | onIlluminatedRunnable is null");
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index ff95604..7b34e52 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -38,6 +38,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.doze.DozeMachine.State;
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
@@ -96,6 +97,7 @@
private long mNotificationPulseTime;
private boolean mPulsePending;
+ private Runnable mAodInterruptRunnable;
/** see {@link #onProximityFar} prox for callback */
private boolean mWantProxSensor;
@@ -303,11 +305,16 @@
} else if (isPickup) {
gentleWakeUp(pulseReason);
} else if (isUdfpsLongPress) {
+ final State state = mMachine.getState();
+ if (state == State.DOZE_AOD || state == State.DOZE) {
+ // Since the gesture won't be received by the UDFPS view, we need to
+ // manually inject an event once the display is ON
+ mAodInterruptRunnable = () ->
+ mAuthController.onAodInterrupt((int) screenX, (int) screenY,
+ rawValues[3] /* major */, rawValues[4] /* minor */);
+ }
+
requestPulse(DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS, true, null);
- // Since the gesture won't be received by the UDFPS view, manually inject an
- // event.
- mAuthController.onAodInterrupt((int) screenX, (int) screenY,
- rawValues[3] /* major */, rawValues[4] /* minor */);
} else {
mDozeHost.extendPulse(pulseReason);
}
@@ -439,6 +446,7 @@
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
switch (newState) {
case INITIALIZED:
+ mAodInterruptRunnable = null;
sWakeDisplaySensorState = true;
mBroadcastReceiver.register(mBroadcastDispatcher);
mDozeHost.addCallback(mHostCallback);
@@ -448,6 +456,7 @@
break;
case DOZE:
case DOZE_AOD:
+ mAodInterruptRunnable = null;
mWantProxSensor = newState != DozeMachine.State.DOZE;
mWantSensors = true;
mWantTouchScreenSensors = true;
@@ -494,6 +503,11 @@
|| state == Display.STATE_DOZE_SUSPEND || state == Display.STATE_OFF;
mDozeSensors.setProxListening(mWantProxSensor && lowPowerStateOrOff);
mDozeSensors.setListening(mWantSensors, mWantTouchScreenSensors, lowPowerStateOrOff);
+
+ if (mAodInterruptRunnable != null && state == Display.STATE_ON) {
+ mAodInterruptRunnable.run();
+ mAodInterruptRunnable = null;
+ }
}
/**
@@ -576,6 +590,8 @@
@Override
public void dump(PrintWriter pw) {
+ pw.println(" mAodInterruptRunnable=" + mAodInterruptRunnable);
+
pw.print(" notificationPulseTime=");
pw.println(Formatter.formatShortElapsedTime(mContext, mNotificationPulseTime));
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index ff3cb21..fbe06b0 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -21,6 +21,7 @@
import android.app.AlarmManager;
import android.content.Context;
+import android.content.res.Configuration;
import android.os.Handler;
import android.os.SystemClock;
import android.provider.Settings;
@@ -34,6 +35,7 @@
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.AlarmTimeout;
import com.android.systemui.util.wakelock.WakeLock;
@@ -48,7 +50,8 @@
* The policy controlling doze.
*/
@DozeScope
-public class DozeUi implements DozeMachine.Part, TunerService.Tunable {
+public class DozeUi implements DozeMachine.Part, TunerService.Tunable,
+ ConfigurationController.ConfigurationListener {
// if enabled, calls dozeTimeTick() whenever the time changes:
private static final boolean BURN_IN_TESTING_ENABLED = false;
private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
@@ -63,6 +66,7 @@
private final DozeLog mDozeLog;
private final Lazy<StatusBarStateController> mStatusBarStateController;
private final TunerService mTunerService;
+ private final ConfigurationController mConfigurationController;
private boolean mKeyguardShowing;
private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback =
@@ -84,6 +88,11 @@
mHandler.post(mWakeLock.wrap(() -> {}));
}
}
+
+ @Override
+ public void onShadeExpandedChanged(boolean expanded) {
+ updateAnimateScreenOff();
+ }
};
private long mLastTimeTickElapsed = 0;
@@ -93,7 +102,8 @@
WakeLock wakeLock, DozeHost host, @Main Handler handler,
DozeParameters params, KeyguardUpdateMonitor keyguardUpdateMonitor,
DozeLog dozeLog, TunerService tunerService,
- Lazy<StatusBarStateController> statusBarStateController) {
+ Lazy<StatusBarStateController> statusBarStateController,
+ ConfigurationController configurationController) {
mContext = context;
mWakeLock = wakeLock;
mHost = host;
@@ -107,11 +117,15 @@
mStatusBarStateController = statusBarStateController;
mTunerService.addTunable(this, Settings.Secure.DOZE_ALWAYS_ON);
+
+ mConfigurationController = configurationController;
+ mConfigurationController.addCallback(this);
}
@Override
public void destroy() {
mTunerService.removeTunable(this);
+ mConfigurationController.removeCallback(this);
}
@Override
@@ -274,4 +288,9 @@
updateAnimateScreenOff();
}
}
+
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ updateAnimateScreenOff();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 1fb36d7..bb44b09 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -30,6 +30,7 @@
import android.app.trust.TrustManager;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
@@ -113,48 +114,101 @@
@VisibleForTesting
boolean mShowLockScreenCards = false;
+ private final KeyguardStateController.Callback mKeyguardStateControllerListener =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onUnlockedChanged() {
+ if (mDialog != null) {
+ ActionsDialog dialog = (ActionsDialog) mDialog;
+ boolean unlocked = mKeyguardStateController.isUnlocked();
+ if (dialog.mWalletViewController != null) {
+ dialog.mWalletViewController.onDeviceLockStateChanged(!unlocked);
+ }
+
+ if (unlocked) {
+ dialog.hideLockMessage();
+ }
+ }
+ }
+ };
+
+ private final ContentObserver mSettingsObserver = new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ onPowerMenuLockScreenSettingsChanged();
+ }
+ };
+
/**
* @param context everything needs a context :(
*/
@Inject
- public GlobalActionsDialog(Context context, GlobalActionsManager windowManagerFuncs,
- AudioManager audioManager, IDreamManager iDreamManager,
- DevicePolicyManager devicePolicyManager, LockPatternUtils lockPatternUtils,
+ public GlobalActionsDialog(
+ Context context,
+ GlobalActionsManager windowManagerFuncs,
+ AudioManager audioManager,
+ IDreamManager iDreamManager,
+ DevicePolicyManager devicePolicyManager,
+ LockPatternUtils lockPatternUtils,
BroadcastDispatcher broadcastDispatcher,
TelephonyListenerManager telephonyListenerManager,
- GlobalSettings globalSettings, SecureSettings secureSettings,
- @Nullable Vibrator vibrator, @Main Resources resources,
- ConfigurationController configurationController, ActivityStarter activityStarter,
- KeyguardStateController keyguardStateController, UserManager userManager,
- TrustManager trustManager, IActivityManager iActivityManager,
- @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger,
- NotificationShadeDepthController depthController, SysuiColorExtractor colorExtractor,
+ GlobalSettings globalSettings,
+ SecureSettings secureSettings,
+ @Nullable Vibrator vibrator,
+ @Main Resources resources,
+ ConfigurationController configurationController,
+ ActivityStarter activityStarter,
+ KeyguardStateController keyguardStateController,
+ UserManager userManager,
+ TrustManager trustManager,
+ IActivityManager iActivityManager,
+ @Nullable TelecomManager telecomManager,
+ MetricsLogger metricsLogger,
+ NotificationShadeDepthController depthController,
+ SysuiColorExtractor colorExtractor,
IStatusBarService statusBarService,
NotificationShadeWindowController notificationShadeWindowController,
IWindowManager iWindowManager,
@Background Executor backgroundExecutor,
UiEventLogger uiEventLogger,
- RingerModeTracker ringerModeTracker, SysUiState sysUiState, @Main Handler handler,
+ RingerModeTracker ringerModeTracker,
+ SysUiState sysUiState,
+ @Main Handler handler,
+ PackageManager packageManager,
StatusBar statusBar) {
- super(context, windowManagerFuncs,
- audioManager, iDreamManager,
- devicePolicyManager, lockPatternUtils,
- broadcastDispatcher, telephonyListenerManager,
- globalSettings, secureSettings,
- vibrator, resources,
+ super(context,
+ windowManagerFuncs,
+ audioManager,
+ iDreamManager,
+ devicePolicyManager,
+ lockPatternUtils,
+ broadcastDispatcher,
+ telephonyListenerManager,
+ globalSettings,
+ secureSettings,
+ vibrator,
+ resources,
configurationController,
- keyguardStateController, userManager,
- trustManager, iActivityManager,
- telecomManager, metricsLogger,
- depthController, colorExtractor,
+ keyguardStateController,
+ userManager,
+ trustManager,
+ iActivityManager,
+ telecomManager,
+ metricsLogger,
+ depthController,
+ colorExtractor,
statusBarService,
notificationShadeWindowController,
iWindowManager,
backgroundExecutor,
uiEventLogger,
null,
- ringerModeTracker, sysUiState, handler, statusBar);
+ ringerModeTracker,
+ sysUiState,
+ handler,
+ packageManager,
+ statusBar);
mLockPatternUtils = lockPatternUtils;
mKeyguardStateController = keyguardStateController;
@@ -164,34 +218,22 @@
mNotificationShadeWindowController = notificationShadeWindowController;
mSysUiState = sysUiState;
mActivityStarter = activityStarter;
- keyguardStateController.addCallback(new KeyguardStateController.Callback() {
- @Override
- public void onUnlockedChanged() {
- if (mDialog != null) {
- ActionsDialog dialog = (ActionsDialog) mDialog;
- boolean unlocked = mKeyguardStateController.isUnlocked();
- if (dialog.mWalletViewController != null) {
- dialog.mWalletViewController.onDeviceLockStateChanged(!unlocked);
- }
- if (unlocked) {
- dialog.hideLockMessage();
- }
- }
- }
- });
+ mKeyguardStateController.addCallback(mKeyguardStateControllerListener);
// Listen for changes to show pay on the power menu while locked
onPowerMenuLockScreenSettingsChanged();
mGlobalSettings.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT),
false /* notifyForDescendants */,
- new ContentObserver(handler) {
- @Override
- public void onChange(boolean selfChange) {
- onPowerMenuLockScreenSettingsChanged();
- }
- });
+ mSettingsObserver);
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ mKeyguardStateController.removeCallback(mKeyguardStateControllerListener);
+ mGlobalSettings.unregisterContentObserver(mSettingsObserver);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index ad920cb..f30d6b1 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -177,6 +177,7 @@
private final IDreamManager mDreamManager;
private final DevicePolicyManager mDevicePolicyManager;
private final LockPatternUtils mLockPatternUtils;
+ private final TelephonyListenerManager mTelephonyListenerManager;
private final KeyguardStateController mKeyguardStateController;
private final BroadcastDispatcher mBroadcastDispatcher;
protected final GlobalSettings mGlobalSettings;
@@ -308,25 +309,38 @@
* @param context everything needs a context :(
*/
@Inject
- public GlobalActionsDialogLite(Context context, GlobalActionsManager windowManagerFuncs,
- AudioManager audioManager, IDreamManager iDreamManager,
- DevicePolicyManager devicePolicyManager, LockPatternUtils lockPatternUtils,
+ public GlobalActionsDialogLite(
+ Context context,
+ GlobalActionsManager windowManagerFuncs,
+ AudioManager audioManager,
+ IDreamManager iDreamManager,
+ DevicePolicyManager devicePolicyManager,
+ LockPatternUtils lockPatternUtils,
BroadcastDispatcher broadcastDispatcher,
TelephonyListenerManager telephonyListenerManager,
- GlobalSettings globalSettings, SecureSettings secureSettings,
- @Nullable Vibrator vibrator, @Main Resources resources,
+ GlobalSettings globalSettings,
+ SecureSettings secureSettings,
+ @Nullable Vibrator vibrator,
+ @Main Resources resources,
ConfigurationController configurationController,
- KeyguardStateController keyguardStateController, UserManager userManager,
- TrustManager trustManager, IActivityManager iActivityManager,
- @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger,
- NotificationShadeDepthController depthController, SysuiColorExtractor colorExtractor,
+ KeyguardStateController keyguardStateController,
+ UserManager userManager,
+ TrustManager trustManager,
+ IActivityManager iActivityManager,
+ @Nullable TelecomManager telecomManager,
+ MetricsLogger metricsLogger,
+ NotificationShadeDepthController depthController,
+ SysuiColorExtractor colorExtractor,
IStatusBarService statusBarService,
NotificationShadeWindowController notificationShadeWindowController,
IWindowManager iWindowManager,
@Background Executor backgroundExecutor,
UiEventLogger uiEventLogger,
GlobalActionsInfoProvider infoProvider,
- RingerModeTracker ringerModeTracker, SysUiState sysUiState, @Main Handler handler,
+ RingerModeTracker ringerModeTracker,
+ SysUiState sysUiState,
+ @Main Handler handler,
+ PackageManager packageManager,
StatusBar statusBar) {
mContext = context;
mWindowManagerFuncs = windowManagerFuncs;
@@ -334,6 +348,7 @@
mDreamManager = iDreamManager;
mDevicePolicyManager = devicePolicyManager;
mLockPatternUtils = lockPatternUtils;
+ mTelephonyListenerManager = telephonyListenerManager;
mKeyguardStateController = keyguardStateController;
mBroadcastDispatcher = broadcastDispatcher;
mGlobalSettings = globalSettings;
@@ -356,7 +371,7 @@
mRingerModeTracker = ringerModeTracker;
mSysUiState = sysUiState;
mMainHandler = handler;
- mSmallestScreenWidthDp = mContext.getResources().getConfiguration().smallestScreenWidthDp;
+ mSmallestScreenWidthDp = resources.getConfiguration().smallestScreenWidthDp;
mStatusBar = statusBar;
// receive broadcasts
@@ -366,11 +381,10 @@
filter.addAction(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter);
- mHasTelephony =
- context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+ mHasTelephony = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
// get notified of phone state changes
- telephonyListenerManager.addServiceStateListener(mPhoneStateListener);
+ mTelephonyListenerManager.addServiceStateListener(mPhoneStateListener);
mGlobalSettings.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
mAirplaneModeObserver);
@@ -390,6 +404,16 @@
mConfigurationController.addCallback(this);
}
+ /**
+ * Clean up callbacks
+ */
+ public void destroy() {
+ mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver);
+ mTelephonyListenerManager.removeServiceStateListener(mPhoneStateListener);
+ mGlobalSettings.unregisterContentObserver(mAirplaneModeObserver);
+ mConfigurationController.removeCallback(this);
+ }
+
protected Context getContext() {
return mContext;
}
@@ -689,14 +713,6 @@
mDialog.refreshDialog();
}
}
-
- /**
- * Clean up callbacks
- */
- public void destroy() {
- mConfigurationController.removeCallback(this);
- }
-
/**
* Implements {@link GlobalActionsPanelPlugin.Callbacks#dismissGlobalActionsMenu()}, which is
* called when the quick access wallet requests dismissal.
@@ -844,6 +860,8 @@
mMetricsLogger.action(MetricsEvent.ACTION_EMERGENCY_DIALER_FROM_POWER_MENU);
mUiEventLogger.log(GlobalActionsEvent.GA_EMERGENCY_DIALER_PRESS);
if (mTelecomManager != null) {
+ // Close shade so user sees the activity
+ mStatusBar.collapseShade();
Intent intent = mTelecomManager.createLaunchEmergencyDialerIntent(
null /* number */);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -974,6 +992,8 @@
Log.w(TAG, "Bugreport handler could not be launched");
mIActivityManager.requestInteractiveBugReport();
}
+ // Close shade so user sees the activity
+ mStatusBar.collapseShade();
} catch (RemoteException e) {
}
}
@@ -992,6 +1012,8 @@
mMetricsLogger.action(MetricsEvent.ACTION_BUGREPORT_FROM_POWER_MENU_FULL);
mUiEventLogger.log(GlobalActionsEvent.GA_BUGREPORT_LONG_PRESS);
mIActivityManager.requestFullBugReport();
+ // Close shade so user sees the activity
+ mStatusBar.collapseShade();
} catch (RemoteException e) {
}
return false;
@@ -2018,7 +2040,7 @@
}
};
- private ContentObserver mAirplaneModeObserver = new ContentObserver(mMainHandler) {
+ private final ContentObserver mAirplaneModeObserver = new ContentObserver(mMainHandler) {
@Override
public void onChange(boolean selfChange) {
onAirplaneModeChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 178a74c..e37d3d5 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -32,7 +32,6 @@
import com.android.internal.R;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.Utils;
-import com.android.systemui.Dependency;
import com.android.systemui.plugins.GlobalActions;
import com.android.systemui.scrim.ScrimDrawable;
import com.android.systemui.statusbar.BlurUtils;
@@ -52,19 +51,24 @@
private final KeyguardStateController mKeyguardStateController;
private final DeviceProvisionedController mDeviceProvisionedController;
private final BlurUtils mBlurUtils;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final CommandQueue mCommandQueue;
private GlobalActionsDialogLite mGlobalActionsDialog;
private boolean mDisabled;
@Inject
public GlobalActionsImpl(Context context, CommandQueue commandQueue,
- Lazy<GlobalActionsDialogLite> globalActionsDialogLazy, BlurUtils blurUtils) {
+ Lazy<GlobalActionsDialogLite> globalActionsDialogLazy, BlurUtils blurUtils,
+ KeyguardStateController keyguardStateController,
+ DeviceProvisionedController deviceProvisionedController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor) {
mContext = context;
mGlobalActionsDialogLazy = globalActionsDialogLazy;
- mKeyguardStateController = Dependency.get(KeyguardStateController.class);
- mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
+ mKeyguardStateController = keyguardStateController;
+ mDeviceProvisionedController = deviceProvisionedController;
mCommandQueue = commandQueue;
mBlurUtils = blurUtils;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mCommandQueue.addCallback(this);
}
@@ -83,7 +87,7 @@
mGlobalActionsDialog = mGlobalActionsDialogLazy.get();
mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(),
mDeviceProvisionedController.isDeviceProvisioned());
- Dependency.get(KeyguardUpdateMonitor.class).requestFaceAuth();
+ mKeyguardUpdateMonitor.requestFaceAuth();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsInfoProvider.kt b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsInfoProvider.kt
index 39008ee..17b532a 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsInfoProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsInfoProvider.kt
@@ -25,6 +25,7 @@
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
+import android.widget.TextView
import com.android.systemui.R
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.plugins.ActivityStarter
@@ -70,6 +71,11 @@
val view = LayoutInflater.from(context).inflate(R.layout.global_actions_change_panel,
parent, false)
+
+ val walletTitle = walletClient.serviceLabel ?: context.getString(R.string.wallet_title)
+ val message = view.findViewById<TextView>(R.id.global_actions_change_message)
+ message?.setText(context.getString(R.string.global_actions_change_description, walletTitle))
+
val button = view.findViewById<ImageView>(R.id.global_actions_change_button)
button.setOnClickListener { _ ->
dismissParent.run()
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index 01a353c..d30783c 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -46,6 +46,7 @@
private final ImageGLWallpaper mWallpaper;
private final Rect mSurfaceSize = new Rect();
private final WallpaperTexture mTexture;
+ private Consumer<Bitmap> mOnBitmapUpdated;
public ImageWallpaperRenderer(Context context) {
final WallpaperManager wpm = context.getSystemService(WallpaperManager.class);
@@ -60,10 +61,9 @@
/**
* @hide
- * @return
*/
- public void useBitmap(Consumer<Bitmap> c) {
- mTexture.use(c);
+ public void setOnBitmapChanged(Consumer<Bitmap> c) {
+ mOnBitmapUpdated = c;
}
@Override
@@ -80,6 +80,8 @@
mTexture.use(bitmap -> {
if (bitmap == null) {
Log.w(TAG, "reload texture failed!");
+ } else if (mOnBitmapUpdated != null) {
+ mOnBitmapUpdated.accept(bitmap);
}
mWallpaper.setup(bitmap);
});
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
index bec4ce6..fc5f3b8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
@@ -20,7 +20,6 @@
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.text.TextUtils;
-import android.view.View;
import androidx.annotation.IntDef;
@@ -202,10 +201,7 @@
mCurrIndicationType = type;
mIndicationQueue.removeIf(x -> x == type);
- if (mCurrIndicationType == INDICATION_TYPE_NONE) {
- mView.setVisibility(View.GONE);
- } else {
- mView.setVisibility(View.VISIBLE);
+ if (mCurrIndicationType != INDICATION_TYPE_NONE) {
mIndicationQueue.add(type); // re-add to show later
}
@@ -299,7 +295,7 @@
}
}
- private static final int INDICATION_TYPE_NONE = -1;
+ static final int INDICATION_TYPE_NONE = -1;
public static final int INDICATION_TYPE_OWNER_INFO = 0;
public static final int INDICATION_TYPE_DISCLOSURE = 1;
public static final int INDICATION_TYPE_LOGOUT = 2;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3276983..88e9f69 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -119,6 +119,7 @@
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
import java.io.FileDescriptor;
@@ -257,6 +258,9 @@
/** TrustManager for letting it know when we change visibility */
private final TrustManager mTrustManager;
+ /** UserSwitcherController for creating guest user on boot complete */
+ private final UserSwitcherController mUserSwitcherController;
+
/**
* Used to keep the device awake while to ensure the keyguard finishes opening before
* we sleep.
@@ -805,6 +809,7 @@
KeyguardUpdateMonitor keyguardUpdateMonitor, DumpManager dumpManager,
@UiBackground Executor uiBgExecutor, PowerManager powerManager,
TrustManager trustManager,
+ UserSwitcherController userSwitcherController,
DeviceConfigProxy deviceConfig,
NavigationModeController navigationModeController,
KeyguardDisplayManager keyguardDisplayManager,
@@ -825,6 +830,7 @@
mUpdateMonitor = keyguardUpdateMonitor;
mPM = powerManager;
mTrustManager = trustManager;
+ mUserSwitcherController = userSwitcherController;
mKeyguardDisplayManager = keyguardDisplayManager;
dumpManager.registerDumpable(getClass().getName(), this);
mDeviceConfig = deviceConfig;
@@ -2558,6 +2564,11 @@
@Override
public void onBootCompleted() {
synchronized (this) {
+ if (mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_guestUserAutoCreated)) {
+ // TODO(b/191067027): Move post-boot guest creation to system_server
+ mUserSwitcherController.guaranteeGuestPresent();
+ }
mBootCompleted = true;
adjustStatusBarLocked(false, true);
if (mBootSendUserPresent) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
index 2e03d9a..6f878d1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
@@ -67,7 +67,7 @@
@Nullable
private final IWallpaperManager mWallpaperManagerService;
- private int mWakefulness = WAKEFULNESS_ASLEEP;
+ private int mWakefulness = WAKEFULNESS_AWAKE;
private @PowerManager.WakeReason int mLastWakeReason = PowerManager.WAKE_REASON_UNKNOWN;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 05d1361..8a383b9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -54,6 +54,7 @@
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.settings.GlobalSettings;
@@ -92,6 +93,7 @@
DumpManager dumpManager,
PowerManager powerManager,
TrustManager trustManager,
+ UserSwitcherController userSwitcherController,
@UiBackground Executor uiBgExecutor,
DeviceConfigProxy deviceConfig,
NavigationModeController navigationModeController,
@@ -114,6 +116,7 @@
uiBgExecutor,
powerManager,
trustManager,
+ userSwitcherController,
deviceConfig,
navigationModeController,
keyguardDisplayManager,
diff --git a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
index 77d78929..2bf102f7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
@@ -186,11 +186,9 @@
}
private fun hideMediaPlayer() {
- if (useSplitShade) {
- setVisibility(splitShadeContainer, View.GONE)
- } else {
- setVisibility(singlePaneContainer, View.GONE)
- }
+ // always hide splitShadeContainer as it's initially visible and may influence layout
+ setVisibility(splitShadeContainer, View.GONE)
+ setVisibility(singlePaneContainer, View.GONE)
}
private fun setVisibility(view: ViewGroup?, newVisibility: Int) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 5b1e039..28d336e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -39,6 +39,7 @@
import android.net.Uri
import android.os.Parcelable
import android.os.UserHandle
+import android.provider.Settings
import android.service.notification.StatusBarNotification
import android.text.TextUtils
import android.util.Log
@@ -54,6 +55,7 @@
import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
import com.android.systemui.statusbar.notification.row.HybridGroupManager
+import com.android.systemui.tuner.TunerService
import com.android.systemui.util.Assert
import com.android.systemui.util.Utils
import com.android.systemui.util.concurrency.DelayableExecutor
@@ -114,7 +116,8 @@
private val smartspaceMediaDataProvider: SmartspaceMediaDataProvider,
private var useMediaResumption: Boolean,
private val useQsMediaPlayer: Boolean,
- private val systemClock: SystemClock
+ private val systemClock: SystemClock,
+ private val tunerService: TunerService
) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener {
companion object {
@@ -147,6 +150,7 @@
// There should ONLY be at most one Smartspace media recommendation.
private var smartspaceMediaData: SmartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA
private var smartspaceSession: SmartspaceSession? = null
+ private var allowMediaRecommendations = Utils.allowMediaRecommendations(context)
@Inject
constructor(
@@ -164,12 +168,13 @@
mediaDataFilter: MediaDataFilter,
activityStarter: ActivityStarter,
smartspaceMediaDataProvider: SmartspaceMediaDataProvider,
- clock: SystemClock
+ clock: SystemClock,
+ tunerService: TunerService
) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory,
broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener,
mediaSessionBasedFilter, mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter,
activityStarter, smartspaceMediaDataProvider, Utils.useMediaResumption(context),
- Utils.useQsMediaPlayer(context), clock)
+ Utils.useQsMediaPlayer(context), clock, tunerService)
private val appChangeReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@@ -243,6 +248,14 @@
})
}
smartspaceSession?.let { it.requestSmartspaceUpdate() }
+ tunerService.addTunable(object : TunerService.Tunable {
+ override fun onTuningChanged(key: String?, newValue: String?) {
+ allowMediaRecommendations = Utils.allowMediaRecommendations(context)
+ if (!allowMediaRecommendations) {
+ dismissSmartspaceRecommendation(key = smartspaceMediaData.targetId, delay = 0L)
+ }
+ }
+ }, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION)
}
fun destroy() {
@@ -695,8 +708,7 @@
}
override fun onSmartspaceTargetsUpdated(targets: List<Parcelable>) {
- if (!Utils.allowMediaRecommendations(context)) {
- Log.d(TAG, "Smartspace recommendation is disabled in Settings.")
+ if (!allowMediaRecommendations) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index 075bc70..edbf187 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -187,6 +187,12 @@
private var currentAttachmentLocation = -1
/**
+ * Is there any active media in the carousel?
+ */
+ private var hasActiveMedia: Boolean = false
+ get() = mediaHosts.get(LOCATION_QQS)?.visible == true
+
+ /**
* Are we currently waiting on an animation to start?
*/
private var animationPending: Boolean = false
@@ -476,8 +482,12 @@
val viewHost = createUniqueObjectHost()
mediaObject.hostView = viewHost
mediaObject.addVisibilityChangeListener {
+ // If QQS changes visibility, we need to force an update to ensure the transition
+ // goes into the correct state
+ val stateUpdate = mediaObject.location == LOCATION_QQS
+
// Never animate because of a visibility change, only state changes should do that
- updateDesiredLocation(forceNoAnimation = true)
+ updateDesiredLocation(forceNoAnimation = true, forceStateUpdate = stateUpdate)
}
mediaHosts[mediaObject.location] = mediaObject
if (mediaObject.location == desiredLocation) {
@@ -521,10 +531,15 @@
* going from the old desired location to the new one.
*
* @param forceNoAnimation optional parameter telling the system not to animate
+ * @param forceStateUpdate optional parameter telling the system to update transition state
+ * even if location did not change
*/
- private fun updateDesiredLocation(forceNoAnimation: Boolean = false) {
+ private fun updateDesiredLocation(
+ forceNoAnimation: Boolean = false,
+ forceStateUpdate: Boolean = false
+ ) {
val desiredLocation = calculateLocation()
- if (desiredLocation != this.desiredLocation) {
+ if (desiredLocation != this.desiredLocation || forceStateUpdate) {
if (this.desiredLocation >= 0) {
previousLocation = this.desiredLocation
}
@@ -784,7 +799,7 @@
private fun getQSTransformationProgress(): Float {
val currentHost = getHost(desiredLocation)
val previousHost = getHost(previousLocation)
- if (currentHost?.location == LOCATION_QS) {
+ if (hasActiveMedia && currentHost?.location == LOCATION_QS) {
if (previousHost?.location == LOCATION_QQS) {
if (previousHost.visible || statusbarState != StatusBarState.KEYGUARD) {
return qsExpansion
@@ -917,6 +932,7 @@
val location = when {
qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS
qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
+ !hasActiveMedia -> LOCATION_QS
onLockscreen && isTransformingToFullShadeAndInQQS() -> LOCATION_QQS
onLockscreen && allowedOnLockscreen -> LOCATION_LOCKSCREEN
else -> LOCATION_QQS
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 0d9749e..ff5d0b1 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -251,8 +251,9 @@
private float mMLResults;
// For debugging
- private ArrayDeque<String> mPredictionLog = new ArrayDeque<>();
- private ArrayDeque<String> mGestureLog = new ArrayDeque<>();
+ private LogArray mPredictionLog = new LogArray(MAX_NUM_LOGGED_PREDICTIONS);
+ private LogArray mGestureLogInsideInsets = new LogArray(MAX_NUM_LOGGED_GESTURES);
+ private LogArray mGestureLogOutsideInsets = new LogArray(MAX_NUM_LOGGED_GESTURES);
private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
@@ -631,7 +632,7 @@
return mMLResults >= mMLModelThreshold ? 1 : 0;
}
- private boolean isWithinTouchRegion(int x, int y) {
+ private boolean isWithinInsets(int x, int y) {
// Disallow if we are in the bottom gesture area
if (y >= (mDisplaySize.y - mBottomGestureHeight)) {
return false;
@@ -644,7 +645,10 @@
&& x < (mDisplaySize.x - 2 * (mEdgeWidthRight + mRightInset))) {
return false;
}
+ return true;
+ }
+ private boolean isWithinTouchRegion(int x, int y) {
// If the point is inside the PiP or Nav bar overlay excluded bounds, then ignore the back
// gesture
final boolean isInsidePip = mIsInPipMode && mPipExcludedBounds.contains(x, y);
@@ -675,14 +679,8 @@
}
// For debugging purposes
- if (mPredictionLog.size() >= MAX_NUM_LOGGED_PREDICTIONS) {
- mPredictionLog.removeFirst();
- }
- mPredictionLog.addLast(String.format("Prediction [%d,%d,%d,%d,%f,%d]",
+ mPredictionLog.log(String.format("Prediction [%d,%d,%d,%d,%f,%d]",
System.currentTimeMillis(), x, y, app, mMLResults, withinRange ? 1 : 0));
- if (DEBUG_MISSING_GESTURE) {
- Log.d(DEBUG_MISSING_GESTURE_TAG, mPredictionLog.peekLast());
- }
// Always allow if the user is in a transient sticky immersive state
if (mIsNavBarShownTransiently) {
@@ -755,7 +753,8 @@
mMLResults = 0;
mLogGesture = false;
mInRejectedExclusion = false;
- mAllowGesture = !mDisabledForQuickstep && mIsBackGestureAllowed
+ boolean isWithinInsets = isWithinInsets((int) ev.getX(), (int) ev.getY());
+ mAllowGesture = !mDisabledForQuickstep && mIsBackGestureAllowed && isWithinInsets
&& !mGestureBlockingActivityRunning
&& !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
&& isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
@@ -769,18 +768,13 @@
mThresholdCrossed = false;
}
- // For debugging purposes
- if (mGestureLog.size() >= MAX_NUM_LOGGED_GESTURES) {
- mGestureLog.removeFirst();
- }
- mGestureLog.addLast(String.format(
+ // For debugging purposes, only log edge points
+ (isWithinInsets ? mGestureLogInsideInsets : mGestureLogOutsideInsets).log(String.format(
"Gesture [%d,alw=%B,%B,%B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
- System.currentTimeMillis(), mAllowGesture, mIsOnLeftEdge, mIsBackGestureAllowed,
+ System.currentTimeMillis(), mAllowGesture, mIsOnLeftEdge,
+ mIsBackGestureAllowed,
QuickStepContract.isBackGestureDisabled(mSysUiFlags), mDisplaySize,
mEdgeWidthLeft, mLeftInset, mEdgeWidthRight, mRightInset, mExcludeRegion));
- if (DEBUG_MISSING_GESTURE) {
- Log.d(DEBUG_MISSING_GESTURE_TAG, mGestureLog.peekLast());
- }
} else if (mAllowGesture || mLogGesture) {
if (!mThresholdCrossed) {
mEndPoint.x = (int) ev.getX();
@@ -907,7 +901,7 @@
pw.println(" mUseMLModel=" + mUseMLModel);
pw.println(" mDisabledForQuickstep=" + mDisabledForQuickstep);
pw.println(" mStartingQuickstepRotation=" + mStartingQuickstepRotation);
- pw.println(" mInRejectedExclusion" + mInRejectedExclusion);
+ pw.println(" mInRejectedExclusion=" + mInRejectedExclusion);
pw.println(" mExcludeRegion=" + mExcludeRegion);
pw.println(" mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion);
pw.println(" mIsInPipMode=" + mIsInPipMode);
@@ -922,7 +916,8 @@
pw.println(" mTouchSlop=" + mTouchSlop);
pw.println(" mBottomGestureHeight=" + mBottomGestureHeight);
pw.println(" mPredictionLog=" + String.join("\n", mPredictionLog));
- pw.println(" mGestureLog=" + String.join("\n", mGestureLog));
+ pw.println(" mGestureLogInsideInsets=" + String.join("\n", mGestureLogInsideInsets));
+ pw.println(" mGestureLogOutsideInsets=" + String.join("\n", mGestureLogOutsideInsets));
pw.println(" mEdgeBackPlugin=" + mEdgeBackPlugin);
}
@@ -945,4 +940,23 @@
}
proto.edgeBackGestureHandler.allowGesture = mAllowGesture;
}
+
+
+ private static class LogArray extends ArrayDeque<String> {
+ private final int mLength;
+
+ LogArray(int length) {
+ mLength = length;
+ }
+
+ void log(String message) {
+ if (size() >= mLength) {
+ removeFirst();
+ }
+ addLast(message);
+ if (DEBUG_MISSING_GESTURE) {
+ Log.d(DEBUG_MISSING_GESTURE_TAG, message);
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java b/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java
index b5ac908..d863dcc 100644
--- a/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java
@@ -240,9 +240,16 @@
/** Returns whether {@code entry} is suppressed from shade, meaning we should not show it. */
public static boolean shouldFilterOut(
Optional<Bubbles> bubblesOptional, NotificationEntry entry) {
- return bubblesOptional.isPresent()
- && bubblesOptional.get().isBubbleNotificationSuppressedFromShade(
- entry.getKey(), entry.getSbn().getGroupKey());
+ boolean isSuppressed = false;
+ //TODO(b/190822282): Investigate what is causing the NullPointerException
+ try {
+ isSuppressed = bubblesOptional.isPresent()
+ && bubblesOptional.get().isBubbleNotificationSuppressedFromShade(
+ entry.getKey(), entry.getSbn().getGroupKey());
+ } catch (Exception e) {
+ Log.e(TAG, "Exception checking if notification is suppressed: " + e);
+ }
+ return isSuppressed;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
index a981b62..929aeda 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
@@ -74,7 +74,7 @@
private final PageIndicator mPageIndicator;
private final View mPowerMenuLite;
private final boolean mShowPMLiteButton;
- private GlobalActionsDialogLite mGlobalActionsDialog;
+ private final GlobalActionsDialogLite mGlobalActionsDialog;
private final UiEventLogger mUiEventLogger;
private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index e1a66b2..7b8a6a0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -539,8 +539,9 @@
private void pinToBottom(float absoluteBottomPosition, MediaHost mediaHost, boolean expanded) {
View hostView = mediaHost.getHostView();
- // on keyguard we cross-fade to expanded, so no need to pin it.
- if (mLastQSExpansion > 0 && !isKeyguardState()) {
+ // On keyguard we cross-fade to expanded, so no need to pin it.
+ // If the collapsed qs isn't visible, we also just keep it at the laid out position.
+ if (mLastQSExpansion > 0 && !isKeyguardState() && mQqsMediaHost.getVisible()) {
float targetPosition = absoluteBottomPosition - getTotalBottomMargin(hostView)
- hostView.getHeight();
float currentPosition = mediaHost.getCurrentBounds().top
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 525bad8..6ddf2a7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -45,7 +45,9 @@
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.external.CustomTile;
+import com.android.systemui.qs.external.CustomTileStatePersister;
import com.android.systemui.qs.external.TileLifecycleManager;
+import com.android.systemui.qs.external.TileServiceKey;
import com.android.systemui.qs.external.TileServices;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.UserTracker;
@@ -93,6 +95,7 @@
private final QSLogger mQSLogger;
private final UiEventLogger mUiEventLogger;
private final InstanceIdSequence mInstanceIdSequence;
+ private final CustomTileStatePersister mCustomTileStatePersister;
private final List<Callback> mCallbacks = new ArrayList<>();
private AutoTileManager mAutoTiles;
@@ -119,7 +122,8 @@
QSLogger qsLogger,
UiEventLogger uiEventLogger,
UserTracker userTracker,
- SecureSettings secureSettings) {
+ SecureSettings secureSettings,
+ CustomTileStatePersister customTileStatePersister) {
mIconController = iconController;
mContext = context;
mUserContext = context;
@@ -139,6 +143,7 @@
mDumpManager.registerDumpable(TAG, this);
mUserTracker = userTracker;
mSecureSettings = secureSettings;
+ mCustomTileStatePersister = customTileStatePersister;
mainHandler.post(() -> {
// This is technically a hack to avoid circular dependency of
@@ -418,6 +423,11 @@
changeTiles(mTileSpecs, newSpecs);
}
+ /**
+ * Change the tiles triggered by the user editing.
+ * <p>
+ * This is not called on device start, or on user change.
+ */
public void changeTiles(List<String> previousTiles, List<String> newTiles) {
final List<String> copy = new ArrayList<>(previousTiles);
final int NP = copy.size();
@@ -433,6 +443,7 @@
mBroadcastDispatcher);
lifecycleManager.onStopListening();
lifecycleManager.onTileRemoved();
+ mCustomTileStatePersister.removeState(new TileServiceKey(component, mCurrentUser));
TileLifecycleManager.setTileAdded(mContext, component, false);
lifecycleManager.flushMessagesAndUnbind();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 7cc6ecd..997b966 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -399,12 +399,14 @@
mClockIconsSeparatorLayoutParams.width = 0;
setSeparatorVisibility(false);
mShowClockIconsSeparator = false;
+ mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
} else {
datePrivacySeparatorLayoutParams.width = topCutout.width();
mDatePrivacySeparator.setVisibility(View.VISIBLE);
mClockIconsSeparatorLayoutParams.width = topCutout.width();
mShowClockIconsSeparator = true;
setSeparatorVisibility(mKeyguardExpansionFraction == 0f);
+ mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ON);
}
}
mDatePrivacySeparator.setLayoutParams(datePrivacySeparatorLayoutParams);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 10eea82..396eca5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -46,6 +46,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -85,6 +86,7 @@
private final IQSTileService mService;
private final TileServiceManager mServiceManager;
private final int mUser;
+ private final CustomTileStatePersister mCustomTileStatePersister;
private android.graphics.drawable.Icon mDefaultIcon;
private CharSequence mDefaultLabel;
@@ -94,6 +96,8 @@
private boolean mIsTokenGranted;
private boolean mIsShowingDialog;
+ private final TileServiceKey mKey;
+
private CustomTile(
QSHost host,
Looper backgroundLooper,
@@ -104,7 +108,8 @@
ActivityStarter activityStarter,
QSLogger qsLogger,
String action,
- Context userContext
+ Context userContext,
+ CustomTileStatePersister customTileStatePersister
) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
@@ -113,15 +118,29 @@
mTile = new Tile();
mUserContext = userContext;
mUser = mUserContext.getUserId();
- updateDefaultTileAndIcon();
+ mKey = new TileServiceKey(mComponent, mUser);
+
mServiceManager = host.getTileServices().getTileWrapper(this);
+ mService = mServiceManager.getTileService();
+ mCustomTileStatePersister = customTileStatePersister;
+ }
+
+ @Override
+ protected void handleInitialize() {
+ updateDefaultTileAndIcon();
if (mServiceManager.isToggleableTile()) {
// Replace states with BooleanState
resetStates();
}
-
- mService = mServiceManager.getTileService();
mServiceManager.setTileChangeListener(this);
+ if (mServiceManager.isActiveTile()) {
+ Tile t = mCustomTileStatePersister.readState(mKey);
+ if (t != null) {
+ applyTileState(t, /* overwriteNulls */ false);
+ mServiceManager.clearPendingBind();
+ refreshState();
+ }
+ }
}
@Override
@@ -191,7 +210,7 @@
@Override
public void onTileChanged(ComponentName tile) {
- updateDefaultTileAndIcon();
+ mHandler.post(this::updateDefaultTileAndIcon);
}
@Override
@@ -213,16 +232,44 @@
}
public Tile getQsTile() {
+ // TODO(b/191145007) Move to background thread safely
updateDefaultTileAndIcon();
return mTile;
}
- public void updateState(Tile tile) {
- mTile.setIcon(tile.getIcon());
- mTile.setLabel(tile.getLabel());
- mTile.setSubtitle(tile.getSubtitle());
- mTile.setContentDescription(tile.getContentDescription());
- mTile.setStateDescription(tile.getStateDescription());
+ /**
+ * Update state of {@link this#mTile} from a remote {@link TileService}.
+ * @param tile tile populated with state to apply
+ */
+ public void updateTileState(Tile tile) {
+ // This comes from a binder call IQSService.updateQsTile
+ mHandler.post(() -> handleUpdateTileState(tile));
+ }
+
+ private void handleUpdateTileState(Tile tile) {
+ applyTileState(tile, /* overwriteNulls */ true);
+ if (mServiceManager.isActiveTile()) {
+ mCustomTileStatePersister.persistState(mKey, tile);
+ }
+ }
+
+ @WorkerThread
+ private void applyTileState(Tile tile, boolean overwriteNulls) {
+ if (tile.getIcon() != null || overwriteNulls) {
+ mTile.setIcon(tile.getIcon());
+ }
+ if (tile.getLabel() != null || overwriteNulls) {
+ mTile.setLabel(tile.getLabel());
+ }
+ if (tile.getSubtitle() != null || overwriteNulls) {
+ mTile.setSubtitle(tile.getSubtitle());
+ }
+ if (tile.getContentDescription() != null || overwriteNulls) {
+ mTile.setContentDescription(tile.getContentDescription());
+ }
+ if (tile.getStateDescription() != null || overwriteNulls) {
+ mTile.setStateDescription(tile.getStateDescription());
+ }
mTile.setState(tile.getState());
}
@@ -459,6 +506,7 @@
final StatusBarStateController mStatusBarStateController;
final ActivityStarter mActivityStarter;
final QSLogger mQSLogger;
+ final CustomTileStatePersister mCustomTileStatePersister;
Context mUserContext;
String mSpec = "";
@@ -472,7 +520,8 @@
MetricsLogger metricsLogger,
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
- QSLogger qsLogger
+ QSLogger qsLogger,
+ CustomTileStatePersister customTileStatePersister
) {
mQSHostLazy = hostLazy;
mBackgroundLooper = backgroundLooper;
@@ -482,6 +531,7 @@
mStatusBarStateController = statusBarStateController;
mActivityStarter = activityStarter;
mQSLogger = qsLogger;
+ mCustomTileStatePersister = customTileStatePersister;
}
Builder setSpec(@NonNull String spec) {
@@ -509,7 +559,8 @@
mActivityStarter,
mQSLogger,
action,
- mUserContext
+ mUserContext,
+ mCustomTileStatePersister
);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt
new file mode 100644
index 0000000..021e632
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt
@@ -0,0 +1,122 @@
+/*
+ * 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.external
+
+import android.content.ComponentName
+import android.content.Context
+import android.service.quicksettings.Tile
+import android.util.Log
+import com.android.internal.annotations.VisibleForTesting
+import org.json.JSONException
+import org.json.JSONObject
+import javax.inject.Inject
+
+data class TileServiceKey(val componentName: ComponentName, val user: Int) {
+ private val string = "${componentName.flattenToString()}:$user"
+ override fun toString() = string
+}
+private const val STATE = "state"
+private const val LABEL = "label"
+private const val SUBTITLE = "subtitle"
+private const val CONTENT_DESCRIPTION = "content_description"
+private const val STATE_DESCRIPTION = "state_description"
+
+/**
+ * Persists and retrieves state for [CustomTile].
+ *
+ * This class will persists to a fixed [SharedPreference] file a state for a pair of [ComponentName]
+ * and user id ([TileServiceKey]).
+ *
+ * It persists the state from a [Tile] necessary to present the view in the same state when
+ * retrieved, with the exception of the icon.
+ */
+class CustomTileStatePersister @Inject constructor(context: Context) {
+ companion object {
+ private const val FILE_NAME = "custom_tiles_state"
+ }
+
+ private val sharedPreferences = context.getSharedPreferences(FILE_NAME, 0)
+
+ /**
+ * Read the state from [SharedPreferences].
+ *
+ * Returns `null` if the tile has no saved state.
+ *
+ * Any fields that have not been saved will be set to `null`
+ */
+ fun readState(key: TileServiceKey): Tile? {
+ val state = sharedPreferences.getString(key.toString(), null) ?: return null
+ return try {
+ readTileFromString(state)
+ } catch (e: JSONException) {
+ Log.e("TileServicePersistence", "Bad saved state: $state", e)
+ null
+ }
+ }
+
+ /**
+ * Persists the state into [SharedPreferences].
+ *
+ * The implementation does not store fields that are `null` or icons.
+ */
+ fun persistState(key: TileServiceKey, tile: Tile) {
+ val state = writeToString(tile)
+
+ sharedPreferences.edit().putString(key.toString(), state).apply()
+ }
+
+ /**
+ * Removes the state for a given tile, user pair.
+ *
+ * Used when the tile is removed by the user.
+ */
+ fun removeState(key: TileServiceKey) {
+ sharedPreferences.edit().remove(key.toString()).apply()
+ }
+}
+
+@VisibleForTesting
+internal fun readTileFromString(stateString: String): Tile {
+ val json = JSONObject(stateString)
+ return Tile().apply {
+ state = json.getInt(STATE)
+ label = json.getStringOrNull(LABEL)
+ subtitle = json.getStringOrNull(SUBTITLE)
+ contentDescription = json.getStringOrNull(CONTENT_DESCRIPTION)
+ stateDescription = json.getStringOrNull(STATE_DESCRIPTION)
+ }
+}
+
+// Properties with null values will not be saved to the Json string in any way. This makes sure
+// to properly retrieve a null in that case.
+private fun JSONObject.getStringOrNull(name: String): String? {
+ return if (has(name)) getString(name) else null
+}
+
+@VisibleForTesting
+internal fun writeToString(tile: Tile): String {
+ // Not storing the icon
+ return with(tile) {
+ JSONObject()
+ .put(STATE, state)
+ .put(LABEL, label)
+ .put(SUBTITLE, subtitle)
+ .put(CONTENT_DESCRIPTION, contentDescription)
+ .put(STATE_DESCRIPTION, stateDescription)
+ .toString()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 35cf2a1..a7cd113 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -204,7 +204,7 @@
tileServiceManager.clearPendingBind();
tileServiceManager.setLastUpdate(System.currentTimeMillis());
}
- customTile.updateState(tile);
+ customTile.updateTileState(tile);
customTile.refreshState();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 8f7c493..842fd6c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -160,7 +160,8 @@
public QSTile createTile(String tileSpec) {
QSTileImpl tile = createTileInternal(tileSpec);
if (tile != null) {
- tile.handleStale(); // Tile was just created, must be stale.
+ tile.initialize();
+ tile.postStale(); // Tile was just created, must be stale.
}
return tile;
}
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 894ab52..4616be8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -159,6 +159,15 @@
*/
abstract public int getMetricsCategory();
+ /**
+ * Performs initialization of the tile
+ *
+ * Use this to perform initialization of the tile. Empty by default.
+ */
+ protected void handleInitialize() {
+
+ }
+
protected QSTileImpl(
QSHost host,
Looper backgroundLooper,
@@ -347,6 +356,15 @@
mHandler.sendEmptyMessage(H.DESTROY);
}
+ /**
+ * Schedules initialization of the tile.
+ *
+ * Should be called upon creation of the tile, before performing other operations
+ */
+ public void initialize() {
+ mHandler.sendEmptyMessage(H.INITIALIZE);
+ }
+
public TState getState() {
return mState;
}
@@ -371,6 +389,13 @@
}
/**
+ * Posts a stale message to the background thread.
+ */
+ public void postStale() {
+ mHandler.sendEmptyMessage(H.STALE);
+ }
+
+ /**
* Handles secondary click on the tile.
*
* Defaults to {@link QSTileImpl#handleClick}
@@ -582,6 +607,7 @@
private static final int SET_LISTENING = 13;
@VisibleForTesting
protected static final int STALE = 14;
+ private static final int INITIALIZE = 15;
@VisibleForTesting
protected H(Looper looper) {
@@ -640,6 +666,9 @@
} else if (msg.what == STALE) {
name = "handleStale";
handleStale();
+ } else if (msg.what == INITIALIZE) {
+ name = "initialize";
+ handleInitialize();
} else {
throw new IllegalArgumentException("Unknown msg: " + msg.what);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
index 9e11451..0a60f6d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
@@ -62,6 +62,7 @@
private final float mCropTouchMargin;
private final Paint mShadePaint;
private final Paint mHandlePaint;
+ private final Paint mContainerBackgroundPaint;
// Crop rect with each element represented as [0,1] along its proper axis.
private RectF mCrop = new RectF(0, 0, 1, 1);
@@ -79,6 +80,9 @@
// The allowable values for the current boundary being dragged
private Range<Float> mMotionRange;
+ // Value [0,1] indicating progress in animateEntrance()
+ private float mEntranceInterpolation = 1f;
+
private CropInteractionListener mCropInteractionListener;
private final ExploreByTouchHelper mExploreByTouchHelper;
@@ -92,6 +96,9 @@
attrs, R.styleable.CropView, 0, 0);
mShadePaint = new Paint();
mShadePaint.setColor(t.getColor(R.styleable.CropView_scrimColor, Color.TRANSPARENT));
+ mContainerBackgroundPaint = new Paint();
+ mContainerBackgroundPaint.setColor(t.getColor(R.styleable.CropView_containerBackgroundColor,
+ Color.TRANSPARENT));
mHandlePaint = new Paint();
mHandlePaint.setColor(t.getColor(R.styleable.CropView_handleColor, Color.BLACK));
mHandlePaint.setStrokeCap(Paint.Cap.ROUND);
@@ -125,10 +132,22 @@
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
- drawShade(canvas, 0, 0, 1, mCrop.top);
- drawShade(canvas, 0, mCrop.bottom, 1, 1);
+ // Top and bottom borders reflect the boundary between the (scrimmed) image and the
+ // opaque container background. This is only meaningful during an entrance transition.
+ float topBorder = MathUtils.lerp(mCrop.top, 0, mEntranceInterpolation);
+ float bottomBorder = MathUtils.lerp(mCrop.bottom, 1, mEntranceInterpolation);
+ drawShade(canvas, 0, topBorder, 1, mCrop.top);
+ drawShade(canvas, 0, mCrop.bottom, 1, bottomBorder);
drawShade(canvas, 0, mCrop.top, mCrop.left, mCrop.bottom);
drawShade(canvas, mCrop.right, mCrop.top, 1, mCrop.bottom);
+
+ // Entrance transition expects the crop bounds to be full width, so we only draw container
+ // background on the top and bottom.
+ drawContainerBackground(canvas, 0, 0, 1, topBorder);
+ drawContainerBackground(canvas, 0, bottomBorder, 1, 1);
+
+ mHandlePaint.setAlpha((int) (mEntranceInterpolation * 255));
+
drawHorizontalHandle(canvas, mCrop.top, /* draw the handle tab up */ true);
drawHorizontalHandle(canvas, mCrop.bottom, /* draw the handle tab down */ false);
drawVerticalHandle(canvas, mCrop.left, /* left */ true);
@@ -282,6 +301,22 @@
}
/**
+ * Fade in crop bounds, animate reveal of cropped-out area from current crop bounds.
+ */
+ public void animateEntrance() {
+ mEntranceInterpolation = 0;
+ ValueAnimator animator = new ValueAnimator();
+ animator.addUpdateListener(animation -> {
+ mEntranceInterpolation = animation.getAnimatedFraction();
+ invalidate();
+ });
+ animator.setFloatValues(0f, 1f);
+ animator.setDuration(750);
+ animator.setInterpolator(new FastOutSlowInInterpolator());
+ animator.start();
+ }
+
+ /**
* Set additional top and bottom padding for the image being cropped (used when the
* corresponding ImageView doesn't take the full height).
*/
@@ -369,6 +404,13 @@
fractionToVerticalPixels(bottom), mShadePaint);
}
+ private void drawContainerBackground(Canvas canvas, float left, float top, float right,
+ float bottom) {
+ canvas.drawRect(fractionToHorizontalPixels(left), fractionToVerticalPixels(top),
+ fractionToHorizontalPixels(right),
+ fractionToVerticalPixels(bottom), mContainerBackgroundPaint);
+ }
+
private void drawHorizontalHandle(Canvas canvas, float frac, boolean handleTabUp) {
int y = fractionToVerticalPixels(frac);
canvas.drawLine(fractionToHorizontalPixels(mCrop.left), y,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index d5b4032..25ec1d7 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -192,7 +192,6 @@
mLongScreenshot = longScreenshot;
Drawable drawable = mLongScreenshot.getDrawable();
mPreview.setImageDrawable(drawable);
- mCropView.setVisibility(View.VISIBLE);
mMagnifierView.setDrawable(mLongScreenshot.getDrawable(),
mLongScreenshot.getWidth(), mLongScreenshot.getHeight());
// Original boundaries go from the image tile set's y=0 to y=pageSize, so
@@ -219,10 +218,12 @@
public void onTransitionEnd(Transition transition) {
super.onTransitionEnd(transition);
mPreview.animate().alpha(1f);
- mCropView.animateBoundaryTo(
+ mCropView.setBoundaryPosition(
CropView.CropBoundary.TOP, topFraction);
- mCropView.animateBoundaryTo(
+ mCropView.setBoundaryPosition(
CropView.CropBoundary.BOTTOM, bottomFraction);
+ mCropView.animateEntrance();
+ mCropView.setVisibility(View.VISIBLE);
setButtonsEnabled(true);
mEnterTransitionView.setVisibility(View.GONE);
}
@@ -250,6 +251,7 @@
Log.d(TAG, "onCachedImageLoaded(imageResult=" + imageResult + ")");
BitmapDrawable drawable = new BitmapDrawable(getResources(), imageResult.bitmap);
mPreview.setImageDrawable(drawable);
+ mPreview.setAlpha(1f);
mMagnifierView.setDrawable(drawable, imageResult.bitmap.getWidth(),
imageResult.bitmap.getHeight());
mCropView.setVisibility(View.VISIBLE);
@@ -476,19 +478,21 @@
params.height = boundaries.height();
mTransitionView.setLayoutParams(params);
- ConstraintLayout.LayoutParams enterTransitionParams =
- (ConstraintLayout.LayoutParams) mEnterTransitionView.getLayoutParams();
- float topFraction = Math.max(0,
- -mLongScreenshot.getTop() / (float) mLongScreenshot.getHeight());
- enterTransitionParams.width = (int) (scale * drawable.getIntrinsicWidth());
- enterTransitionParams.height = (int) (scale * mLongScreenshot.getPageHeight());
- mEnterTransitionView.setLayoutParams(enterTransitionParams);
+ if (mLongScreenshot != null) {
+ ConstraintLayout.LayoutParams enterTransitionParams =
+ (ConstraintLayout.LayoutParams) mEnterTransitionView.getLayoutParams();
+ float topFraction = Math.max(0,
+ -mLongScreenshot.getTop() / (float) mLongScreenshot.getHeight());
+ enterTransitionParams.width = (int) (scale * drawable.getIntrinsicWidth());
+ enterTransitionParams.height = (int) (scale * mLongScreenshot.getPageHeight());
+ mEnterTransitionView.setLayoutParams(enterTransitionParams);
- Matrix matrix = new Matrix();
- matrix.setScale(scale, scale);
- matrix.postTranslate(0, -scale * drawable.getIntrinsicHeight() * topFraction);
- mEnterTransitionView.setImageMatrix(matrix);
- mEnterTransitionView.setTranslationY(
- topFraction * previewHeight + mPreview.getPaddingTop() + extraPadding);
+ Matrix matrix = new Matrix();
+ matrix.setScale(scale, scale);
+ matrix.postTranslate(0, -scale * drawable.getIntrinsicHeight() * topFraction);
+ mEnterTransitionView.setImageMatrix(matrix);
+ mEnterTransitionView.setTranslationY(
+ topFraction * previewHeight + mPreview.getPaddingTop() + extraPadding);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 5efa1b2..aea8849 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -573,6 +573,10 @@
mScreenshotView.updateDisplayCutoutMargins(
mWindowManager.getCurrentWindowMetrics().getWindowInsets()
.getDisplayCutout());
+ // screenshot animation calculations won't be valid anymore, so just end
+ if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
+ mScreenshotAnimation.end();
+ }
}
});
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 91a0e6f..0bb702f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -112,6 +112,7 @@
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private ViewGroup mIndicationArea;
private KeyguardIndicationTextView mTopIndicationView;
+ private KeyguardIndicationTextView mLockScreenIndicationView;
private final IBatteryStats mBatteryInfo;
private final SettableWakeLock mWakeLock;
private final DockManager mDockManager;
@@ -208,17 +209,21 @@
mKeyguardUpdateMonitor.registerCallback(mTickReceiver);
mStatusBarStateController.addCallback(mStatusBarStateListener);
mKeyguardStateController.addCallback(this);
+
+ mStatusBarStateListener.onDozingChanged(mStatusBarStateController.isDozing());
}
public void setIndicationArea(ViewGroup indicationArea) {
mIndicationArea = indicationArea;
mTopIndicationView = indicationArea.findViewById(R.id.keyguard_indication_text);
+ mLockScreenIndicationView = indicationArea.findViewById(
+ R.id.keyguard_indication_text_bottom);
mInitialTextColorState = mTopIndicationView != null
? mTopIndicationView.getTextColors() : ColorStateList.valueOf(Color.WHITE);
mRotateTextViewController = new KeyguardIndicationRotateTextViewController(
- indicationArea.findViewById(R.id.keyguard_indication_text_bottom),
- mExecutor,
- mStatusBarStateController);
+ mLockScreenIndicationView,
+ mExecutor,
+ mStatusBarStateController);
updateIndication(false /* animate */);
updateDisclosure();
if (mBroadcastReceiver == null) {
@@ -630,6 +635,7 @@
// should be shown based on user or device state
// AoD
if (mDozing) {
+ mLockScreenIndicationView.setVisibility(View.GONE);
mTopIndicationView.setVisibility(VISIBLE);
// When dozing we ignore any text color and use white instead, because
// colors can be hard to read in low brightness.
@@ -659,6 +665,8 @@
// LOCK SCREEN
mTopIndicationView.setVisibility(GONE);
+ mTopIndicationView.setText(null);
+ mLockScreenIndicationView.setVisibility(View.VISIBLE);
updateIndications(animate, KeyguardUpdateMonitor.getCurrentUser());
}
@@ -914,7 +922,8 @@
} else if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.showBouncerMessage(errString, mInitialTextColorState);
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
- showTransientIndication(errString);
+ showTransientIndication(errString, /* isError */ true,
+ /* hideOnScreenOff */ true);
// We want to keep this message around in case the screen was off
hideTransientIndicationDelayed(HIDE_DELAY_MS);
} else {
@@ -1032,9 +1041,8 @@
if (mHideTransientMessageOnScreenOff && mDozing) {
hideTransientIndication();
- } else {
- updateIndication(false);
}
+ updateIndication(false);
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index 6a5f001..ec648ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -93,10 +93,10 @@
val endRadius: Float
) : LightRevealEffect {
override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {
- val interpolatedAmount = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(amount)
- val fadeAmount =
- LightRevealEffect.getPercentPastThreshold(interpolatedAmount, 0.75f)
- val radius = startRadius + ((endRadius - startRadius) * interpolatedAmount)
+ // reveal amount updates already have an interpolator, so we intentionally use the
+ // non-interpolated amount
+ val fadeAmount = LightRevealEffect.getPercentPastThreshold(amount, 0.5f)
+ val radius = startRadius + ((endRadius - startRadius) * amount)
scrim.revealGradientEndColorAlpha = 1f - fadeAmount
scrim.setRevealGradientBounds(
centerX - radius /* left */,
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 760bee2..b0a7767 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -264,7 +264,7 @@
}
override fun onStateChanged(newState: Int) {
- if (unlockedScreenOffAnimationController.shouldPlayScreenOffAnimation()) {
+ if (dozeParameters.shouldControlUnlockedScreenOff()) {
if (unlockedScreenOffAnimationController.isScreenOffAnimationPlaying() &&
state == StatusBarState.KEYGUARD &&
newState == StatusBarState.SHADE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 6822d24..26606cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -224,8 +224,14 @@
return mScrollY;
}
+ /**
+ * Set the new Scroll Y position.
+ */
public void setScrollY(int scrollY) {
- this.mScrollY = scrollY;
+ // Because we're dealing with an overscroller, scrollY could sometimes become smaller than
+ // 0. However this is only for internal purposes and the scroll position when read
+ // should never be smaller than 0, otherwise it can lead to flickers.
+ this.mScrollY = Math.max(scrollY, 0);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 99fe541..f2e39e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -710,10 +710,10 @@
if (mUserLocked) {
expandFraction = getGroupExpandFraction();
}
- final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
- || (mChildrenExpanded && mShowDividersWhenExpanded)
- || (mContainingNotification.isGroupExpansionChanging()
- && !mHideDividersDuringExpand);
+ final boolean isExpanding = !showingAsLowPriority()
+ && (mUserLocked || mContainingNotification.isGroupExpansionChanging());
+ final boolean dividersVisible = (mChildrenExpanded && mShowDividersWhenExpanded)
+ || (isExpanding && !mHideDividersDuringExpand);
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mAttachedChildren.get(i);
ExpandableViewState viewState = child.getViewState();
@@ -789,10 +789,10 @@
int childCount = mAttachedChildren.size();
ViewState tmpState = new ViewState();
float expandFraction = getGroupExpandFraction();
- final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
- || (mChildrenExpanded && mShowDividersWhenExpanded)
- || (mContainingNotification.isGroupExpansionChanging()
- && !mHideDividersDuringExpand);
+ final boolean isExpanding = !showingAsLowPriority()
+ && (mUserLocked || mContainingNotification.isGroupExpansionChanging());
+ final boolean dividersVisible = (mChildrenExpanded && mShowDividersWhenExpanded)
+ || (isExpanding && !mHideDividersDuringExpand);
for (int i = childCount - 1; i >= 0; i--) {
ExpandableNotificationRow child = mAttachedChildren.get(i);
ExpandableViewState viewState = child.getViewState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index d79c575..f0201cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -648,6 +648,7 @@
mController.hasActiveClearableNotifications(ROWS_ALL);
RemoteInputController remoteInputController = mRemoteInputManager.getController();
boolean showFooterView = (showDismissView || mController.hasActiveNotifications())
+ && mEmptyShadeView.getVisibility() == GONE
&& mStatusBarState != StatusBarState.KEYGUARD
&& !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()
&& (remoteInputController == null || !remoteInputController.isRemoteInputActive());
@@ -1184,7 +1185,8 @@
private void updateStackPosition(boolean listenerNeedsAnimation) {
// Consider interpolating from an mExpansionStartY for use on lockscreen and AOD
float endTopPosition = mTopPadding + mExtraTopInsetForFullShadeTransition
- + mAmbientState.getOverExpansion();
+ + mAmbientState.getOverExpansion()
+ - getCurrentOverScrollAmount(false /* top */);
final float fraction = mAmbientState.getExpansionFraction();
final float stackY = MathUtils.lerp(0, endTopPosition, fraction);
mAmbientState.setStackY(stackY);
@@ -1906,6 +1908,7 @@
if (onTop) {
notifyOverscrollTopListener(amount, isRubberbanded);
}
+ updateStackPosition();
requestChildrenUpdate();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index fb4f559..495eda7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -1071,10 +1071,6 @@
mView.setAlpha(alpha);
}
- public float getCurrentOverScrollAmount(boolean top) {
- return mView.getCurrentOverScrollAmount(top);
- }
-
public float calculateAppearFraction(float height) {
return mView.calculateAppearFraction(height);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 74e8de4..8f4a71c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -218,13 +218,7 @@
*/
private void initAlgorithmState(ViewGroup hostView, StackScrollAlgorithmState state,
AmbientState ambientState) {
- float bottomOverScroll = ambientState.getOverScrollAmount(false /* onTop */);
- int scrollY = ambientState.getScrollY();
-
- // Due to the overScroller, the stackscroller can have negative scroll state. This is
- // already accounted for by the top padding and doesn't need an additional adaption
- scrollY = Math.max(0, scrollY);
- state.scrollY = (int) (scrollY + bottomOverScroll);
+ state.scrollY = ambientState.getScrollY();
state.mCurrentYPosition = -state.scrollY;
state.mCurrentExpandedYPosition = -state.scrollY;
@@ -261,7 +255,7 @@
// Save the index of first view in shelf from when shade is fully
// expanded. Consider updating these states in updateContentView instead so that we don't
// have to recalculate in every frame.
- float currentY = -scrollY;
+ float currentY = -ambientState.getScrollY();
if (!ambientState.isOnKeyguard()) {
currentY += mNotificationScrimPadding;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 01d489f..c4d1abc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -63,6 +63,7 @@
private final Resources mResources;
private final BatteryController mBatteryController;
private final FeatureFlags mFeatureFlags;
+ private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
private final Set<Callback> mCallbacks = new HashSet<>();
@@ -78,7 +79,8 @@
BatteryController batteryController,
TunerService tunerService,
DumpManager dumpManager,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
mResources = resources;
mAmbientDisplayConfiguration = ambientDisplayConfiguration;
mAlwaysOnPolicy = alwaysOnDisplayPolicy;
@@ -89,6 +91,7 @@
mPowerManager = powerManager;
mPowerManager.setDozeAfterScreenOff(!mControlScreenOffAnimation);
mFeatureFlags = featureFlags;
+ mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
tunerService.addTunable(
this,
@@ -220,7 +223,8 @@
* then abruptly showing AOD.
*/
public boolean shouldControlUnlockedScreenOff() {
- return getAlwaysOn() && mFeatureFlags.useNewLockscreenAnimations();
+ return getAlwaysOn() && mFeatureFlags.useNewLockscreenAnimations()
+ && mUnlockedScreenOffAnimationController.shouldPlayUnlockedScreenOffAnimation();
}
private boolean getBoolean(String propName, int resId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index 68e2070..96276f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -38,7 +38,7 @@
* A view to show hints on Keyguard ("Swipe up to unlock", "Tap again to open").
*/
public class KeyguardIndicationTextView extends TextView {
- private static final long MSG_DURATION_MILLIS = 600;
+ private static final long MSG_DURATION_MILLIS = 1500;
private long mNextAnimationTime = 0;
private boolean mAnimationsEnabled = true;
private LinkedList<CharSequence> mMessages = new LinkedList<>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 35d1526..aaddfca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -4236,7 +4236,7 @@
int oldState = mBarState;
boolean keyguardShowing = statusBarState == KEYGUARD;
- if (mUnlockedScreenOffAnimationController.shouldPlayScreenOffAnimation()
+ if (mDozeParameters.shouldControlUnlockedScreenOff()
&& oldState == StatusBarState.SHADE
&& statusBarState == KEYGUARD) {
// This means we're doing the screen off animation - position the keyguard status
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
index 52f9aca..c958796 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
@@ -26,11 +26,9 @@
import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
-import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.os.Binder;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.os.Trace;
import android.util.Log;
import android.view.Display;
@@ -53,6 +51,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.google.android.collect.Lists;
@@ -108,12 +107,14 @@
StatusBarStateController statusBarStateController,
ConfigurationController configurationController,
KeyguardViewMediator keyguardViewMediator,
- KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor,
- DumpManager dumpManager) {
+ KeyguardBypassController keyguardBypassController,
+ SysuiColorExtractor colorExtractor,
+ DumpManager dumpManager,
+ KeyguardStateController keyguardStateController) {
mContext = context;
mWindowManager = windowManager;
mActivityManager = activityManager;
- mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
+ mKeyguardScreenRotation = keyguardStateController.isKeyguardScreenRotationAllowed();
mDozeParameters = dozeParameters;
mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
mLpChanged = new LayoutParams();
@@ -173,12 +174,6 @@
}
}
- private boolean shouldEnableKeyguardScreenRotation() {
- Resources res = mContext.getResources();
- return SystemProperties.getBoolean("lockscreen.rot_override", false)
- || res.getBoolean(R.bool.config_enableLockScreenRotation);
- }
-
/**
* Adds the notification shade view to the window manager.
*/
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 07ad136..5d2fe52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -21,7 +21,6 @@
import static android.app.StatusBarManager.WindowType;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
-import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -46,8 +45,6 @@
import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import static com.android.wm.shell.bubbles.BubbleController.TASKBAR_CHANGED_BROADCAST;
-import android.animation.ValueAnimator;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -121,6 +118,7 @@
import android.view.accessibility.AccessibilityManager;
import android.widget.DateTimeView;
+import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
@@ -402,8 +400,6 @@
private LightRevealScrim mLightRevealScrim;
private WiredChargingRippleController mChargingRippleAnimationController;
private PowerButtonReveal mPowerButtonReveal;
- private CircleReveal mCircleReveal;
- private ValueAnimator mCircleRevealAnimator = ValueAnimator.ofFloat(0f, 1f);
private final Object mQueueLock = new Object();
@@ -2778,9 +2774,14 @@
+ String.valueOf(CameraIntents.getOverrideCameraPackage(mContext)));
}
- public static void dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions) {
+ public static void dumpBarTransitions(
+ PrintWriter pw, String var, @Nullable BarTransitions transitions) {
pw.print(" "); pw.print(var); pw.print(".BarTransitions.mMode=");
- pw.println(BarTransitions.modeToString(transitions.getMode()));
+ if (transitions != null) {
+ pw.println(BarTransitions.modeToString(transitions.getMode()));
+ } else {
+ pw.println("Unknown");
+ }
}
public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
@@ -2803,11 +2804,11 @@
return mDisplayMetrics.density;
}
- float getDisplayWidth() {
+ public float getDisplayWidth() {
return mDisplayMetrics.widthPixels;
}
- float getDisplayHeight() {
+ public float getDisplayHeight() {
return mDisplayMetrics.heightPixels;
}
@@ -3537,9 +3538,6 @@
public void fadeKeyguardWhilePulsing() {
mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING,
()-> {
- if (shouldShowCircleReveal()) {
- startCircleReveal();
- }
hideKeyguard();
mStatusBarKeyguardViewManager.onKeyguardFadedAway();
}).start();
@@ -3880,7 +3878,7 @@
@Override
public void onDozeAmountChanged(float linear, float eased) {
if (mFeatureFlags.useNewLockscreenAnimations()
- && !mCircleRevealAnimator.isRunning()) {
+ && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
mLightRevealScrim.setRevealAmount(1f - linear);
}
}
@@ -3903,7 +3901,7 @@
|| (!isDozing && mWakefulnessLifecycle.getLastWakeReason()
== PowerManager.WAKE_REASON_POWER_BUTTON)) {
mLightRevealScrim.setRevealEffect(mPowerButtonReveal);
- } else if (!mCircleRevealAnimator.isRunning()) {
+ } else if (!(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
}
@@ -3915,36 +3913,8 @@
Trace.endSection();
}
- /**
- * Update the parameters for the dozing circle reveal that animates when the user authenticates
- * from AOD using the fingerprint sensor.
- */
- public void updateCircleReveal() {
- final PointF fpLocation = mAuthRippleController.getFingerprintSensorLocation();
- if (fpLocation != null) {
- mCircleReveal =
- new CircleReveal(
- fpLocation.x,
- fpLocation.y,
- 0,
- Math.max(Math.max(fpLocation.x, getDisplayWidth() - fpLocation.x),
- Math.max(fpLocation.y, getDisplayHeight() - fpLocation.y)));
- }
- }
-
- private void startCircleReveal() {
- mLightRevealScrim.setRevealEffect(mCircleReveal);
- mCircleRevealAnimator.cancel();
- mCircleRevealAnimator.addUpdateListener(animation ->
- mLightRevealScrim.setRevealAmount(
- (float) mCircleRevealAnimator.getAnimatedValue()));
- mCircleRevealAnimator.setDuration(900);
- mCircleRevealAnimator.start();
- }
-
- private boolean shouldShowCircleReveal() {
- return mCircleReveal != null && !mCircleRevealAnimator.isRunning()
- && mBiometricUnlockController.getBiometricType() == FINGERPRINT;
+ public LightRevealScrim getLightRevealScrim() {
+ return mLightRevealScrim;
}
private void updateKeyguardState() {
@@ -4084,7 +4054,7 @@
// The screen off animation uses our LightRevealScrim - we need to be expanded for it to
// be visible.
- if (mUnlockedScreenOffAnimationController.shouldPlayScreenOffAnimation()) {
+ if (mDozeParameters.shouldControlUnlockedScreenOff()) {
makeExpandedVisible(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 2601b8b..e846399 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -899,6 +899,9 @@
};
protected void updateStates() {
+ if (mContainer == null ) {
+ return;
+ }
int vis = mContainer.getSystemUiVisibility();
boolean showing = mShowing;
boolean occluded = mOccluded;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index a2d0672..52bf2d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -3,6 +3,8 @@
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
+import android.content.Context
+import android.content.res.Configuration
import android.os.Handler
import android.view.View
import com.android.systemui.animation.Interpolators
@@ -16,6 +18,7 @@
import com.android.systemui.statusbar.notification.PropertyAnimator
import com.android.systemui.statusbar.notification.stack.AnimationProperties
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
+import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
/**
@@ -38,10 +41,11 @@
*/
@SysUISingleton
class UnlockedScreenOffAnimationController @Inject constructor(
+ private val context: Context,
private val wakefulnessLifecycle: WakefulnessLifecycle,
private val statusBarStateControllerImpl: StatusBarStateControllerImpl,
private val keyguardViewMediatorLazy: dagger.Lazy<KeyguardViewMediator>,
- private val dozeParameters: DozeParameters
+ private val keyguardStateController: KeyguardStateController
) : WakefulnessLifecycle.Observer {
private val handler = Handler()
@@ -142,7 +146,7 @@
}
override fun onStartedGoingToSleep() {
- if (shouldPlayScreenOffAnimation()) {
+ if (shouldPlayUnlockedScreenOffAnimation()) {
lightRevealAnimationPlaying = true
lightRevealAnimator.start()
@@ -156,13 +160,31 @@
}
/**
- * Whether we should play the screen off animation when the phone starts going to sleep. We can
- * do that if dozeParameters says we can control the unlocked screen off animation and we are in
- * the SHADE state. If we're in KEYGUARD or SHADE_LOCKED, the regular
+ * Whether we want to play the screen off animation when the phone starts going to sleep, based
+ * on the current state of the device.
*/
- fun shouldPlayScreenOffAnimation(): Boolean {
- return dozeParameters.shouldControlUnlockedScreenOff() &&
- statusBarStateControllerImpl.state == StatusBarState.SHADE
+ fun shouldPlayUnlockedScreenOffAnimation(): Boolean {
+ // We only play the unlocked screen off animation if we are... unlocked.
+ if (statusBarStateControllerImpl.state != StatusBarState.SHADE) {
+ return false
+ }
+
+ // We currently draw both the light reveal scrim, and the AOD UI, in the shade. If it's
+ // already expanded and showing notifications/QS, the animation looks really messy. For now,
+ // disable it if the notification panel is expanded.
+ if (statusBar.notificationPanelViewController.isFullyExpanded) {
+ return false
+ }
+
+ // If we're not allowed to rotate the keyguard, then only do the screen off animation if
+ // we're in portrait. Otherwise, AOD will animate in sideways, which looks weird.
+ if (!keyguardStateController.isKeyguardScreenRotationAllowed &&
+ context.resources.configuration.orientation != Configuration.ORIENTATION_PORTRAIT) {
+ return false
+ }
+
+ // Otherwise, good to go.
+ return true
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
index af7bf95..fcfc967 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
@@ -57,6 +57,11 @@
boolean canPerformSmartSpaceTransition();
/**
+ * Whether the keyguard is allowed to rotate, or needs to be locked to the default orientation.
+ */
+ boolean isKeyguardScreenRotationAllowed();
+
+ /**
* If the device has PIN/pattern/password or a lock screen at all.
*/
boolean isMethodSecure();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index 0945a3f..64750bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -23,6 +23,7 @@
import android.content.IntentFilter;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Build;
+import android.os.SystemProperties;
import android.os.Trace;
import androidx.annotation.VisibleForTesting;
@@ -31,6 +32,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dumpable;
+import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
@@ -50,6 +52,7 @@
private static final String AUTH_BROADCAST_KEY = "debug_trigger_auth";
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+ private final Context mContext;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final LockPatternUtils mLockPatternUtils;
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
@@ -100,6 +103,7 @@
public KeyguardStateControllerImpl(Context context,
KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils,
SmartspaceTransitionController smartspaceTransitionController) {
+ mContext = context;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
@@ -243,6 +247,12 @@
}
@Override
+ public boolean isKeyguardScreenRotationAllowed() {
+ return SystemProperties.getBoolean("lockscreen.rot_override", false)
+ || mContext.getResources().getBoolean(R.bool.config_enableLockScreenRotation);
+ }
+
+ @Override
public boolean isFaceAuthEnabled() {
return mFaceAuthEnabled;
}
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 efeeac6..e6c4e82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -336,7 +336,7 @@
RemoteInput.addResultsToIntent(mRemoteInputs, fillInIntent,
results);
- mEntry.remoteInputText = mEditText.getText();
+ mEntry.remoteInputText = mEditText.getText().toString();
// TODO(b/188646667): store attachment to entry
mEntry.remoteInputUri = null;
mEntry.remoteInputMimeType = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 5c44017..1ebb9dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -21,6 +21,7 @@
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import static com.android.systemui.DejankUtils.whitelistIpcs;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.Dialog;
import android.app.IActivityTaskManager;
@@ -48,6 +49,7 @@
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
import android.widget.BaseAdapter;
import com.android.internal.annotations.VisibleForTesting;
@@ -63,6 +65,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSUserSwitcherEvent;
@@ -76,6 +79,8 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
import javax.inject.Inject;
import javax.inject.Provider;
@@ -123,23 +128,35 @@
private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
private final UiEventLogger mUiEventLogger;
public final DetailAdapter mUserDetailAdapter;
+ private final Executor mUiBgExecutor;
+ private final boolean mGuestUserAutoCreated;
+ private final AtomicBoolean mGuestCreationScheduled;
@Inject
- public UserSwitcherController(Context context, KeyguardStateController keyguardStateController,
- @Main Handler handler, ActivityStarter activityStarter,
- BroadcastDispatcher broadcastDispatcher, UiEventLogger uiEventLogger,
+ public UserSwitcherController(Context context,
+ KeyguardStateController keyguardStateController,
+ @Main Handler handler,
+ ActivityStarter activityStarter,
+ BroadcastDispatcher broadcastDispatcher,
+ UiEventLogger uiEventLogger,
TelephonyListenerManager telephonyListenerManager,
- IActivityTaskManager activityTaskManager, UserDetailAdapter userDetailAdapter) {
+ IActivityTaskManager activityTaskManager,
+ UserDetailAdapter userDetailAdapter,
+ @UiBackground Executor uiBgExecutor) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
mTelephonyListenerManager = telephonyListenerManager;
mActivityTaskManager = activityTaskManager;
mUiEventLogger = uiEventLogger;
- mGuestResumeSessionReceiver = new GuestResumeSessionReceiver(mUiEventLogger);
+ mGuestResumeSessionReceiver = new GuestResumeSessionReceiver(this, mUiEventLogger);
mUserDetailAdapter = userDetailAdapter;
+ mUiBgExecutor = uiBgExecutor;
if (!UserManager.isGuestUserEphemeral()) {
mGuestResumeSessionReceiver.register(mBroadcastDispatcher);
}
+ mGuestUserAutoCreated = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_guestUserAutoCreated);
+ mGuestCreationScheduled = new AtomicBoolean();
mKeyguardStateController = keyguardStateController;
mHandler = handler;
mActivityStarter = activityStarter;
@@ -379,21 +396,13 @@
int id;
if (record.isGuest && record.info == null) {
// No guest user. Create one.
- UserInfo guest;
- try {
- guest = mUserManager.createGuest(mContext,
- mContext.getString(com.android.settingslib.R.string.guest_nickname));
- } catch (UserManager.UserOperationException e) {
- Log.e(TAG, "Couldn't create guest user", e);
- return;
- }
- if (guest == null) {
- // Couldn't create guest, most likely because there already exists one, we just
- // haven't reloaded the user list yet.
+ int guestId = createGuest();
+ if (guestId == UserHandle.USER_NULL) {
+ // This may happen if we haven't reloaded the user list yet.
return;
}
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_ADD);
- id = guest.id;
+ id = guestId;
} else if (record.isAddUser) {
showAddUserDialog();
return;
@@ -457,11 +466,6 @@
mAddUserDialog.show();
}
- protected void exitGuest(int id, int targetId) {
- switchToUserId(targetId);
- mUserManager.removeUser(id);
- }
-
private void listenForCallState() {
mTelephonyListenerManager.addCallStateListener(mPhoneStateListener);
}
@@ -576,6 +580,7 @@
pw.print(" "); pw.println(u.toString());
}
pw.println("mSimpleUserSwitcher=" + mSimpleUserSwitcher);
+ pw.println("mGuestUserAutoCreated=" + mGuestUserAutoCreated);
}
/** Returns the name of the current user of the phone. */
@@ -602,6 +607,126 @@
return mUsers;
}
+ /**
+ * Removes guest user and switches to target user. The guest must be the current user and its id
+ * must be {@code guestUserId}.
+ *
+ * <p>If {@code targetUserId} is {@link UserHandle.USER_NULL}, then create a new guest user in
+ * the foreground, and immediately switch to it. This is used for wiping the current guest and
+ * replacing it with a new one.
+ *
+ * <p>If {@code targetUserId} is specified, then remove the guest in the background while
+ * switching to {@code targetUserId}.
+ *
+ * <p>If device is configured with {@link
+ * com.android.internal.R.bool.config_guestUserAutoCreated}, then after guest user is removed, a
+ * new one is created in the background. This has no effect if {@code targetUserId} is {@link
+ * UserHandle.USER_NULL}.
+ *
+ * @param guestUserId id of the guest user to remove
+ * @param targetUserId id of the user to switch to after guest is removed. If {@link
+ * UserHandle.USER_NULL}, then switch immediately to the newly created guest user.
+ */
+ public void removeGuestUser(@UserIdInt int guestUserId, @UserIdInt int targetUserId) {
+ UserInfo currentUser;
+ try {
+ currentUser = ActivityManager.getService().getCurrentUser();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't remove guest because ActivityManager is dead");
+ return;
+ }
+ if (currentUser.id != guestUserId) {
+ Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
+ + " is not current user (" + currentUser.id + ")");
+ return;
+ }
+ if (!currentUser.isGuest()) {
+ Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
+ + " is not a guest");
+ return;
+ }
+
+ boolean marked = mUserManager.markGuestForDeletion(currentUser.id);
+ if (!marked) {
+ Log.w(TAG, "Couldn't mark the guest for deletion for user " + guestUserId);
+ return;
+ }
+
+ try {
+ if (targetUserId == UserHandle.USER_NULL) {
+ // Create a new guest in the foreground, and then immediately switch to it
+ int newGuestId = createGuest();
+ if (newGuestId == UserHandle.USER_NULL) {
+ Log.e(TAG, "Could not create new guest, switching back to system user");
+ switchToUserId(UserHandle.USER_SYSTEM);
+ mUserManager.removeUser(currentUser.id);
+ WindowManagerGlobal.getWindowManagerService().lockNow(/* options= */ null);
+ return;
+ }
+ switchToUserId(newGuestId);
+ mUserManager.removeUser(currentUser.id);
+ } else {
+ if (mGuestUserAutoCreated) {
+ // TODO(b/191067027): Move guest recreation to system_server
+ scheduleGuestCreation();
+ }
+ switchToUserId(targetUserId);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't remove guest because ActivityManager or WindowManager is dead");
+ return;
+ }
+ }
+
+ private void scheduleGuestCreation() {
+ if (!mGuestCreationScheduled.compareAndSet(false, true)) {
+ return;
+ }
+
+ mUiBgExecutor.execute(() -> {
+ int newGuestId = createGuest();
+ if (newGuestId == UserHandle.USER_NULL) {
+ Log.w(TAG, "Could not create new guest while exiting existing guest");
+ }
+ mGuestCreationScheduled.set(false);
+ });
+
+ }
+
+ /**
+ * If there is no guest on the device, schedule creation of a new guest user in the background.
+ */
+ public void guaranteeGuestPresent() {
+ if (mUserManager.findCurrentGuestUser() == null) {
+ scheduleGuestCreation();
+ }
+ }
+
+ /**
+ * Creates a guest user and return its multi-user user ID.
+ *
+ * This method does not check if a guest already exists before it makes a call to
+ * {@link UserManager} to create a new one.
+ *
+ * @return The multi-user user ID of the newly created guest user, or
+ * {@link UserHandle.USER_NULL} if the guest couldn't be created.
+ */
+ public @UserIdInt int createGuest() {
+ UserInfo guest;
+ try {
+ guest = mUserManager.createGuest(mContext,
+ mContext.getString(com.android.settingslib.R.string.guest_nickname));
+ } catch (UserManager.UserOperationException e) {
+ Log.e(TAG, "Couldn't create guest user", e);
+ return UserHandle.USER_NULL;
+ }
+ if (guest == null) {
+ Log.e(TAG, "Couldn't create guest, most likely because there already exists one");
+ return UserHandle.USER_NULL;
+ }
+ return guest.id;
+ }
+
public static abstract class BaseUserAdapter extends BaseAdapter {
final UserSwitcherController mController;
@@ -662,10 +787,15 @@
public String getName(Context context, UserRecord item) {
if (item.isGuest) {
if (item.isCurrent) {
- return context.getString(com.android.settingslib.R.string.guest_exit_guest);
+ return context.getString(mController.mGuestUserAutoCreated
+ ? com.android.settingslib.R.string.guest_reset_guest
+ : com.android.settingslib.R.string.guest_exit_guest);
} else {
+ // If config_guestUserAutoCreated, always show guest nickname instead of "Add
+ // guest" to make it seem as though the device always has a guest ready for use
return context.getString(
- item.info == null ? com.android.settingslib.R.string.guest_new_guest
+ item.info == null && !mController.mGuestUserAutoCreated
+ ? com.android.settingslib.R.string.guest_new_guest
: com.android.settingslib.R.string.guest_nickname);
}
} else if (item.isAddUser) {
@@ -882,12 +1012,15 @@
public ExitGuestDialog(Context context, int guestId, int targetId) {
super(context);
- setTitle(R.string.guest_exit_guest_dialog_title);
+ setTitle(mGuestUserAutoCreated ? R.string.guest_reset_guest_dialog_title
+ : R.string.guest_exit_guest_dialog_title);
setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
setButton(DialogInterface.BUTTON_NEGATIVE,
context.getString(android.R.string.cancel), this);
setButton(DialogInterface.BUTTON_POSITIVE,
- context.getString(R.string.guest_exit_guest_dialog_remove), this);
+ context.getString(
+ mGuestUserAutoCreated ? R.string.guest_reset_guest_dialog_remove
+ : R.string.guest_exit_guest_dialog_remove), this);
SystemUIDialog.setWindowOnTop(this);
setCanceledOnTouchOutside(false);
mGuestId = guestId;
@@ -901,7 +1034,7 @@
} else {
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE);
dismiss();
- exitGuest(mGuestId, mTargetId);
+ removeGuestUser(mGuestId, mTargetId);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 26f4a2b..d97815f 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -68,7 +68,8 @@
private static final String[] RESET_EXCEPTION_LIST = new String[] {
QSTileHost.TILES_SETTING,
Settings.Secure.DOZE_ALWAYS_ON,
- Settings.Secure.MEDIA_CONTROLS_RESUME
+ Settings.Secure.MEDIA_CONTROLS_RESUME,
+ Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION
};
private final Observer mObserver = new Observer();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index a5ccc47..ab4b1f1 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -135,7 +135,7 @@
private boolean mShowVolumeDialog;
private boolean mShowSafetyWarning;
private long mLastToggledRingerOn;
- private boolean mDeviceInteractive;
+ private boolean mDeviceInteractive = true;
private boolean mDestroyed;
private VolumePolicy mVolumePolicy;
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
index 8412a8a..0c53477 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
@@ -104,15 +104,14 @@
float percentDistanceFromCenter) {
CharSequence centerCardText = getLabelText(centerCard);
Drawable centerCardIcon = getHeaderIcon(mContext, centerCard);
- if (!TextUtils.equals(mCenterCardText, centerCardText)) {
- mCenterCardText = centerCardText;
+ renderActionButton(centerCard, mIsDeviceLocked, mIsUdfpsEnabled);
+ if (centerCard.isUiEquivalent(nextCard)) {
+ mCardLabel.setAlpha(1f);
+ mIcon.setAlpha(1f);
+ mActionButton.setAlpha(1f);
+ } else {
mCardLabel.setText(centerCardText);
mIcon.setImageDrawable(centerCardIcon);
- }
- renderActionButton(centerCard, mIsDeviceLocked, mIsUdfpsEnabled);
- if (TextUtils.equals(centerCardText, getLabelText(nextCard))) {
- mCardLabel.setAlpha(1f);
- } else {
mCardLabel.setAlpha(percentDistanceFromCenter);
mIcon.setAlpha(percentDistanceFromCenter);
mActionButton.setAlpha(percentDistanceFromCenter);
@@ -141,6 +140,7 @@
mErrorView.setVisibility(GONE);
mEmptyStateView.setVisibility(GONE);
mIcon.setImageDrawable(getHeaderIcon(mContext, data.get(selectedIndex)));
+ mCardLabel.setText(getLabelText(data.get(selectedIndex)));
renderActionButton(data.get(selectedIndex), isDeviceLocked, mIsUdfpsEnabled);
if (shouldAnimate) {
animateViewsShown(mIcon, mCardLabel, mActionButton);
@@ -248,20 +248,20 @@
private void renderActionButton(
WalletCardViewInfo walletCard, boolean isDeviceLocked, boolean isUdfpsEnabled) {
CharSequence actionButtonText = getActionButtonText(walletCard);
- if (!isUdfpsEnabled && isDeviceLocked) {
+ if (!isUdfpsEnabled && actionButtonText != null) {
mActionButton.setVisibility(VISIBLE);
- mActionButton.setText(R.string.wallet_action_button_label_unlock);
- mActionButton.setOnClickListener(mDeviceLockedActionOnClickListener);
- } else if (!isDeviceLocked && actionButtonText != null) {
mActionButton.setText(actionButtonText);
- mActionButton.setVisibility(VISIBLE);
- mActionButton.setOnClickListener(v -> {
- try {
- walletCard.getPendingIntent().send();
- } catch (PendingIntent.CanceledException e) {
- Log.w(TAG, "Error sending pending intent for wallet card");
- }
- });
+ mActionButton.setOnClickListener(
+ isDeviceLocked
+ ? mDeviceLockedActionOnClickListener
+ : v -> {
+ try {
+ walletCard.getPendingIntent().send();
+ } catch (PendingIntent.CanceledException e) {
+ Log.w(TAG, "Error sending pending intent for wallet card.");
+ }
+ }
+ );
} else {
mActionButton.setVisibility(GONE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index 5441bd4..a29a638 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -617,7 +617,7 @@
* cancel it (and hence the bubbles associated with it).
*
* @return true if we want to intercept the dismissal of the entry, else false.
- * @see Bubbles#handleDismissalInterception(BubbleEntry, List, IntConsumer)
+ * @see Bubbles#handleDismissalInterception(BubbleEntry, List, IntConsumer, Executor)
*/
public boolean handleDismissalInterception(NotificationEntry entry) {
if (entry == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 92ef850..3af82f9 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -34,6 +34,7 @@
import android.inputmethodservice.InputMethodService;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.view.KeyEvent;
import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -57,6 +58,7 @@
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.nano.WmShellTraceProto;
import com.android.wm.shell.onehanded.OneHanded;
+import com.android.wm.shell.onehanded.OneHandedEventCallback;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.onehanded.OneHandedUiEventLogger;
import com.android.wm.shell.pip.Pip;
@@ -253,6 +255,15 @@
}
});
+ oneHanded.registerEventCallback(new OneHandedEventCallback() {
+ @Override
+ public void notifyExpandNotification() {
+ mSysUiMainExecutor.execute(
+ () -> mCommandQueue.handleSystemKey(
+ KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN));
+ }
+ });
+
mOneHandedKeyguardCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onKeyguardBouncerChanged(boolean bouncer) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
index 240fdf3..d87a26b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -25,6 +25,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.CommandRegistry
+import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.StatusBar
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -53,6 +54,7 @@
@Mock private lateinit var authController: AuthController
@Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
@Mock private lateinit var bypassController: KeyguardBypassController
+ @Mock private lateinit var biometricUnlockController: BiometricUnlockController
@Before
fun setUp() {
@@ -66,6 +68,7 @@
commandRegistry,
notificationShadeWindowController,
bypassController,
+ biometricUnlockController,
rippleView
)
controller.init()
@@ -90,7 +93,7 @@
// THEN update sensor location and show ripple
verify(rippleView).setSensorLocation(fpsLocation)
- verify(rippleView).startRipple(any())
+ verify(rippleView).startRipple(any(), any())
}
@Test
@@ -111,7 +114,7 @@
false /* isStrongBiometric */)
// THEN no ripple
- verify(rippleView, never()).startRipple(any())
+ verify(rippleView, never()).startRipple(any(), any())
}
@Test
@@ -132,7 +135,7 @@
false /* isStrongBiometric */)
// THEN no ripple
- verify(rippleView, never()).startRipple(any())
+ verify(rippleView, never()).startRipple(any(), any())
}
@Test
@@ -156,7 +159,7 @@
// THEN show ripple
verify(rippleView).setSensorLocation(faceLocation)
- verify(rippleView).startRipple(any())
+ verify(rippleView).startRipple(any(), any())
}
@Test
@@ -176,7 +179,7 @@
false /* isStrongBiometric */)
// THEN no ripple
- verify(rippleView, never()).startRipple(any())
+ verify(rippleView, never()).startRipple(any(), any())
}
@Test
@@ -191,7 +194,7 @@
0 /* userId */,
BiometricSourceType.FACE /* type */,
false /* isStrongBiometric */)
- verify(rippleView, never()).startRipple(any())
+ verify(rippleView, never()).startRipple(any(), any())
}
@Test
@@ -206,7 +209,7 @@
0 /* userId */,
BiometricSourceType.FINGERPRINT /* type */,
false /* isStrongBiometric */)
- verify(rippleView, never()).startRipple(any())
+ verify(rippleView, never()).startRipple(any(), any())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index c0b45c6..a11b9cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -16,7 +16,10 @@
package com.android.systemui.doze;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
+
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
@@ -161,7 +164,7 @@
clearInvocations(mSensors);
mTriggers.transitionTo(DozeMachine.State.DOZE_PULSING, DozeMachine.State.DOZE_PULSE_DONE);
- mTriggers.transitionTo(DozeMachine.State.DOZE_PULSE_DONE, DozeMachine.State.DOZE_AOD);
+ mTriggers.transitionTo(DozeMachine.State.DOZE_PULSE_DONE, DOZE_AOD);
waitForSensorManager();
verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor));
}
@@ -207,7 +210,7 @@
mTriggers.onSensor(DozeLog.REASON_SENSOR_QUICK_PICKUP, 100, 100, null);
// THEN device goes into aod (shows clock with black background)
- verify(mMachine).requestState(DozeMachine.State.DOZE_AOD);
+ verify(mMachine).requestState(DOZE_AOD);
// THEN a log is taken that quick pick up was triggered
verify(mUiEventLogger).log(DozingUpdateUiEvent.DOZING_UPDATE_QUICK_PICKUP);
@@ -218,7 +221,7 @@
// GIVEN quick pickup is triggered when device is in DOZE
when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
mTriggers.onSensor(DozeLog.REASON_SENSOR_QUICK_PICKUP, 100, 100, null);
- verify(mMachine).requestState(DozeMachine.State.DOZE_AOD);
+ verify(mMachine).requestState(DOZE_AOD);
verify(mMachine, never()).requestState(DozeMachine.State.DOZE);
// WHEN next executable is run
@@ -234,6 +237,8 @@
@Test
public void testOnSensor_Fingerprint() {
+ // GIVEN dozing state
+ when(mMachine.getState()).thenReturn(DOZE_AOD);
final int screenX = 100;
final int screenY = 100;
final float misc = -1;
@@ -241,8 +246,20 @@
final float major = 3f;
final int reason = DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
float[] rawValues = new float[]{screenX, screenY, misc, major, minor};
+
+ // WHEN longpress gesture is triggered
mTriggers.onSensor(reason, screenX, screenY, rawValues);
+
+ // THEN
+ // * don't immediately send interrupt
+ // * immediately extend pulse
+ verify(mAuthController, never()).onAodInterrupt(anyInt(), anyInt(), anyFloat(), anyFloat());
verify(mHost).extendPulse(reason);
+
+ // WHEN display state changes to ON
+ mTriggers.onScreenState(Display.STATE_ON);
+
+ // THEN send interrupt
verify(mAuthController).onAodInterrupt(eq(screenX), eq(screenY), eq(major), eq(minor));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
index afe5c0b..1d34aac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
@@ -43,6 +43,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.wakelock.WakeLockFake;
@@ -77,6 +78,8 @@
private DozeUi mDozeUi;
@Mock
private StatusBarStateController mStatusBarStateController;
+ @Mock
+ private ConfigurationController mConfigurationController;
@Before
public void setUp() throws Exception {
@@ -89,7 +92,7 @@
mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler,
mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService,
- () -> mStatusBarStateController);
+ () -> mStatusBarStateController, mConfigurationController);
mDozeUi.setDozeMachine(mMachine);
}
@@ -146,7 +149,7 @@
when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler,
mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService,
- () -> mStatusBarStateController);
+ () -> mStatusBarStateController, mConfigurationController);
mDozeUi.setDozeMachine(mMachine);
// Never animate if display doesn't support it.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
index f0f5420..adc8ffc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
@@ -30,6 +30,7 @@
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Color;
import android.media.AudioManager;
@@ -109,6 +110,7 @@
@Mock private RingerModeTracker mRingerModeTracker;
@Mock private RingerModeLiveData mRingerModeLiveData;
@Mock private SysUiState mSysUiState;
+ @Mock private PackageManager mPackageManager;
@Mock private Handler mHandler;
@Mock private UserContextProvider mUserContextProvider;
@Mock private StatusBar mStatusBar;
@@ -123,6 +125,8 @@
when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);
when(mUserContextProvider.getUserContext()).thenReturn(mContext);
+ when(mResources.getConfiguration()).thenReturn(
+ getContext().getResources().getConfiguration());
mGlobalActionsDialogLite = new GlobalActionsDialogLite(mContext,
mWindowManagerFuncs,
@@ -154,6 +158,7 @@
mRingerModeTracker,
mSysUiState,
mHandler,
+ mPackageManager,
mStatusBar
);
mGlobalActionsDialogLite.setZeroDialogPressDelayForTesting();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
index c543470..e5c104e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
@@ -33,6 +33,7 @@
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Color;
@@ -124,6 +125,7 @@
@Mock GlobalActionsPanelPlugin.PanelViewController mWalletController;
@Mock private Handler mHandler;
@Mock private UserTracker mUserTracker;
+ @Mock private PackageManager mPackageManager;
@Mock private SecureSettings mSecureSettings;
@Mock private StatusBar mStatusBar;
@@ -136,6 +138,8 @@
allowTestableLooperAsMainThread();
when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);
+ when(mResources.getConfiguration()).thenReturn(
+ getContext().getResources().getConfiguration());
mGlobalActionsDialog = new GlobalActionsDialog(mContext,
mWindowManagerFuncs,
@@ -167,6 +171,7 @@
mRingerModeTracker,
mSysUiState,
mHandler,
+ mPackageManager,
mStatusBar
);
mGlobalActionsDialog.setZeroDialogPressDelayForTesting();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
index 2f78532..5157668 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
@@ -34,7 +34,6 @@
import android.graphics.Color;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
-import android.view.View;
import androidx.test.filters.SmallTest;
@@ -258,8 +257,8 @@
// WHEN the device is dozing
mStatusBarStateListener.onDozingChanged(true);
- // THEN the view is GONE
- verify(mView).setVisibility(View.GONE);
+ // THEN switch to INDICATION_TYPE_NONE
+ verify(mView).switchIndication(null);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index d9b56a4..1dacc62 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -52,6 +52,7 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DeviceConfigProxyFake;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -78,6 +79,7 @@
private @Mock DumpManager mDumpManager;
private @Mock PowerManager mPowerManager;
private @Mock TrustManager mTrustManager;
+ private @Mock UserSwitcherController mUserSwitcherController;
private @Mock NavigationModeController mNavigationModeController;
private @Mock KeyguardDisplayManager mKeyguardDisplayManager;
private @Mock DozeParameters mDozeParameters;
@@ -100,13 +102,27 @@
when(mPowerManager.newWakeLock(anyInt(), any())).thenReturn(mock(WakeLock.class));
mViewMediator = new KeyguardViewMediator(
- mContext, mFalsingCollector, mLockPatternUtils, mBroadcastDispatcher,
+ mContext,
+ mFalsingCollector,
+ mLockPatternUtils,
+ mBroadcastDispatcher,
() -> mStatusBarKeyguardViewManager,
- mDismissCallbackRegistry, mUpdateMonitor, mDumpManager, mUiBgExecutor,
- mPowerManager, mTrustManager, mDeviceConfig, mNavigationModeController,
- mKeyguardDisplayManager, mDozeParameters, mStatusBarStateController,
- mKeyguardStateController, () -> mKeyguardUnlockAnimationController,
- mUnlockedScreenOffAnimationController, () -> mNotificationShadeDepthController);
+ mDismissCallbackRegistry,
+ mUpdateMonitor,
+ mDumpManager,
+ mUiBgExecutor,
+ mPowerManager,
+ mTrustManager,
+ mUserSwitcherController,
+ mDeviceConfig,
+ mNavigationModeController,
+ mKeyguardDisplayManager,
+ mDozeParameters,
+ mStatusBarStateController,
+ mKeyguardStateController,
+ () -> mKeyguardUnlockAnimationController,
+ mUnlockedScreenOffAnimationController,
+ () -> mNotificationShadeDepthController);
mViewMediator.start();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
index 63ce98a..910b381 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
@@ -56,7 +56,7 @@
@Test
public void baseState() throws Exception {
- assertEquals(WakefulnessLifecycle.WAKEFULNESS_ASLEEP, mWakefulness.getWakefulness());
+ assertEquals(WakefulnessLifecycle.WAKEFULNESS_AWAKE, mWakefulness.getWakefulness());
verifyNoMoreInteractions(mWakefulnessObserver);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index 15cfee8..3128db4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -9,8 +9,8 @@
import android.media.MediaMetadata
import android.media.session.MediaController
import android.media.session.MediaSession
-import android.provider.Settings
import android.os.Bundle
+import android.provider.Settings
import android.service.notification.StatusBarNotification
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
@@ -20,6 +20,7 @@
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.SbnBuilder
+import com.android.systemui.tuner.TunerService
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
@@ -86,6 +87,8 @@
lateinit var mediaNotification: StatusBarNotification
@Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
private val clock = FakeSystemClock()
+ @Mock private lateinit var tunerService: TunerService
+ @Captor lateinit var tunableCaptor: ArgumentCaptor<TunerService.Tunable>
private val originalSmartspaceSetting = Settings.Secure.getInt(context.contentResolver,
Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 1)
@@ -114,8 +117,11 @@
smartspaceMediaDataProvider = smartspaceMediaDataProvider,
useMediaResumption = true,
useQsMediaPlayer = true,
- systemClock = clock
+ systemClock = clock,
+ tunerService = tunerService
)
+ verify(tunerService).addTunable(capture(tunableCaptor),
+ eq(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION))
session = MediaSession(context, "MediaDataManagerTestSession")
mediaNotification = SbnBuilder().run {
setPkg(PACKAGE_NAME)
@@ -364,6 +370,9 @@
fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_callsRemoveListener() {
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
smartspaceMediaDataProvider.onTargetsAvailable(listOf())
+ foregroundExecutor.advanceClockToLast()
+ foregroundExecutor.runAllReady()
+
verify(listener).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false))
}
@@ -372,6 +381,8 @@
// WHEN media recommendation setting is off
Settings.Secure.putInt(context.contentResolver,
Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 0)
+ tunableCaptor.value.onTuningChanged(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, "0")
+
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
// THEN smartspace signal is ignored
@@ -380,6 +391,24 @@
}
@Test
+ fun testMediaRecommendationDisabled_removesSmartspaceData() {
+ // GIVEN a media recommendation card is present
+ smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
+ verify(listener).onSmartspaceMediaDataLoaded(eq(KEY_MEDIA_SMARTSPACE), anyObject(),
+ anyBoolean())
+
+ // WHEN the media recommendation setting is turned off
+ Settings.Secure.putInt(context.contentResolver,
+ Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 0)
+ tunableCaptor.value.onTuningChanged(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, "0")
+
+ // THEN listeners are notified
+ foregroundExecutor.advanceClockToLast()
+ foregroundExecutor.runAllReady()
+ verify(listener).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(true))
+ }
+
+ @Test
fun testOnMediaDataChanged_updatesLastActiveTime() {
val currentTime = clock.elapsedRealtime()
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java
index 5f4d90b..f6264ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java
@@ -49,6 +49,7 @@
import com.android.wm.shell.bubbles.Bubble;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -213,6 +214,7 @@
verify(mBubblesManager, never()).expandStackAndSelectBubble(any(NotificationEntry.class));
}
+ @Ignore
@Test
public void testBubbleWithNoNotifOpensBubble() throws Exception {
Bubble bubble = mock(Bubble.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index b0e3e3e..2ae4cbe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -46,6 +46,7 @@
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
+import com.android.systemui.qs.external.CustomTileStatePersister;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.settings.UserTracker;
@@ -132,7 +133,7 @@
() -> mock(AutoTileManager.class), mock(DumpManager.class),
mock(BroadcastDispatcher.class), Optional.of(mock(StatusBar.class)),
mock(QSLogger.class), mock(UiEventLogger.class), mock(UserTracker.class),
- mock(SecureSettings.class));
+ mock(SecureSettings.class), mock(CustomTileStatePersister.class));
qs.setHost(host);
qs.setListening(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 7c73b4c..69bdcbcf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -59,6 +59,8 @@
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.external.CustomTile;
+import com.android.systemui.qs.external.CustomTileStatePersister;
+import com.android.systemui.qs.external.TileServiceKey;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
@@ -125,6 +127,8 @@
private UserTracker mUserTracker;
@Mock
private SecureSettings mSecureSettings;
+ @Mock
+ private CustomTileStatePersister mCustomTileStatePersister;
private Handler mHandler;
private TestableLooper mLooper;
@@ -145,7 +149,7 @@
mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler,
mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpManager,
mBroadcastDispatcher, mStatusBar, mQSLogger, mUiEventLogger, mUserTracker,
- mSecureSettings);
+ mSecureSettings, mCustomTileStatePersister);
setUpTileFactory();
when(mSecureSettings.getStringForUser(eq(QSTileHost.TILES_SETTING), anyInt()))
@@ -371,6 +375,14 @@
verify(mQSLogger, never()).logTileDestroyed(isNull(), anyString());
}
+ @Test
+ public void testCustomTileRemoved_stateDeleted() {
+ mQSTileHost.changeTiles(List.of(CUSTOM_TILE_SPEC), List.of());
+
+ verify(mCustomTileStatePersister)
+ .removeState(new TileServiceKey(CUSTOM_TILE, mQSTileHost.getUserId()));
+ }
+
private class TestQSTileHost extends QSTileHost {
TestQSTileHost(Context context, StatusBarIconController iconController,
QSFactory defaultFactory, Handler mainHandler, Looper bgLooper,
@@ -378,10 +390,11 @@
Provider<AutoTileManager> autoTiles, DumpManager dumpManager,
BroadcastDispatcher broadcastDispatcher, StatusBar statusBar, QSLogger qsLogger,
UiEventLogger uiEventLogger, UserTracker userTracker,
- SecureSettings secureSettings) {
+ SecureSettings secureSettings, CustomTileStatePersister customTileStatePersister) {
super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager,
tunerService, autoTiles, dumpManager, broadcastDispatcher,
- Optional.of(statusBar), qsLogger, uiEventLogger, userTracker, secureSettings);
+ Optional.of(statusBar), qsLogger, uiEventLogger, userTracker, secureSettings,
+ customTileStatePersister);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileStatePersisterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileStatePersisterTest.kt
new file mode 100644
index 0000000..6c96576
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileStatePersisterTest.kt
@@ -0,0 +1,159 @@
+/*
+ * 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.external
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.SharedPreferences
+import android.service.quicksettings.Tile
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Answers
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class CustomTileStatePersisterTest : SysuiTestCase() {
+
+ companion object {
+ private val TEST_COMPONENT = ComponentName("pkg", "cls")
+ private const val TEST_USER = 0
+ private val KEY = TileServiceKey(TEST_COMPONENT, TEST_USER)
+
+ private const val TEST_STATE = Tile.STATE_INACTIVE
+ private const val TEST_LABEL = "test_label"
+ private const val TEST_SUBTITLE = "test_subtitle"
+ private const val TEST_CONTENT_DESCRIPTION = "test_content_description"
+ private const val TEST_STATE_DESCRIPTION = "test_state_description"
+
+ private fun Tile.isEqualTo(other: Tile): Boolean {
+ return state == other.state &&
+ label == other.label &&
+ subtitle == other.subtitle &&
+ contentDescription == other.contentDescription &&
+ stateDescription == other.stateDescription
+ }
+ }
+
+ @Mock
+ private lateinit var mockContext: Context
+ @Mock
+ private lateinit var sharedPreferences: SharedPreferences
+ @Mock(answer = Answers.RETURNS_SELF)
+ private lateinit var editor: SharedPreferences.Editor
+ private lateinit var tile: Tile
+ private lateinit var customTileStatePersister: CustomTileStatePersister
+
+ @Captor
+ private lateinit var stringCaptor: ArgumentCaptor<String>
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ `when`(mockContext.getSharedPreferences(anyString(), anyInt()))
+ .thenReturn(sharedPreferences)
+ `when`(sharedPreferences.edit()).thenReturn(editor)
+
+ tile = Tile()
+ customTileStatePersister = CustomTileStatePersister(mockContext)
+ }
+
+ @Test
+ fun testWriteState() {
+ tile.apply {
+ state = TEST_STATE
+ label = TEST_LABEL
+ subtitle = TEST_SUBTITLE
+ contentDescription = TEST_CONTENT_DESCRIPTION
+ stateDescription = TEST_STATE_DESCRIPTION
+ }
+
+ customTileStatePersister.persistState(KEY, tile)
+
+ verify(editor).putString(eq(KEY.toString()), capture(stringCaptor))
+
+ assertThat(tile.isEqualTo(readTileFromString(stringCaptor.value))).isTrue()
+ }
+
+ @Test
+ fun testReadState() {
+ tile.apply {
+ state = TEST_STATE
+ label = TEST_LABEL
+ subtitle = TEST_SUBTITLE
+ contentDescription = TEST_CONTENT_DESCRIPTION
+ stateDescription = TEST_STATE_DESCRIPTION
+ }
+
+ `when`(sharedPreferences.getString(eq(KEY.toString()), any()))
+ .thenReturn(writeToString(tile))
+
+ assertThat(tile.isEqualTo(customTileStatePersister.readState(KEY)!!)).isTrue()
+ }
+
+ @Test
+ fun testReadStateDefault() {
+ `when`(sharedPreferences.getString(any(), any())).thenAnswer {
+ it.getArgument(1)
+ }
+
+ assertThat(customTileStatePersister.readState(KEY)).isNull()
+ }
+
+ @Test
+ fun testStoreNulls() {
+ assertThat(tile.label).isNull()
+
+ customTileStatePersister.persistState(KEY, tile)
+
+ verify(editor).putString(eq(KEY.toString()), capture(stringCaptor))
+
+ assertThat(readTileFromString(stringCaptor.value).label).isNull()
+ }
+
+ @Test
+ fun testReadNulls() {
+ assertThat(tile.label).isNull()
+
+ `when`(sharedPreferences.getString(eq(KEY.toString()), any()))
+ .thenReturn(writeToString(tile))
+
+ assertThat(customTileStatePersister.readState(KEY)!!.label).isNull()
+ }
+
+ @Test
+ fun testRemoveState() {
+ customTileStatePersister.removeState(KEY)
+
+ verify(editor).remove(KEY.toString())
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
index b1c3d1d..9b5c161 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
@@ -38,6 +38,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.util.mockito.any
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
@@ -48,8 +49,9 @@
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito.`when`
-import org.mockito.Mockito.any
import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@SmallTest
@@ -76,6 +78,7 @@
@Mock private lateinit var packageManager: PackageManager
@Mock private lateinit var applicationInfo: ApplicationInfo
@Mock private lateinit var serviceInfo: ServiceInfo
+ @Mock private lateinit var customTileStatePersister: CustomTileStatePersister
private lateinit var customTile: CustomTile
private lateinit var testableLooper: TestableLooper
@@ -108,10 +111,13 @@
metricsLogger,
statusBarStateController,
activityStarter,
- qsLogger
+ qsLogger,
+ customTileStatePersister
)
customTile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
+ customTile.initialize()
+ testableLooper.processAllMessages()
}
@Test
@@ -123,6 +129,8 @@
`when`(userContext.userId).thenReturn(10)
val tile = CustomTile.create(customTileBuilder, TILE_SPEC, userContext)
+ tile.initialize()
+ testableLooper.processAllMessages()
assertEquals(10, tile.user)
}
@@ -131,6 +139,8 @@
fun testToggleableTileHasBooleanState() {
`when`(tileServiceManager.isToggleableTile).thenReturn(true)
customTile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
+ customTile.initialize()
+ testableLooper.processAllMessages()
assertTrue(customTile.state is QSTile.BooleanState)
assertTrue(customTile.newTileState() is QSTile.BooleanState)
@@ -146,6 +156,9 @@
fun testValueUpdatedInBooleanTile() {
`when`(tileServiceManager.isToggleableTile).thenReturn(true)
customTile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
+ customTile.initialize()
+ testableLooper.processAllMessages()
+
customTile.qsTile.icon = mock(Icon::class.java)
`when`(customTile.qsTile.icon.loadDrawable(any(Context::class.java)))
.thenReturn(mock(Drawable::class.java))
@@ -173,4 +186,88 @@
.thenReturn(null)
customTile.handleUpdateState(customTile.newTileState(), null)
}
+
+ @Test
+ fun testNoLoadStateTileNotActive() {
+ // Not active by default
+ testableLooper.processAllMessages()
+
+ verify(customTileStatePersister, never()).readState(any())
+ }
+
+ @Test
+ fun testNoPersistedStateTileNotActive() {
+ // Not active by default
+ val t = Tile().apply {
+ state = Tile.STATE_INACTIVE
+ }
+ customTile.updateTileState(t)
+ testableLooper.processAllMessages()
+
+ verify(customTileStatePersister, never()).persistState(any(), any())
+ }
+
+ @Test
+ fun testPersistedStateRetrieved() {
+ val state = Tile.STATE_INACTIVE
+ val label = "test_label"
+ val subtitle = "test_subtitle"
+ val contentDescription = "test_content_description"
+ val stateDescription = "test_state_description"
+
+ val t = Tile().apply {
+ this.state = state
+ this.label = label
+ this.subtitle = subtitle
+ this.contentDescription = contentDescription
+ this.stateDescription = stateDescription
+ }
+ `when`(tileServiceManager.isActiveTile).thenReturn(true)
+ `when`(customTileStatePersister
+ .readState(TileServiceKey(componentName, customTile.user))).thenReturn(t)
+ val tile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
+ tile.initialize()
+ testableLooper.processAllMessages()
+
+ // Make sure we have an icon in the tile because we don't have a default icon
+ // This should not be overridden by the retrieved tile that has null icon.
+ tile.qsTile.icon = mock(Icon::class.java)
+ `when`(tile.qsTile.icon.loadDrawable(any(Context::class.java)))
+ .thenReturn(mock(Drawable::class.java))
+
+ tile.refreshState()
+
+ testableLooper.processAllMessages()
+
+ val tileState = tile.state
+
+ assertEquals(state, tileState.state)
+ assertEquals(label, tileState.label)
+ assertEquals(subtitle, tileState.secondaryLabel)
+ assertEquals(contentDescription, tileState.contentDescription)
+ assertEquals(stateDescription, tileState.stateDescription)
+ }
+
+ @Test
+ fun testStoreStateOnChange() {
+ val t = Tile().apply {
+ state = Tile.STATE_INACTIVE
+ label = "test_label"
+ subtitle = "test_subtitle"
+ contentDescription = "test_content_description"
+ stateDescription = "test_state_description"
+ }
+ `when`(tileServiceManager.isActiveTile).thenReturn(true)
+
+ val tile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
+ tile.initialize()
+ testableLooper.processAllMessages()
+
+ tile.updateTileState(t)
+
+ testableLooper.processAllMessages()
+
+ verify(customTileStatePersister)
+ .persistState(TileServiceKey(componentName, customTile.user), t)
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 641f917..2b18404 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -118,7 +118,8 @@
mQSLogger,
mUiEventLogger,
mUserTracker,
- mSecureSettings);
+ mSecureSettings,
+ mock(CustomTileStatePersister.class));
mTileService = new TestTileServices(host, Looper.getMainLooper(), mBroadcastDispatcher,
mUserTracker);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 80231a4..ea4d7cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -121,6 +121,9 @@
mTile = new TileImpl(mHost, mTestableLooper.getLooper(), mainHandler, mFalsingManager,
mMetricsLogger, mStatusBarStateController, mActivityStarter, mQsLogger);
+ mTile.initialize();
+ mTestableLooper.processAllMessages();
+
mTile.setTileSpec(SPEC);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
index 32b1f43..5e2d8fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
@@ -80,6 +80,8 @@
nextAlarmController
)
+ tile.initialize()
+
verify(nextAlarmController).observe(eq(tile), capture(callbackCaptor))
tile.refreshState()
testableLooper.processAllMessages()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
index f17bd56..1bf8351 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
@@ -87,6 +87,9 @@
qsLogger,
batteryController,
secureSettings)
+
+ tile.initialize()
+ testableLooper.processAllMessages()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
index 7c1a5f5..d44a526 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -112,11 +112,14 @@
mNetworkController,
mHotspotController
);
+ mCastTile.initialize();
// We are not setting the mocks to listening, so we trigger a first refresh state to
// set the initial state
mCastTile.refreshState();
+ mTestableLooper.processAllMessages();
+
mCastTile.handleSetListening(true);
ArgumentCaptor<NetworkController.SignalCallback> signalCallbackArgumentCaptor =
ArgumentCaptor.forClass(NetworkController.SignalCallback.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index 6d1bbd9..94af10a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -378,7 +378,10 @@
qsLogger,
controlsComponent,
keyguardStateController
- )
+ ).also {
+ it.initialize()
+ testableLooper.processAllMessages()
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
index 99d028c..cfd3735 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
@@ -92,6 +92,9 @@
mQSLogger,
mBroadcastDispatcher
);
+
+ mNfcTile.initialize();
+ mTestableLooper.processAllMessages();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index e4a9aac..a50cbe5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -155,6 +155,9 @@
mPackageManager,
mSecureSettings,
mController);
+
+ mTile.initialize();
+ mTestableLooper.processAllMessages();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
index df4908d..9eb688d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
@@ -89,6 +89,9 @@
mActivityStarter,
mQSLogger
);
+
+ mTile.initialize();
+ mTestableLooper.processAllMessages();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index 3b4e863..964ce01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -91,6 +91,9 @@
mController,
mKeyguardDismissUtil
);
+
+ mTile.initialize();
+ mTestableLooper.processAllMessages();
}
// Test that the tile is inactive and labeled correctly when the controller is neither starting
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 43f7284..04d7b72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.stack;
import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED;
+import static android.view.View.GONE;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
@@ -316,6 +317,7 @@
public void testUpdateFooter_oneClearableNotification() {
setBarStateForTest(StatusBarState.SHADE);
+ when(mEmptyShadeView.getVisibility()).thenReturn(GONE);
when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
.thenReturn(true);
when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
@@ -337,6 +339,7 @@
when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
.thenReturn(false);
+ when(mEmptyShadeView.getVisibility()).thenReturn(GONE);
FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index 9ac600a..5bf1bb3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -63,6 +63,7 @@
@Mock private BatteryController mBatteryController;
@Mock private FeatureFlags mFeatureFlags;
@Mock private DumpManager mDumpManager;
+ @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@Before
public void setup() {
@@ -75,7 +76,8 @@
mBatteryController,
mTunerService,
mDumpManager,
- mFeatureFlags
+ mFeatureFlags,
+ mUnlockedScreenOffAnimationController
);
}
@Test
@@ -125,7 +127,8 @@
when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
mDozeParameters.onTuningChanged(Settings.Secure.DOZE_ALWAYS_ON, "1");
when(mFeatureFlags.useNewLockscreenAnimations()).thenReturn(true);
-
+ when(mUnlockedScreenOffAnimationController.shouldPlayUnlockedScreenOffAnimation())
+ .thenReturn(true);
assertTrue(mDozeParameters.shouldControlUnlockedScreenOff());
// Trigger the setter for the current value.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java
index 3238430..9fe47ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java
@@ -45,6 +45,7 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
import org.junit.Test;
@@ -70,6 +71,7 @@
@Mock private SysuiColorExtractor mColorExtractor;
@Mock ColorExtractor.GradientColors mGradientColors;
@Mock private DumpManager mDumpManager;
+ @Mock private KeyguardStateController mKeyguardStateController;
@Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters;
private NotificationShadeWindowControllerImpl mNotificationShadeWindowController;
@@ -83,7 +85,7 @@
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController,
- mColorExtractor, mDumpManager);
+ mColorExtractor, mDumpManager, mKeyguardStateController);
mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
mNotificationShadeWindowController.attach();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 154972e..cbc7c6d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -777,6 +777,12 @@
}
@Test
+ public void testDumpBarTransitions_DoesNotCrash() {
+ StatusBar.dumpBarTransitions(
+ new PrintWriter(new ByteArrayOutputStream()), "var", /* transitions= */ null);
+ }
+
+ @Test
@RunWithLooper(setAsMainLooper = true)
public void testUpdateKeyguardState_DoesNotCrash() {
mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
index 1aebf1c..e136d00 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
@@ -132,4 +132,9 @@
public boolean canPerformSmartSpaceTransition() {
return false;
}
+
+ @Override
+ public boolean isKeyguardScreenRotationAllowed() {
+ return false;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
index e6c740b..3018089 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
@@ -67,7 +67,6 @@
@SmallTest
public class WalletScreenControllerTest extends SysuiTestCase {
- private static final int MAX_CARDS = 10;
private static final int CARD_CAROUSEL_WIDTH = 10;
private static final String CARD_ID_1 = "card_id_1";
private static final String CARD_ID_2 = "card_id_2";
@@ -158,7 +157,7 @@
when(mKeyguardStateController.isUnlocked()).thenReturn(false);
GetWalletCardsResponse response =
new GetWalletCardsResponse(
- Collections.singletonList(createWalletCard(mContext)), 0);
+ Collections.singletonList(createLockedWalletCard(mContext)), 0);
mController.queryWalletCards();
mTestableLooper.processAllMessages();
@@ -406,6 +405,15 @@
.build();
}
+ private WalletCard createLockedWalletCard(Context context) {
+ PendingIntent pendingIntent =
+ PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
+ return new WalletCard.Builder(CARD_ID_2, createIcon(), "•••• 5679", pendingIntent)
+ .setCardIcon(createIcon())
+ .setCardLabel("Locked\nUnlock to pay")
+ .build();
+ }
+
private WalletCard createWalletCard(Context context) {
PendingIntent pendingIntent =
PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 6e2e4cb..9fa35f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -23,6 +23,8 @@
import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
@@ -37,6 +39,7 @@
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -98,6 +101,7 @@
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -227,6 +231,8 @@
private TaskStackListenerImpl mTaskStackListener;
@Mock
private ShellTaskOrganizer mShellTaskOrganizer;
+ @Mock
+ private KeyguardStateController mKeyguardStateController;
private TestableBubblePositioner mPositioner;
@@ -249,7 +255,7 @@
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController,
- mColorExtractor, mDumpManager);
+ mColorExtractor, mDumpManager, mKeyguardStateController);
mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
mNotificationShadeWindowController.attach();
@@ -287,6 +293,7 @@
// TODO: Fix
mPositioner = new TestableBubblePositioner(mContext, mWindowManager);
+ mPositioner.setMaxBubbles(5);
mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner, syncExecutor);
TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
@@ -320,6 +327,7 @@
syncExecutor,
mock(Handler.class));
mBubbleController.setExpandListener(mBubbleExpandListener);
+ spyOn(mBubbleController);
mBubblesManager = new BubblesManager(
mContext,
@@ -466,7 +474,7 @@
@Test
public void testExpandCollapseStack() {
- assertFalse(mBubbleController.isStackExpanded());
+ assertStackCollapsed();
// Mark it as a bubble and add it explicitly
mEntryListener.onPendingEntryAdded(mRow);
@@ -474,25 +482,23 @@
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Expand the stack
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
assertTrue(mSysUiStateBubblesExpanded);
// Make sure the notif is suppressed
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Collapse
mBubbleController.collapseStack();
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getKey());
- assertFalse(mBubbleController.isStackExpanded());
+ assertStackCollapsed();
assertFalse(mSysUiStateBubblesExpanded);
}
@@ -508,15 +514,13 @@
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry2.getKey(), mBubbleEntry2.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry2);
// Expand
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
true, mRow2.getKey());
@@ -524,8 +528,7 @@
// Last added is the one that is expanded
assertEquals(mRow2.getKey(), mBubbleData.getSelectedBubble().getKey());
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry2.getKey(), mBubbleEntry2.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry2);
// Switch which bubble is expanded
mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(
@@ -533,8 +536,7 @@
mBubbleData.setExpanded(true);
assertEquals(mRow.getKey(), mBubbleData.getBubbleInStackWithKey(
stackView.getExpandedBubble().getKey()).getKey());
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// collapse for previous bubble
verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
@@ -545,7 +547,7 @@
// Collapse
mBubbleController.collapseStack();
- assertFalse(mBubbleController.isStackExpanded());
+ assertStackCollapsed();
assertFalse(mSysUiStateBubblesExpanded);
}
@@ -558,22 +560,20 @@
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
// Expand
mBubbleData.setExpanded(true);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
assertTrue(mSysUiStateBubblesExpanded);
// Notif is suppressed after expansion
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
}
@@ -586,22 +586,20 @@
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
// Expand
mBubbleData.setExpanded(true);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
assertTrue(mSysUiStateBubblesExpanded);
// Notif is suppressed after expansion
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -610,8 +608,7 @@
// Nothing should have changed
// Notif is suppressed after expansion
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
}
@@ -630,14 +627,13 @@
assertTrue(mSysUiStateBubblesExpanded);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getKey());
// Last added is the one that is expanded
assertEquals(mRow2.getKey(), mBubbleData.getBubbleInStackWithKey(
stackView.getExpandedBubble().getKey()).getKey());
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry2.getKey(), mBubbleEntry2.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry2);
// Dismiss currently expanded
mBubbleController.removeBubble(
@@ -675,7 +671,7 @@
mBubbleData.setExpanded(true);
assertTrue(mSysUiStateBubblesExpanded);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
// Block the bubble so it won't be in the overflow
@@ -694,7 +690,7 @@
@Test
public void testAutoExpand_fails_noFlag() {
- assertFalse(mBubbleController.isStackExpanded());
+ assertStackCollapsed();
setMetadataFlags(mRow,
Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, false /* enableFlag */);
@@ -705,7 +701,7 @@
// Expansion shouldn't change
verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
mRow.getKey());
- assertFalse(mBubbleController.isStackExpanded());
+ assertStackCollapsed();
assertFalse(mSysUiStateBubblesExpanded);
}
@@ -722,7 +718,7 @@
// Expansion should change
verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
mRow.getKey());
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
assertTrue(mSysUiStateBubblesExpanded);
}
@@ -737,8 +733,7 @@
mBubbleController.updateBubble(mBubbleEntry);
// Notif should be suppressed because we were foreground
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Dot + flyout is hidden because notif is suppressed
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showFlyout());
@@ -751,8 +746,7 @@
mBubbleController.updateBubble(mBubbleEntry);
// Should not be suppressed
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Should show dot
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -762,8 +756,7 @@
mBubbleController.updateBubble(mBubbleEntry);
// Notif should be suppressed
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Dot + flyout is hidden because notif is suppressed
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showFlyout());
@@ -788,8 +781,7 @@
@Test
public void testMarkNewNotificationAsShowInShade() {
mEntryListener.onPendingEntryAdded(mRow);
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -874,8 +866,7 @@
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
mRow.getKey(), mRow, REASON_CANCEL_ALL);
@@ -883,8 +874,7 @@
// Intercept!
assertTrue(intercepted);
// Should update show in shade state
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
}
@Test
@@ -893,8 +883,7 @@
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
mRow.getKey(), mRow, REASON_CANCEL);
@@ -902,8 +891,7 @@
// Intercept!
assertTrue(intercepted);
// Should update show in shade state
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
}
@Test
@@ -912,8 +900,7 @@
mEntryListener.onPendingEntryAdded(mRow);
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Dismiss the bubble into overflow.
mBubbleController.removeBubble(
@@ -934,8 +921,7 @@
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mBubbleController.removeBubble(
mRow.getKey(), Bubbles.DISMISS_NO_LONGER_BUBBLE);
@@ -981,48 +967,36 @@
@Test
public void testNotifyShadeSuppressionChange_notificationDismiss() {
- Bubbles.SuppressionChangedListener listener =
- mock(Bubbles.SuppressionChangedListener.class);
- mBubbleData.setSuppressionChangedListener(listener);
-
mEntryListener.onPendingEntryAdded(mRow);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mRemoveInterceptor.onNotificationRemoveRequested(
mRow.getKey(), mRow, REASON_CANCEL);
// Should update show in shade state
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Should notify delegate that shade state changed
- verify(listener).onBubbleNotificationSuppressionChange(
+ verify(mBubbleController).onBubbleNotificationSuppressionChanged(
mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
}
@Test
public void testNotifyShadeSuppressionChange_bubbleExpanded() {
- Bubbles.SuppressionChangedListener listener =
- mock(Bubbles.SuppressionChangedListener.class);
- mBubbleData.setSuppressionChangedListener(listener);
-
mEntryListener.onPendingEntryAdded(mRow);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mBubbleData.setExpanded(true);
// Once a bubble is expanded the notif is suppressed
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Should notify delegate that shade state changed
- verify(listener).onBubbleNotificationSuppressionChange(
+ verify(mBubbleController).onBubbleNotificationSuppressionChanged(
mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
}
@@ -1042,7 +1016,11 @@
// THEN the summary and bubbled child are suppressed from the shade
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- groupedBubble.getEntry().getKey(), groupSummary.getEntry().getSbn().getGroupKey()));
+ groupedBubble.getEntry().getKey(),
+ groupSummary.getEntry().getSbn().getGroupKey()));
+ assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ groupedBubble.getEntry().getKey(),
+ groupSummary.getEntry().getSbn().getGroupKey()));
assertTrue(mBubbleData.isSummarySuppressed(groupSummary.getEntry().getSbn().getGroupKey()));
}
@@ -1098,6 +1076,9 @@
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(),
groupedBubble.getEntry().getSbn().getGroupKey()));
+ assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ groupedBubble.getEntry().getKey(),
+ groupedBubble.getEntry().getSbn().getGroupKey()));
// THEN the summary is removed from GroupManager
verify(mNotificationGroupManager, times(1)).onEntryRemoved(groupSummary.getEntry());
@@ -1253,4 +1234,42 @@
Icon.createWithResource(mContext, R.drawable.bubble_ic_create_bubble))
.build();
}
+
+ /**
+ * Asserts that the bubble stack is expanded and also validates the cached state is updated.
+ */
+ private void assertStackExpanded() {
+ assertTrue(mBubbleController.isStackExpanded());
+ assertTrue(mBubbleController.getImplCachedState().isStackExpanded());
+ }
+
+ /**
+ * Asserts that the bubble stack is collapsed and also validates the cached state is updated.
+ */
+ private void assertStackCollapsed() {
+ assertFalse(mBubbleController.isStackExpanded());
+ assertFalse(mBubbleController.getImplCachedState().isStackExpanded());
+ }
+
+ /**
+ * Asserts that a bubble notification is suppressed from the shade and also validates the cached
+ * state is updated.
+ */
+ private void assertBubbleNotificationSuppressedFromShade(BubbleEntry entry) {
+ assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+ entry.getKey(), entry.getGroupKey()));
+ assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ entry.getKey(), entry.getGroupKey()));
+ }
+
+ /**
+ * Asserts that a bubble notification is not suppressed from the shade and also validates the
+ * cached state is updated.
+ */
+ private void assertBubbleNotificationNotSuppressedFromShade(BubbleEntry entry) {
+ assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+ entry.getKey(), entry.getGroupKey()));
+ assertFalse(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ entry.getKey(), entry.getGroupKey()));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
index 9339f81..55cc8bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
@@ -19,6 +19,8 @@
import static android.app.Notification.FLAG_BUBBLE;
import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
@@ -82,6 +84,7 @@
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper;
@@ -192,6 +195,8 @@
private TaskStackListenerImpl mTaskStackListener;
@Mock
private ShellTaskOrganizer mShellTaskOrganizer;
+ @Mock
+ private KeyguardStateController mKeyguardStateController;
private TestableBubblePositioner mPositioner;
@@ -213,7 +218,7 @@
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController,
- mColorExtractor, mDumpManager);
+ mColorExtractor, mDumpManager, mKeyguardStateController);
mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
mNotificationShadeWindowController.attach();
@@ -232,6 +237,7 @@
when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
mPositioner = new TestableBubblePositioner(mContext, mWindowManager);
+ mPositioner.setMaxBubbles(5);
mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner, syncExecutor);
TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
@@ -264,6 +270,7 @@
syncExecutor,
mock(Handler.class));
mBubbleController.setExpandListener(mBubbleExpandListener);
+ spyOn(mBubbleController);
mBubblesManager = new BubblesManager(
mContext,
@@ -324,8 +331,7 @@
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Make it look like dismissed notif
mBubbleData.getBubbleInStackWithKey(mRow.getKey()).setSuppressNotification(true);
@@ -348,8 +354,7 @@
.thenReturn(mRow);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Make it look like dismissed notif
mBubbleData.getBubbleInStackWithKey(mRow.getKey()).setSuppressNotification(true);
@@ -384,7 +389,7 @@
@Test
public void testExpandCollapseStack() {
- assertFalse(mBubbleController.isStackExpanded());
+ assertStackCollapsed();
// Mark it as a bubble and add it explicitly
mEntryListener.onEntryAdded(mRow);
@@ -392,23 +397,20 @@
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Expand the stack
- BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
// Make sure the notif is suppressed
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Collapse
mBubbleController.collapseStack();
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getKey());
- assertFalse(mBubbleController.isStackExpanded());
+ assertStackCollapsed();
}
@Test
@@ -422,22 +424,19 @@
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry2);
// Expand
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
true, mRow2.getKey());
// Last added is the one that is expanded
assertEquals(mRow2.getKey(), mBubbleData.getSelectedBubble().getKey());
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry2.getKey(), mBubbleEntry2.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry2);
// Switch which bubble is expanded
mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(
@@ -445,8 +444,7 @@
mBubbleData.setExpanded(true);
assertEquals(mRow.getKey(), mBubbleData.getBubbleInStackWithKey(
stackView.getExpandedBubble().getKey()).getKey());
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// collapse for previous bubble
verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
@@ -458,7 +456,7 @@
// Collapse
mBubbleController.collapseStack();
- assertFalse(mBubbleController.isStackExpanded());
+ assertStackCollapsed();
}
@Test
@@ -469,20 +467,18 @@
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
// Expand
mBubbleData.setExpanded(true);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
// Notif is suppressed after expansion
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
}
@@ -495,20 +491,18 @@
// We should have bubbles & their notifs should not be suppressed
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
// Expand
mBubbleData.setExpanded(true);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
// Notif is suppressed after expansion
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -517,8 +511,7 @@
// Nothing should have changed
// Notif is suppressed after expansion
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Notif shouldn't show dot after expansion
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
}
@@ -535,14 +528,13 @@
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getKey());
// Last added is the one that is expanded
assertEquals(mRow2.getKey(), mBubbleData.getBubbleInStackWithKey(
stackView.getExpandedBubble().getKey()).getKey());
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry2.getKey(), mBubbleEntry2.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry2);
// Dismiss currently expanded
mBubbleController.removeBubble(
@@ -578,7 +570,7 @@
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
// Block the bubble so it won't be in the overflow
@@ -597,7 +589,7 @@
@Test
public void testAutoExpand_fails_noFlag() {
- assertFalse(mBubbleController.isStackExpanded());
+ assertStackCollapsed();
setMetadataFlags(mRow,
Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE, false /* enableFlag */);
@@ -608,7 +600,7 @@
// Expansion shouldn't change
verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
mRow.getKey());
- assertFalse(mBubbleController.isStackExpanded());
+ assertStackCollapsed();
}
@Test
@@ -623,7 +615,7 @@
// Expansion should change
verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
mRow.getKey());
- assertTrue(mBubbleController.isStackExpanded());
+ assertStackExpanded();
}
@Test
@@ -636,8 +628,7 @@
mBubbleController.updateBubble(mBubbleEntry);
// Notif should be suppressed because we were foreground
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Dot + flyout is hidden because notif is suppressed
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showFlyout());
@@ -648,8 +639,7 @@
mBubbleController.updateBubble(mBubbleEntry);
// Should not be suppressed
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Should show dot
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -659,8 +649,7 @@
mBubbleController.updateBubble(mBubbleEntry);
// Notif should be suppressed
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Dot + flyout is hidden because notif is suppressed
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showFlyout());
@@ -669,8 +658,7 @@
@Test
public void testMarkNewNotificationAsShowInShade() {
mEntryListener.onEntryAdded(mRow);
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mTestableLooper.processAllMessages();
assertTrue(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
@@ -741,16 +729,14 @@
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
boolean intercepted = mBubblesManager.handleDismissalInterception(mRow);
// Intercept!
assertTrue(intercepted);
// Should update show in shade state
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
}
@Test
@@ -759,8 +745,7 @@
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Dismiss the bubble
mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
@@ -779,8 +764,7 @@
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
// Dismiss the bubble
mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_NOTIF_CANCEL);
@@ -795,47 +779,35 @@
@Test
public void testNotifyShadeSuppressionChange_notificationDismiss() {
- Bubbles.SuppressionChangedListener listener =
- mock(Bubbles.SuppressionChangedListener.class);
- mBubbleData.setSuppressionChangedListener(listener);
-
mEntryListener.onEntryAdded(mRow);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mBubblesManager.handleDismissalInterception(mRow);
// Should update show in shade state
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Should notify delegate that shade state changed
- verify(listener).onBubbleNotificationSuppressionChange(
+ verify(mBubbleController).onBubbleNotificationSuppressionChanged(
mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
}
@Test
public void testNotifyShadeSuppressionChange_bubbleExpanded() {
- Bubbles.SuppressionChangedListener listener =
- mock(Bubbles.SuppressionChangedListener.class);
- mBubbleData.setSuppressionChangedListener(listener);
-
mEntryListener.onEntryAdded(mRow);
assertTrue(mBubbleController.hasBubbles());
- assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
mBubbleData.setExpanded(true);
// Once a bubble is expanded the notif is suppressed
- assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
- mBubbleEntry.getKey(), mBubbleEntry.getGroupKey()));
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
// Should notify delegate that shade state changed
- verify(listener).onBubbleNotificationSuppressionChange(
+ verify(mBubbleController).onBubbleNotificationSuppressionChanged(
mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
}
@@ -857,6 +829,9 @@
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(),
groupedBubble.getEntry().getSbn().getGroupKey()));
+ assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ groupedBubble.getEntry().getKey(),
+ groupedBubble.getEntry().getSbn().getGroupKey()));
assertTrue(mBubbleData.isSummarySuppressed(groupSummary.getEntry().getSbn().getGroupKey()));
}
@@ -911,11 +886,17 @@
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
groupedBubble.getEntry().getKey(),
groupedBubble.getEntry().getSbn().getGroupKey()));
+ assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ groupedBubble.getEntry().getKey(),
+ groupedBubble.getEntry().getSbn().getGroupKey()));
// THEN the summary is also suppressed from the shade
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
groupSummary.getEntry().getKey(),
groupSummary.getEntry().getSbn().getGroupKey()));
+ assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ groupSummary.getEntry().getKey(),
+ groupSummary.getEntry().getSbn().getGroupKey()));
}
/**
@@ -934,4 +915,42 @@
}
bubbleMetadata.setFlags(flags);
}
+
+ /**
+ * Asserts that the bubble stack is expanded and also validates the cached state is updated.
+ */
+ private void assertStackExpanded() {
+ assertTrue(mBubbleController.isStackExpanded());
+ assertTrue(mBubbleController.getImplCachedState().isStackExpanded());
+ }
+
+ /**
+ * Asserts that the bubble stack is collapsed and also validates the cached state is updated.
+ */
+ private void assertStackCollapsed() {
+ assertFalse(mBubbleController.isStackExpanded());
+ assertFalse(mBubbleController.getImplCachedState().isStackExpanded());
+ }
+
+ /**
+ * Asserts that a bubble notification is suppressed from the shade and also validates the cached
+ * state is updated.
+ */
+ private void assertBubbleNotificationSuppressedFromShade(BubbleEntry entry) {
+ assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+ entry.getKey(), entry.getGroupKey()));
+ assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ entry.getKey(), entry.getGroupKey()));
+ }
+
+ /**
+ * Asserts that a bubble notification is not suppressed from the shade and also validates the
+ * cached state is updated.
+ */
+ private void assertBubbleNotificationNotSuppressedFromShade(BubbleEntry entry) {
+ assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+ entry.getKey(), entry.getGroupKey()));
+ assertFalse(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ entry.getKey(), entry.getGroupKey()));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubblePositioner.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubblePositioner.java
index 24a7cd5..6edc373 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubblePositioner.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubblePositioner.java
@@ -22,9 +22,11 @@
import android.graphics.Rect;
import android.view.WindowManager;
+import com.android.wm.shell.R;
import com.android.wm.shell.bubbles.BubblePositioner;
public class TestableBubblePositioner extends BubblePositioner {
+ private int mMaxBubbles;
public TestableBubblePositioner(Context context,
WindowManager windowManager) {
@@ -33,5 +35,15 @@
updateInternal(Configuration.ORIENTATION_PORTRAIT,
Insets.of(0, 0, 0, 0),
new Rect(0, 0, 500, 1000));
+ mMaxBubbles = context.getResources().getInteger(R.integer.bubbles_max_rendered);
+ }
+
+ public void setMaxBubbles(int max) {
+ mMaxBubbles = max;
+ }
+
+ @Override
+ public int getMaxBubbles() {
+ return mMaxBubbles;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index 1dd0b21..ff15d01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -37,6 +37,7 @@
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.onehanded.OneHanded;
+import com.android.wm.shell.onehanded.OneHandedEventCallback;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.pip.Pip;
@@ -106,6 +107,7 @@
verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class));
verify(mScreenLifecycle).addObserver(any(ScreenLifecycle.Observer.class));
verify(mOneHanded).registerTransitionCallback(any(OneHandedTransitionCallback.class));
+ verify(mOneHanded).registerEventCallback(any(OneHandedEventCallback.class));
}
@Test
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 7eecc45..241a0db 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2892,7 +2892,8 @@
// In case user assigned magnification to the given shortcut.
if (targetName.equals(MAGNIFICATION_CONTROLLER_NAME)) {
final boolean enabled = !getFullScreenMagnificationController().isMagnifying(displayId);
- logAccessibilityShortcutActivated(MAGNIFICATION_COMPONENT_NAME, shortcutType, enabled);
+ logAccessibilityShortcutActivated(mContext, MAGNIFICATION_COMPONENT_NAME, shortcutType,
+ enabled);
sendAccessibilityButtonToInputFilter(displayId);
return;
}
@@ -2907,7 +2908,7 @@
}
// In case user assigned an accessibility shortcut target to the given shortcut.
if (performAccessibilityShortcutTargetActivity(displayId, targetComponentName)) {
- logAccessibilityShortcutActivated(targetComponentName, shortcutType);
+ logAccessibilityShortcutActivated(mContext, targetComponentName, shortcutType);
return;
}
// in case user assigned an accessibility service to the given shortcut.
@@ -2930,12 +2931,12 @@
featureInfo.getSettingKey(), mCurrentUserId);
// Assuming that the default state will be to have the feature off
if (!TextUtils.equals(featureInfo.getSettingOnValue(), setting.read())) {
- logAccessibilityShortcutActivated(assignedTarget, shortcutType, /* serviceEnabled= */
- true);
+ logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType,
+ /* serviceEnabled= */ true);
setting.write(featureInfo.getSettingOnValue());
} else {
- logAccessibilityShortcutActivated(assignedTarget, shortcutType, /* serviceEnabled= */
- false);
+ logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType,
+ /* serviceEnabled= */ false);
setting.write(featureInfo.getSettingOffValue());
}
return true;
@@ -2997,13 +2998,13 @@
if ((targetSdk <= Build.VERSION_CODES.Q && shortcutType == ACCESSIBILITY_SHORTCUT_KEY)
|| (targetSdk > Build.VERSION_CODES.Q && !requestA11yButton)) {
if (serviceConnection == null) {
- logAccessibilityShortcutActivated(assignedTarget,
- shortcutType, /* serviceEnabled= */ true);
+ logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType,
+ /* serviceEnabled= */ true);
enableAccessibilityServiceLocked(assignedTarget, mCurrentUserId);
} else {
- logAccessibilityShortcutActivated(assignedTarget,
- shortcutType, /* serviceEnabled= */ false);
+ logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType,
+ /* serviceEnabled= */ false);
disableAccessibilityServiceLocked(assignedTarget, mCurrentUserId);
}
return true;
@@ -3024,8 +3025,8 @@
return false;
}
// ServiceConnection means service enabled.
- logAccessibilityShortcutActivated(assignedTarget, shortcutType, /* serviceEnabled= */
- true);
+ logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType,
+ /* serviceEnabled= */ true);
serviceConnection.notifyAccessibilityButtonClickedLocked(displayId);
return true;
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 320047f..078d908 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2648,6 +2648,10 @@
Slog.d(TAG, "Starting partition or augmented request for view id " + id + ": "
+ viewState.getStateAsString());
}
+ // Fix to always let standard autofill start.
+ // Sometimes activity contain IMPORTANT_FOR_AUTOFILL_NO fields which marks session as
+ // augmentedOnly, but other fields are still fillable by standard autofill.
+ mSessionFlags.mAugmentedAutofillOnly = false;
requestNewFillResponseLocked(viewState, ViewState.STATE_STARTED_PARTITION, flags);
return true;
}
@@ -2847,12 +2851,18 @@
if (sDebug) Slog.d(TAG, "trigger augmented autofill.");
triggerAugmentedAutofillLocked(flags);
} else {
- if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
+ if (sDebug) {
+ Slog.d(TAG, "skip augmented autofill for same view: "
+ + "same view entered");
+ }
}
return;
} else if (mSessionFlags.mAugmentedAutofillOnly && isSameViewEntered) {
// Regular autofill is disabled.
- if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
+ if (sDebug) {
+ Slog.d(TAG, "skip augmented autofill for same view: "
+ + "standard autofill disabled.");
+ }
return;
}
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 83dfe8e..05131d4 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -454,19 +454,13 @@
}).cancelTimeout();
}, FgThread.getExecutor()).whenComplete(uncheckExceptions((association, err) -> {
-
- final long callingIdentity = Binder.clearCallingIdentity();
- try {
- if (err == null) {
- addAssociation(association);
- } else {
- Slog.e(LOG_TAG, "Failed to discover device(s)", err);
- callback.onFailure("No devices found: " + err.getMessage());
- }
- cleanup();
- } finally {
- Binder.restoreCallingIdentity(callingIdentity);
+ if (err == null) {
+ addAssociation(association);
+ } else {
+ Slog.e(LOG_TAG, "Failed to discover device(s)", err);
+ callback.onFailure("No devices found: " + err.getMessage());
}
+ cleanup();
}));
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index a231de3..2a634eb 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -375,6 +375,9 @@
// Cancel account request notification if a permission was preventing the account access
mPackageManager.addOnPermissionsChangeListener(
(int uid) -> {
+ // Permission changes cause requires updating accounts cache.
+ AccountManager.invalidateLocalAccountsDataCaches();
+
Account[] accounts = null;
String[] packageNames = mPackageManager.getPackagesForUid(uid);
if (packageNames != null) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 0802123..5e388d9 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1877,7 +1877,6 @@
active.mNumActive++;
}
r.isForeground = true;
- r.mLogEntering = true;
// The logging of FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER event could
// be deferred, make a copy of mAllowStartForeground and
// mAllowWhileInUsePermissionInFgs.
@@ -1903,6 +1902,9 @@
AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
registerAppOpCallbackLocked(r);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, true);
+ logFGSStateChangeLocked(r,
+ FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER,
+ 0);
}
// Even if the service is already a FGS, we need to update the notification,
// so we need to call it again.
@@ -1958,6 +1960,7 @@
FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT,
r.mFgsExitTime > r.mFgsEnterTime
? (int)(r.mFgsExitTime - r.mFgsEnterTime) : 0);
+ r.mFgsNotificationWasDeferred = false;
resetFgsRestrictionLocked(r);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
if (r.app != null) {
@@ -2162,6 +2165,7 @@
}
r.fgDisplayTime = when;
r.mFgsNotificationDeferred = true;
+ r.mFgsNotificationWasDeferred = true;
r.mFgsNotificationShown = false;
mPendingFgsNotifications.add(r);
if (DEBUG_FOREGROUND_SERVICE) {
@@ -2205,11 +2209,6 @@
Slog.d(TAG_SERVICE, " - service no longer running/fg, ignoring");
}
}
- // Regardless of whether we needed to post the notification or the
- // service is no longer running, we may not have logged its FGS
- // transition yet depending on the timing and API sequence that led
- // to this point - so make sure to do so.
- maybeLogFGSStateEnteredLocked(r);
}
}
if (DEBUG_FOREGROUND_SERVICE) {
@@ -2252,16 +2251,6 @@
}
}
- private void maybeLogFGSStateEnteredLocked(ServiceRecord r) {
- if (r.mLogEntering) {
- logFGSStateChangeLocked(r,
- FrameworkStatsLog
- .FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER,
- 0);
- r.mLogEntering = false;
- }
- }
-
/**
* Callback from NotificationManagerService whenever it posts a notification
* associated with a foreground service. This is the unified handling point
@@ -2280,9 +2269,7 @@
&& id == sr.foregroundId
&& sr.appInfo.packageName.equals(pkg)) {
// Found it. If 'shown' is false, it means that the notification
- // subsystem will not be displaying it yet, so all we do is log
- // the "fgs entered" transition noting deferral, then we're done.
- maybeLogFGSStateEnteredLocked(sr);
+ // subsystem will not be displaying it yet.
if (shown) {
if (DEBUG_FOREGROUND_SERVICE) {
Slog.d(TAG_SERVICE, "Notification shown; canceling deferral of "
@@ -4240,6 +4227,7 @@
r.isForeground = false;
r.foregroundId = 0;
r.foregroundNoti = null;
+ r.mFgsNotificationWasDeferred = false;
resetFgsRestrictionLocked(r);
// Clear start entries.
@@ -6263,7 +6251,7 @@
? r.mRecentCallerApplicationInfo.targetSdkVersion : 0,
r.mInfoTempFgsAllowListReason != null
? r.mInfoTempFgsAllowListReason.mCallingUid : INVALID_UID,
- r.mFgsNotificationDeferred,
+ r.mFgsNotificationWasDeferred,
r.mFgsNotificationShown,
durationMs,
r.mStartForegroundCount,
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 4e6e91a..08f6f1e 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
@@ -78,6 +79,7 @@
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.BatteryUsageStatsProvider;
+import com.android.internal.os.BatteryUsageStatsStore;
import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.RailStats;
@@ -124,10 +126,12 @@
Watchdog.Monitor {
static final String TAG = "BatteryStatsService";
static final boolean DBG = false;
+ private static final boolean BATTERY_USAGE_STORE_ENABLED = true;
private static IBatteryStats sService;
final BatteryStatsImpl mStats;
+ private final BatteryUsageStatsStore mBatteryUsageStatsStore;
private final BatteryStatsImpl.UserInfoProvider mUserManagerUserInfoProvider;
private final Context mContext;
private final BatteryExternalStatsWorker mWorker;
@@ -348,7 +352,14 @@
mStats.setPowerProfileLocked(new PowerProfile(context));
mStats.startTrackingSystemServerCpuTime();
- mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mStats);
+ if (BATTERY_USAGE_STORE_ENABLED) {
+ mBatteryUsageStatsStore =
+ new BatteryUsageStatsStore(context, mStats, systemDir, mHandler);
+ } else {
+ mBatteryUsageStatsStore = null;
+ }
+ mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mStats,
+ mBatteryUsageStatsStore);
}
public void publish() {
@@ -752,6 +763,10 @@
FrameworkStatsLog.BATTERY_USAGE_STATS_SINCE_RESET_USING_POWER_PROFILE_MODEL,
null, // use default PullAtomMetadata values
BackgroundThread.getExecutor(), pullAtomCallback);
+ statsManager.setPullAtomCallback(
+ FrameworkStatsLog.BATTERY_USAGE_STATS_BEFORE_RESET,
+ null, // use default PullAtomMetadata values
+ BackgroundThread.getExecutor(), pullAtomCallback);
}
/** StatsPullAtomCallback for pulling BatteryUsageStats data. */
@@ -768,6 +783,17 @@
new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build();
bus = getBatteryUsageStats(List.of(powerProfileQuery)).get(0);
break;
+ case FrameworkStatsLog.BATTERY_USAGE_STATS_BEFORE_RESET:
+ final long sessionStart = mBatteryUsageStatsStore
+ .getLastBatteryUsageStatsBeforeResetAtomPullTimestamp();
+ final long sessionEnd = mStats.getStartClockTime();
+ final BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder()
+ .aggregateSnapshots(sessionStart, sessionEnd)
+ .build();
+ bus = getBatteryUsageStats(List.of(query)).get(0);
+ mBatteryUsageStatsStore
+ .setLastBatteryUsageStatsBeforeResetAtomPullTimestamp(sessionEnd);
+ break;
default:
throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
}
@@ -2499,6 +2525,12 @@
* @hide
*/
public CellularBatteryStats getCellularBatteryStats() {
+ if (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.UPDATE_DEVICE_STATS) == PERMISSION_DENIED) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ }
+
// Wait for the completion of pending works if there is any
awaitCompletion();
synchronized (mStats) {
@@ -2511,6 +2543,12 @@
* @hide
*/
public WifiBatteryStats getWifiBatteryStats() {
+ if (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.UPDATE_DEVICE_STATS) == PERMISSION_DENIED) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ }
+
// Wait for the completion of pending works if there is any
awaitCompletion();
synchronized (mStats) {
@@ -2523,6 +2561,8 @@
* @hide
*/
public GpsBatteryStats getGpsBatteryStats() {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BATTERY_STATS, null);
+
// Wait for the completion of pending works if there is any
awaitCompletion();
synchronized (mStats) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 6228637..aef402a 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -328,7 +328,8 @@
final int index = mCache.indexOfKey(app.packageName);
Pair<Boolean, WeakReference<ApplicationInfo>> p;
if (index < 0) {
- p = new Pair<>(mPlatformCompat.isChangeEnabled(mChangeId, app),
+ p = new Pair<>(mPlatformCompat.isChangeEnabledInternalNoLogging(mChangeId,
+ app),
new WeakReference<>(app));
mCache.put(app.packageName, p);
return p.first;
@@ -338,7 +339,8 @@
return p.first;
}
// Cache is invalid, regenerate it
- p = new Pair<>(mPlatformCompat.isChangeEnabled(mChangeId, app),
+ p = new Pair<>(mPlatformCompat.isChangeEnabledInternalNoLogging(mChangeId,
+ app),
new WeakReference<>(app));
mCache.setValueAt(index, p);
return p.first;
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 3ba07af..141f081 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -109,7 +109,6 @@
boolean fgWaiting; // is a timeout for going foreground already scheduled?
boolean isNotAppComponentUsage; // is service binding not considered component/package usage?
boolean isForeground; // is service currently in foreground mode?
- boolean mLogEntering; // need to report fgs transition once deferral policy is known
int foregroundId; // Notification ID of last foreground req.
Notification foregroundNoti; // Notification record of foreground state.
long fgDisplayTime; // time at which the FGS notification should become visible
@@ -167,8 +166,10 @@
long mFgsEnterTime = 0;
// The uptime when the service exits FGS state.
long mFgsExitTime = 0;
- // FGS notification was deferred.
+ // FGS notification is deferred.
boolean mFgsNotificationDeferred;
+ // FGS notification was deferred.
+ boolean mFgsNotificationWasDeferred;
// FGS notification was shown before the FGS finishes, or it wasn't deferred in the first place.
boolean mFgsNotificationShown;
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 104bc9b..99a33e4 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -848,7 +848,7 @@
return mAttributionFlags;
}
- /** @return attributoin chiang id for the access */
+ /** @return attribution chain id for the access */
public int getAttributionChainId() {
return mAttributionChainId;
}
@@ -912,7 +912,8 @@
proxyAttributionTag, uidState, flags);
mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName,
- tag, uidState, flags, accessTime);
+ tag, uidState, flags, accessTime, AppOpsManager.ATTRIBUTION_FLAGS_NONE,
+ AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
}
/**
@@ -1053,9 +1054,9 @@
event.numUnfinishedStarts++;
if (isStarted) {
- // TODO: Consider storing the attribution chain flags and id
mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
- parent.packageName, tag, uidState, flags, startTime);
+ parent.packageName, tag, uidState, flags, startTime, attributionFlags,
+ attributionChainId);
}
}
@@ -1112,7 +1113,8 @@
mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid,
parent.packageName, tag, event.getUidState(),
- event.getFlags(), finishedEvent.getNoteTime(), finishedEvent.getDuration());
+ event.getFlags(), finishedEvent.getNoteTime(), finishedEvent.getDuration(),
+ event.getAttributionFlags(), event.getAttributionChainId());
if (!isPausing) {
mInProgressStartOpEventPool.release(event);
@@ -1215,7 +1217,8 @@
event.mStartElapsedTime = SystemClock.elapsedRealtime();
event.mStartTime = startTime;
mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
- parent.packageName, tag, event.mUidState, event.mFlags, startTime);
+ parent.packageName, tag, event.mUidState, event.mFlags, startTime,
+ event.getAttributionFlags(), event.getAttributionChainId());
if (shouldSendActive) {
scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, parent.packageName,
tag, true, event.getAttributionFlags(), event.getAttributionChainId());
diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java
index 10cfddf..49469cc 100644
--- a/services/core/java/com/android/server/appop/DiscreteRegistry.java
+++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java
@@ -26,6 +26,7 @@
import static android.app.AppOpsManager.OP_FLAGS_ALL;
import static android.app.AppOpsManager.OP_FLAG_SELF;
import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
+import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXY;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA;
import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE;
@@ -156,8 +157,11 @@
private static final String ATTR_NOTE_DURATION = "nd";
private static final String ATTR_UID_STATE = "us";
private static final String ATTR_FLAGS = "f";
+ private static final String ATTR_ATTRIBUTION_FLAGS = "af";
+ private static final String ATTR_CHAIN_ID = "ci";
- private static final int OP_FLAGS_DISCRETE = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED;
+ private static final int OP_FLAGS_DISCRETE = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED
+ | OP_FLAG_TRUSTED_PROXY;
// Lock for read/write access to on disk state
private final Object mOnDiskLock = new Object();
@@ -227,13 +231,14 @@
void recordDiscreteAccess(int uid, String packageName, int op, @Nullable String attributionTag,
@AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, long accessTime,
- long accessDuration) {
+ long accessDuration, @AppOpsManager.AttributionFlags int attributionFlags,
+ int attributionChainId) {
if (!isDiscreteOp(op, flags)) {
return;
}
synchronized (mInMemoryLock) {
mDiscreteOps.addDiscreteAccess(op, uid, packageName, attributionTag, flags, uidState,
- accessTime, accessDuration);
+ accessTime, accessDuration, attributionFlags, attributionChainId);
}
}
@@ -383,9 +388,10 @@
void addDiscreteAccess(int op, int uid, @NonNull String packageName,
@Nullable String attributionTag, @AppOpsManager.OpFlags int flags,
- @AppOpsManager.UidState int uidState, long accessTime, long accessDuration) {
+ @AppOpsManager.UidState int uidState, long accessTime, long accessDuration,
+ @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
getOrCreateDiscreteUidOps(uid).addDiscreteAccess(op, packageName, attributionTag, flags,
- uidState, accessTime, accessDuration);
+ uidState, accessTime, accessDuration, attributionFlags, attributionChainId);
}
private void filter(long beginTimeMillis, long endTimeMillis,
@@ -613,9 +619,10 @@
void addDiscreteAccess(int op, @NonNull String packageName, @Nullable String attributionTag,
@AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState,
- long accessTime, long accessDuration) {
+ long accessTime, long accessDuration,
+ @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
getOrCreateDiscretePackageOps(packageName).addDiscreteAccess(op, attributionTag, flags,
- uidState, accessTime, accessDuration);
+ uidState, accessTime, accessDuration, attributionFlags, attributionChainId);
}
private DiscretePackageOps getOrCreateDiscretePackageOps(String packageName) {
@@ -680,9 +687,10 @@
void addDiscreteAccess(int op, @Nullable String attributionTag,
@AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState,
- long accessTime, long accessDuration) {
+ long accessTime, long accessDuration,
+ @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
getOrCreateDiscreteOp(op).addDiscreteAccess(attributionTag, flags, uidState, accessTime,
- accessDuration);
+ accessDuration, attributionFlags, attributionChainId);
}
void merge(DiscretePackageOps other) {
@@ -823,37 +831,39 @@
for (int j = 0; j < n; j++) {
DiscreteOpEvent event = list.get(j);
list.set(j, new DiscreteOpEvent(event.mNoteTime - offset, event.mNoteDuration,
- event.mUidState, event.mOpFlag));
+ event.mUidState, event.mOpFlag, event.mAttributionFlags,
+ event.mAttributionChainId));
}
}
}
void addDiscreteAccess(@Nullable String attributionTag,
@AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState,
- long accessTime, long accessDuration) {
+ long accessTime, long accessDuration,
+ @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
List<DiscreteOpEvent> attributedOps = getOrCreateDiscreteOpEventsList(
attributionTag);
- accessTime = accessTime / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization;
- accessDuration = accessDuration == -1 ? -1
- : (accessDuration + sDiscreteHistoryQuantization - 1)
- / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization;
int nAttributedOps = attributedOps.size();
int i = nAttributedOps;
for (; i > 0; i--) {
DiscreteOpEvent previousOp = attributedOps.get(i - 1);
- if (previousOp.mNoteTime < accessTime) {
+ if (discretizeTimeStamp(previousOp.mNoteTime) < discretizeTimeStamp(accessTime)) {
break;
}
- if (previousOp.mOpFlag == flags && previousOp.mUidState == uidState) {
- if (accessDuration != previousOp.mNoteDuration) {
+ if (previousOp.mOpFlag == flags && previousOp.mUidState == uidState
+ && previousOp.mAttributionFlags == attributionFlags
+ && previousOp.mAttributionChainId == attributionChainId) {
+ if (discretizeDuration(accessDuration) != discretizeDuration(
+ previousOp.mNoteDuration)) {
break;
} else {
return;
}
}
}
- attributedOps.add(i, new DiscreteOpEvent(accessTime, accessDuration, uidState, flags));
+ attributedOps.add(i, new DiscreteOpEvent(accessTime, accessDuration, uidState, flags,
+ attributionFlags, attributionChainId));
}
private List<DiscreteOpEvent> getOrCreateDiscreteOpEventsList(String attributionTag) {
@@ -875,7 +885,8 @@
for (int j = 0; j < nEvents; j++) {
DiscreteOpEvent event = events.get(j);
result.addDiscreteAccess(op, uid, packageName, tag, event.mUidState,
- event.mOpFlag, event.mNoteTime, event.mNoteDuration);
+ event.mOpFlag, discretizeTimeStamp(event.mNoteTime),
+ discretizeDuration(event.mNoteDuration));
}
}
}
@@ -932,11 +943,15 @@
-1);
int uidState = parser.getAttributeInt(null, ATTR_UID_STATE);
int opFlags = parser.getAttributeInt(null, ATTR_FLAGS);
+ int attributionFlags = parser.getAttributeInt(null,
+ ATTR_ATTRIBUTION_FLAGS, AppOpsManager.ATTRIBUTION_FLAGS_NONE);
+ int attributionChainId = parser.getAttributeInt(null, ATTR_CHAIN_ID,
+ AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
if (noteTime + noteDuration < beginTimeMillis) {
continue;
}
DiscreteOpEvent event = new DiscreteOpEvent(noteTime, noteDuration,
- uidState, opFlags);
+ uidState, opFlags, attributionFlags, attributionChainId);
events.add(event);
}
}
@@ -952,13 +967,18 @@
final long mNoteDuration;
final @AppOpsManager.UidState int mUidState;
final @AppOpsManager.OpFlags int mOpFlag;
+ final @AppOpsManager.AttributionFlags int mAttributionFlags;
+ final int mAttributionChainId;
DiscreteOpEvent(long noteTime, long noteDuration, @AppOpsManager.UidState int uidState,
- @AppOpsManager.OpFlags int opFlag) {
+ @AppOpsManager.OpFlags int opFlag,
+ @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
mNoteTime = noteTime;
mNoteDuration = noteDuration;
mUidState = uidState;
mOpFlag = opFlag;
+ mAttributionFlags = attributionFlags;
+ mAttributionChainId = attributionChainId;
}
private void dump(@NonNull PrintWriter pw, @NonNull SimpleDateFormat sdf,
@@ -969,13 +989,19 @@
pw.print("-");
pw.print(flagsToString(mOpFlag));
pw.print("] at ");
- date.setTime(mNoteTime);
+ date.setTime(discretizeTimeStamp(mNoteTime));
pw.print(sdf.format(date));
if (mNoteDuration != -1) {
pw.print(" for ");
- pw.print(mNoteDuration);
+ pw.print(discretizeDuration(mNoteDuration));
pw.print(" milliseconds ");
}
+ if (mAttributionFlags != AppOpsManager.ATTRIBUTION_FLAGS_NONE) {
+ pw.print(" attribution flags=");
+ pw.print(mAttributionFlags);
+ pw.print(" with chainId=");
+ pw.print(mAttributionChainId);
+ }
pw.println();
}
@@ -984,6 +1010,12 @@
if (mNoteDuration != -1) {
out.attributeLong(null, ATTR_NOTE_DURATION, mNoteDuration);
}
+ if (mAttributionFlags != AppOpsManager.ATTRIBUTION_FLAGS_NONE) {
+ out.attributeInt(null, ATTR_ATTRIBUTION_FLAGS, mAttributionFlags);
+ }
+ if (mAttributionChainId != AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE) {
+ out.attributeInt(null, ATTR_CHAIN_ID, mAttributionChainId);
+ }
out.attributeInt(null, ATTR_UID_STATE, mUidState);
out.attributeInt(null, ATTR_FLAGS, mOpFlag);
}
@@ -1055,6 +1087,16 @@
return true;
}
+ private static long discretizeTimeStamp(long timeStamp) {
+ return timeStamp / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization;
+
+ }
+
+ private static long discretizeDuration(long duration) {
+ return duration == -1 ? -1 : (duration + sDiscreteHistoryQuantization - 1)
+ / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization;
+ }
+
void setDebugMode(boolean debugMode) {
this.mDebugMode = debugMode;
}
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 8b72be7..dd5df50 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -487,7 +487,8 @@
void incrementOpAccessedCount(int op, int uid, @NonNull String packageName,
@Nullable String attributionTag, @UidState int uidState, @OpFlags int flags,
- long accessTime) {
+ long accessTime, @AppOpsManager.AttributionFlags int attributionFlags,
+ int attributionChainId) {
synchronized (mInMemoryLock) {
if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
if (!isPersistenceInitializedMLocked()) {
@@ -499,7 +500,7 @@
attributionTag, uidState, flags, 1);
mDiscreteRegistry.recordDiscreteAccess(uid, packageName, op, attributionTag,
- flags, uidState, accessTime, -1);
+ flags, uidState, accessTime, -1, attributionFlags, attributionChainId);
}
}
}
@@ -521,7 +522,8 @@
void increaseOpAccessDuration(int op, int uid, @NonNull String packageName,
@Nullable String attributionTag, @UidState int uidState, @OpFlags int flags,
- long eventStartTime, long increment) {
+ long eventStartTime, long increment,
+ @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
synchronized (mInMemoryLock) {
if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
if (!isPersistenceInitializedMLocked()) {
@@ -532,7 +534,8 @@
System.currentTimeMillis()).increaseAccessDuration(op, uid, packageName,
attributionTag, uidState, flags, increment);
mDiscreteRegistry.recordDiscreteAccess(uid, packageName, op, attributionTag,
- flags, uidState, eventStartTime, increment);
+ flags, uidState, eventStartTime, increment, attributionFlags,
+ attributionChainId);
}
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
index 0ba731e..cb966e7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
@@ -59,11 +59,13 @@
@Override
protected void stopHalOperation() {
- try {
- mCancellationSignal.cancel();
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote exception", e);
- mCallback.onClientFinished(this, false /* success */);
+ if (mCancellationSignal != null) {
+ try {
+ mCancellationSignal.cancel();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ mCallback.onClientFinished(this, false /* success */);
+ }
}
}
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 6dca001..c237535 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -257,8 +257,8 @@
addChange(c);
}
c.addPackageOverride(packageName, overrides, allowedState, versionCode);
- invalidateCache();
}
+ invalidateCache();
return alreadyKnown;
}
@@ -379,9 +379,9 @@
CompatChange change = mChanges.valueAt(i);
removeOverrideUnsafe(change, packageName, versionCode);
}
- saveOverrides();
- invalidateCache();
}
+ saveOverrides();
+ invalidateCache();
}
/**
@@ -626,7 +626,18 @@
if (mOverridesFile == null) {
return;
}
+ Overrides overrides = new Overrides();
synchronized (mChanges) {
+ List<ChangeOverrides> changeOverridesList = overrides.getChangeOverrides();
+ for (int idx = 0; idx < mChanges.size(); ++idx) {
+ CompatChange c = mChanges.valueAt(idx);
+ ChangeOverrides changeOverrides = c.saveOverrides();
+ if (changeOverrides != null) {
+ changeOverridesList.add(changeOverrides);
+ }
+ }
+ }
+ synchronized (mOverridesFile) {
// Create the file if it doesn't already exist
try {
mOverridesFile.createNewFile();
@@ -636,15 +647,6 @@
}
try (PrintWriter out = new PrintWriter(mOverridesFile)) {
XmlWriter writer = new XmlWriter(out);
- Overrides overrides = new Overrides();
- List<ChangeOverrides> changeOverridesList = overrides.getChangeOverrides();
- for (int idx = 0; idx < mChanges.size(); ++idx) {
- CompatChange c = mChanges.valueAt(idx);
- ChangeOverrides changeOverrides = c.saveOverrides();
- if (changeOverrides != null) {
- changeOverridesList.add(changeOverrides);
- }
- }
XmlWriter.write(writer, overrides);
} catch (IOException e) {
Slog.e(TAG, e.toString());
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index ddac19b..7148bec 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1250,6 +1250,8 @@
updateState(DetailedState.CONNECTING, "agentConnect");
final NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig.Builder()
+ .setLegacyType(ConnectivityManager.TYPE_VPN)
+ .setLegacyTypeName("VPN")
.setBypassableVpn(mConfig.allowBypass && !mLockdown)
.build();
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 170564d..184ddae 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -21,6 +21,7 @@
import android.content.res.Resources;
import android.os.Environment;
import android.os.PowerManager;
+import android.text.TextUtils;
import android.util.MathUtils;
import android.util.Slog;
import android.util.Spline;
@@ -34,6 +35,7 @@
import com.android.server.display.config.HighBrightnessMode;
import com.android.server.display.config.NitsMap;
import com.android.server.display.config.Point;
+import com.android.server.display.config.RefreshRateRange;
import com.android.server.display.config.SensorDetails;
import com.android.server.display.config.XmlParser;
@@ -79,10 +81,10 @@
private final Context mContext;
// The details of the ambient light sensor associated with this display.
- private final SensorIdentifier mAmbientLightSensor = new SensorIdentifier();
+ private final SensorData mAmbientLightSensor = new SensorData();
// The details of the proximity sensor associated with this display.
- private final SensorIdentifier mProximitySensor = new SensorIdentifier();
+ private final SensorData mProximitySensor = new SensorData();
// Nits and backlight values that are loaded from either the display device config file, or
// config.xml. These are the raw values and just used for the dumpsys
@@ -113,6 +115,7 @@
private List<String> mQuirks;
private boolean mIsHighBrightnessModeEnabled = false;
private HighBrightnessModeData mHbmData;
+ private String mLoadedFrom = null;
private DisplayDeviceConfig(Context context) {
mContext = context;
@@ -273,11 +276,11 @@
return mBrightnessRampSlowIncrease;
}
- SensorIdentifier getAmbientLightSensor() {
+ SensorData getAmbientLightSensor() {
return mAmbientLightSensor;
}
- SensorIdentifier getProximitySensor() {
+ SensorData getProximitySensor() {
return mProximitySensor;
}
@@ -306,7 +309,8 @@
@Override
public String toString() {
String str = "DisplayDeviceConfig{"
- + "mBacklight=" + Arrays.toString(mBacklight)
+ + "mLoadedFrom=" + mLoadedFrom
+ + ", mBacklight=" + Arrays.toString(mBacklight)
+ ", mNits=" + Arrays.toString(mNits)
+ ", mRawBacklight=" + Arrays.toString(mRawBacklight)
+ ", mRawNits=" + Arrays.toString(mRawNits)
@@ -336,9 +340,8 @@
final String filename = String.format(CONFIG_FILE_FORMAT, suffix);
final File filePath = Environment.buildPath(
baseDirectory, ETC_DIR, DISPLAY_CONFIG_DIR, filename);
- if (filePath.exists()) {
- final DisplayDeviceConfig config = new DisplayDeviceConfig(context);
- config.initFromFile(filePath);
+ final DisplayDeviceConfig config = new DisplayDeviceConfig(context);
+ if (config.initFromFile(filePath)) {
return config;
}
return null;
@@ -356,15 +359,15 @@
return config;
}
- private void initFromFile(File configFile) {
+ private boolean initFromFile(File configFile) {
if (!configFile.exists()) {
// Display configuration files aren't required to exist.
- return;
+ return false;
}
if (!configFile.isFile()) {
Slog.e(TAG, "Display configuration is not a file: " + configFile + ", skipping");
- return;
+ return false;
}
try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
@@ -385,6 +388,8 @@
Slog.e(TAG, "Encountered an error while reading/parsing display config file: "
+ configFile, e);
}
+ mLoadedFrom = configFile.toString();
+ return true;
}
private void initFromGlobalXml() {
@@ -395,10 +400,12 @@
loadBrightnessRampsFromConfigXml();
loadAmbientLightSensorFromConfigXml();
setProxSensorUnspecified();
+ mLoadedFrom = "<config.xml>";
}
private void initFromDefaultValues() {
// Set all to basic values
+ mLoadedFrom = "Static values";
mBacklightMinimum = PowerManager.BRIGHTNESS_MIN;
mBacklightMaximum = PowerManager.BRIGHTNESS_MAX;
mBrightnessDefault = BRIGHTNESS_DEFAULT;
@@ -689,6 +696,11 @@
if (sensorDetails != null) {
mAmbientLightSensor.type = sensorDetails.getType();
mAmbientLightSensor.name = sensorDetails.getName();
+ final RefreshRateRange rr = sensorDetails.getRefreshRate();
+ if (rr != null) {
+ mAmbientLightSensor.minRefreshRate = rr.getMinimum().floatValue();
+ mAmbientLightSensor.maxRefreshRate = rr.getMaximum().floatValue();
+ }
} else {
loadAmbientLightSensorFromConfigXml();
}
@@ -704,22 +716,42 @@
if (sensorDetails != null) {
mProximitySensor.name = sensorDetails.getName();
mProximitySensor.type = sensorDetails.getType();
+ final RefreshRateRange rr = sensorDetails.getRefreshRate();
+ if (rr != null) {
+ mProximitySensor.minRefreshRate = rr.getMinimum().floatValue();
+ mProximitySensor.maxRefreshRate = rr.getMaximum().floatValue();
+ }
} else {
setProxSensorUnspecified();
}
}
- static class SensorIdentifier {
+ static class SensorData {
public String type;
public String name;
+ public float minRefreshRate = 0.0f;
+ public float maxRefreshRate = Float.POSITIVE_INFINITY;
@Override
public String toString() {
return "Sensor{"
- + "type: \"" + type + "\""
- + ", name: \"" + name + "\""
+ + "type: " + type
+ + ", name: " + name
+ + ", refreshRateRange: [" + minRefreshRate + ", " + maxRefreshRate + "]"
+ "} ";
}
+
+ /**
+ * @return True if the sensor matches both the specified name and type, or one if only
+ * one is specified (not-empty). Always returns false if both parameters are null or empty.
+ */
+ public boolean matches(String sensorName, String sensorType) {
+ final boolean isNameSpecified = !TextUtils.isEmpty(sensorName);
+ final boolean isTypeSpecified = !TextUtils.isEmpty(sensorType);
+ return (isNameSpecified || isTypeSpecified)
+ && (!isNameSpecified || sensorName.equals(name))
+ && (!isTypeSpecified || sensorType.equals(type));
+ }
}
/**
@@ -771,7 +803,7 @@
+ ", transition: " + transitionPoint
+ ", timeWindow: " + timeWindowMillis + "ms"
+ ", timeMax: " + timeMaxMillis + "ms"
- + ", timeMin: " + timeMinMillis
+ + ", timeMin: " + timeMinMillis + "ms"
+ "} ";
}
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index fe5ee78..bff39a9 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -50,6 +50,7 @@
import android.database.ContentObserver;
import android.graphics.ColorSpace;
import android.graphics.Point;
+import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.AmbientBrightnessDayStats;
@@ -62,6 +63,7 @@
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayGroupListener;
import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
+import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes;
@@ -119,6 +121,8 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.UiThread;
+import com.android.server.display.DisplayDeviceConfig.SensorData;
+import com.android.server.display.utils.SensorUtils;
import com.android.server.wm.SurfaceAnimationThread;
import com.android.server.wm.WindowManagerInternal;
@@ -3257,6 +3261,40 @@
public int getRefreshRateSwitchingType() {
return getRefreshRateSwitchingTypeInternal();
}
+
+ @Override
+ public RefreshRateRange getRefreshRateForDisplayAndSensor(int displayId, String sensorName,
+ String sensorType) {
+ final SensorManager sensorManager;
+ synchronized (mSyncRoot) {
+ sensorManager = mSensorManager;
+ }
+ if (sensorManager == null) {
+ return null;
+ }
+
+ // Verify that the specified sensor exists.
+ final Sensor sensor = SensorUtils.findSensor(sensorManager, sensorType, sensorName,
+ SensorUtils.NO_FALLBACK);
+ if (sensor == null) {
+ return null;
+ }
+
+ synchronized (mSyncRoot) {
+ final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
+ final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
+ if (device == null) {
+ return null;
+ }
+ final DisplayDeviceConfig config = device.getDisplayDeviceConfig();
+ SensorData sensorData = config.getProximitySensor();
+ if (sensorData.matches(sensorName, sensorType)) {
+ return new RefreshRateRange(sensorData.minRefreshRate,
+ sensorData.maxRefreshRate);
+ }
+ }
+ return null;
+ }
}
class DesiredDisplayModeSpecsObserver
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 07d13c2..2364a3c 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -27,6 +27,8 @@
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.net.Uri;
import android.os.Handler;
@@ -51,6 +53,8 @@
import com.android.server.LocalServices;
import com.android.server.display.utils.AmbientFilter;
import com.android.server.display.utils.AmbientFilterFactory;
+import com.android.server.sensors.SensorManagerInternal;
+import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.utils.DeviceConfigInterface;
@@ -85,8 +89,7 @@
private static final int INVALID_DISPLAY_MODE_ID = -1;
- // The tolerance within which we consider something approximately equals.
- private static final float FLOAT_TOLERANCE = 0.01f;
+ private static final float FLOAT_TOLERANCE = RefreshRateRange.FLOAT_TOLERANCE;
private final Object mLock = new Object();
private final Context mContext;
@@ -98,6 +101,7 @@
private final SettingsObserver mSettingsObserver;
private final DisplayObserver mDisplayObserver;
private final UdfpsObserver mUdfpsObserver;
+ private final SensorObserver mSensorObserver;
private final DeviceConfigInterface mDeviceConfig;
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
@@ -139,6 +143,11 @@
mDisplayObserver = new DisplayObserver(context, handler);
mBrightnessObserver = new BrightnessObserver(context, handler);
mUdfpsObserver = new UdfpsObserver();
+ mSensorObserver = new SensorObserver(context, (displayId, priority, vote) -> {
+ synchronized (mLock) {
+ updateVoteLocked(displayId, priority, vote);
+ }
+ });
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
mDeviceConfig = injector.getDeviceConfig();
mAlwaysRespectAppRequest = false;
@@ -155,6 +164,7 @@
mSettingsObserver.observe();
mDisplayObserver.observe();
mBrightnessObserver.observe(sensorManager);
+ mSensorObserver.observe();
synchronized (mLock) {
// We may have a listener already registered before the call to start, so go ahead and
// notify them to pick up our newly initialized state.
@@ -585,6 +595,7 @@
mAppRequestObserver.dumpLocked(pw);
mBrightnessObserver.dumpLocked(pw);
mUdfpsObserver.dumpLocked(pw);
+ mSensorObserver.dumpLocked(pw);
}
}
@@ -768,66 +779,6 @@
}
/**
- * Information about the min and max refresh rate DM would like to set the display to.
- */
- public static final class RefreshRateRange {
- /**
- * The lowest desired refresh rate.
- */
- public float min;
- /**
- * The highest desired refresh rate.
- */
- public float max;
-
- public RefreshRateRange() {}
-
- public RefreshRateRange(float min, float max) {
- if (min < 0 || max < 0 || min > max + FLOAT_TOLERANCE) {
- Slog.e(TAG, "Wrong values for min and max when initializing RefreshRateRange : "
- + min + " " + max);
- this.min = this.max = 0;
- return;
- }
- if (min > max) {
- // Min and max are within epsilon of each other, but in the wrong order.
- float t = min;
- min = max;
- max = t;
- }
- this.min = min;
- this.max = max;
- }
-
- /**
- * Checks whether the two objects have the same values.
- */
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- if (!(other instanceof RefreshRateRange)) {
- return false;
- }
-
- RefreshRateRange refreshRateRange = (RefreshRateRange) other;
- return (min == refreshRateRange.min && max == refreshRateRange.max);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(min, max);
- }
-
- @Override
- public String toString() {
- return "(" + min + " " + max + ")";
- }
- }
-
- /**
* Information about the desired display mode to be set by the system. Includes the base
* mode ID and the primary and app request refresh rate ranges.
*
@@ -987,9 +938,13 @@
// user seeing the display flickering when the switches occur.
public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 8;
+ // The proximity sensor needs the refresh rate to be locked in order to function, so this is
+ // set to a high priority.
+ public static final int PRIORITY_PROXIMITY = 9;
+
// The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order
// to function, so this needs to be the highest priority of all votes.
- public static final int PRIORITY_UDFPS = 9;
+ public static final int PRIORITY_UDFPS = 10;
// Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
// APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
@@ -1086,6 +1041,8 @@
return "PRIORITY_LOW_POWER_MODE";
case PRIORITY_UDFPS:
return "PRIORITY_UDFPS";
+ case PRIORITY_PROXIMITY:
+ return "PRIORITY_PROXIMITY";
default:
return Integer.toString(priority);
@@ -2142,6 +2099,62 @@
}
}
+ private static class SensorObserver implements ProximityActiveListener {
+ private static final String PROXIMITY_SENSOR_NAME = null;
+ private static final String PROXIMITY_SENSOR_TYPE = Sensor.STRING_TYPE_PROXIMITY;
+
+ private final BallotBox mBallotBox;
+ private final Context mContext;
+
+ private DisplayManager mDisplayManager;
+ private DisplayManagerInternal mDisplayManagerInternal;
+ private boolean mIsProxActive = false;
+
+ SensorObserver(Context context, BallotBox ballotBox) {
+ mContext = context;
+ mBallotBox = ballotBox;
+ }
+
+ @Override
+ public void onProximityActive(boolean isActive) {
+ if (mIsProxActive != isActive) {
+ mIsProxActive = isActive;
+ recalculateVotes();
+ }
+ }
+
+ public void observe() {
+ mDisplayManager = mContext.getSystemService(DisplayManager.class);
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
+
+ final SensorManagerInternal sensorManager =
+ LocalServices.getService(SensorManagerInternal.class);
+ sensorManager.addProximityActiveListener(BackgroundThread.getExecutor(), this);
+ }
+
+ private void recalculateVotes() {
+ final Display[] displays = mDisplayManager.getDisplays();
+ for (Display d : displays) {
+ int displayId = d.getDisplayId();
+ Vote vote = null;
+ if (mIsProxActive) {
+ final RefreshRateRange rate =
+ mDisplayManagerInternal.getRefreshRateForDisplayAndSensor(
+ displayId, PROXIMITY_SENSOR_NAME, PROXIMITY_SENSOR_TYPE);
+ if (rate != null) {
+ vote = Vote.forRefreshRates(rate.min, rate.max);
+ }
+ }
+ mBallotBox.vote(displayId, Vote.PRIORITY_PROXIMITY, vote);
+ }
+ }
+
+ void dumpLocked(PrintWriter pw) {
+ pw.println(" SensorObserver");
+ pw.println(" mIsProxActive=" + mIsProxActive);
+ }
+ }
+
private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
public DeviceConfigDisplaySettings() {
}
@@ -2328,4 +2341,7 @@
}
}
+ interface BallotBox {
+ void vote(int displayId, int priority, Vote vote);
+ }
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1b50f03..555add4 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -48,7 +48,6 @@
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
-import android.text.TextUtils;
import android.util.Log;
import android.util.MathUtils;
import android.util.Slog;
@@ -65,13 +64,13 @@
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
+import com.android.server.display.utils.SensorUtils;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory;
import com.android.server.display.whitebalance.DisplayWhiteBalanceSettings;
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
-import java.util.List;
/**
* Controls the power state of the display.
@@ -586,26 +585,6 @@
mBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), adjustedNits);
}
- private Sensor findSensor(String sensorType, String sensorName, int fallbackType,
- boolean useFallback) {
- final boolean isNameSpecified = !TextUtils.isEmpty(sensorName);
- final boolean isTypeSpecified = !TextUtils.isEmpty(sensorType);
- List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
- if (isNameSpecified || isTypeSpecified) {
- for (Sensor sensor : sensors) {
- if ((!isNameSpecified || sensorName.equals(sensor.getName()))
- && (!isTypeSpecified || sensorType.equals(sensor.getStringType()))) {
- return sensor;
- }
- }
- }
- if (useFallback) {
- return mSensorManager.getDefaultSensor(fallbackType);
- } else {
- return null;
- }
- }
-
/**
* Returns true if the proximity sensor screen-off function is available.
*/
@@ -1654,24 +1633,23 @@
}
private void loadAmbientLightSensor() {
- DisplayDeviceConfig.SensorIdentifier lightSensor =
- mDisplayDeviceConfig.getAmbientLightSensor();
- String lightSensorName = lightSensor.name;
- String lightSensorType = lightSensor.type;
- mLightSensor = findSensor(lightSensorType, lightSensorName, Sensor.TYPE_LIGHT,
- mDisplayId == Display.DEFAULT_DISPLAY);
+ DisplayDeviceConfig.SensorData lightSensor = mDisplayDeviceConfig.getAmbientLightSensor();
+ final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY
+ ? Sensor.TYPE_LIGHT : SensorUtils.NO_FALLBACK;
+ mLightSensor = SensorUtils.findSensor(mSensorManager, lightSensor.type, lightSensor.name,
+ fallbackType);
}
private void loadProximitySensor() {
if (DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
return;
}
- final DisplayDeviceConfig.SensorIdentifier proxSensor =
+ final DisplayDeviceConfig.SensorData proxSensor =
mDisplayDeviceConfig.getProximitySensor();
- final String proxSensorName = proxSensor.name;
- final String proxSensorType = proxSensor.type;
- mProximitySensor = findSensor(proxSensorType, proxSensorName, Sensor.TYPE_PROXIMITY,
- mDisplayId == Display.DEFAULT_DISPLAY);
+ final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY
+ ? Sensor.TYPE_PROXIMITY : SensorUtils.NO_FALLBACK;
+ mProximitySensor = SensorUtils.findSensor(mSensorManager, proxSensor.type, proxSensor.name,
+ fallbackType);
if (mProximitySensor != null) {
mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
TYPICAL_PROXIMITY_THRESHOLD);
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index b948777..57a8c4b 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -22,6 +22,7 @@
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Slog;
+import android.util.TimeUtils;
import android.view.SurfaceControlHdrLayerInfoListener;
import com.android.internal.annotations.VisibleForTesting;
@@ -189,6 +190,10 @@
}
void dump(PrintWriter pw) {
+ mHandler.runWithScissors(() -> dumpLocal(pw), 1000);
+ }
+
+ private void dumpLocal(PrintWriter pw) {
pw.println("HighBrightnessModeController:");
pw.println(" mCurrentMin=" + getCurrentBrightnessMin());
pw.println(" mCurrentMax=" + getCurrentBrightnessMax());
@@ -202,6 +207,29 @@
pw.println(" mIsHdrLayerPresent=" + mIsHdrLayerPresent);
pw.println(" mBrightnessMin=" + mBrightnessMin);
pw.println(" mBrightnessMax=" + mBrightnessMax);
+ pw.println(" mRunningStartTimeMillis=" + TimeUtils.formatUptime(mRunningStartTimeMillis));
+ pw.println(" mEvents=");
+ final long currentTime = mClock.uptimeMillis();
+ long lastStartTime = currentTime;
+ if (mRunningStartTimeMillis != -1) {
+ lastStartTime = dumpHbmEvent(pw, new HbmEvent(mRunningStartTimeMillis, currentTime));
+ }
+ for (HbmEvent event : mEvents) {
+ if (lastStartTime > event.endTimeMillis) {
+ pw.println(" event: [normal brightness]: "
+ + TimeUtils.formatDuration(lastStartTime - event.endTimeMillis));
+ }
+ lastStartTime = dumpHbmEvent(pw, event);
+ }
+ }
+
+ private long dumpHbmEvent(PrintWriter pw, HbmEvent event) {
+ final long duration = event.endTimeMillis - event.startTimeMillis;
+ pw.println(" event: ["
+ + TimeUtils.formatUptime(event.startTimeMillis) + ", "
+ + TimeUtils.formatUptime(event.endTimeMillis) + "] ("
+ + TimeUtils.formatDuration(duration) + ")");
+ return event.startTimeMillis;
}
private boolean isCurrentlyAllowed() {
diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java
index 6db75eb..a7e1a28 100644
--- a/services/core/java/com/android/server/display/WifiDisplayController.java
+++ b/services/core/java/com/android/server/display/WifiDisplayController.java
@@ -550,11 +550,6 @@
private void disconnect() {
mDesiredDevice = null;
- mWifiP2pManager = null;
- if (null != mWifiP2pChannel) {
- mWifiP2pChannel.close();
- mWifiP2pChannel = null;
- }
updateConnection();
}
diff --git a/services/core/java/com/android/server/display/utils/SensorUtils.java b/services/core/java/com/android/server/display/utils/SensorUtils.java
new file mode 100644
index 0000000..cb40b40
--- /dev/null
+++ b/services/core/java/com/android/server/display/utils/SensorUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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.display.utils;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.text.TextUtils;
+
+import java.util.List;
+
+/**
+ * Provides utility methods for dealing with sensors.
+ */
+public class SensorUtils {
+ public static final int NO_FALLBACK = 0;
+
+ /**
+ * Finds the specified sensor by type and name using SensorManager.
+ */
+ public static Sensor findSensor(SensorManager sensorManager, String sensorType,
+ String sensorName, int fallbackType) {
+ final boolean isNameSpecified = !TextUtils.isEmpty(sensorName);
+ final boolean isTypeSpecified = !TextUtils.isEmpty(sensorType);
+ if (isNameSpecified || isTypeSpecified) {
+ final List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
+ for (Sensor sensor : sensors) {
+ if ((!isNameSpecified || sensorName.equals(sensor.getName()))
+ && (!isTypeSpecified || sensorType.equals(sensor.getStringType()))) {
+ return sensor;
+ }
+ }
+ }
+ if (fallbackType != NO_FALLBACK) {
+ return sensorManager.getDefaultSensor(fallbackType);
+ }
+
+ return null;
+ }
+
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 2ed160a..a086bda 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -2580,7 +2580,8 @@
return null;
}
- private void addHdmiControlStatusChangeListener(
+ @VisibleForTesting
+ void addHdmiControlStatusChangeListener(
final IHdmiControlStatusChangeListener listener) {
final HdmiControlStatusChangeListenerRecord record =
new HdmiControlStatusChangeListenerRecord(listener);
@@ -2916,13 +2917,17 @@
} else {
mIsCecAvailable = true;
}
+ if (!listeners.isEmpty()) {
+ invokeHdmiControlStatusChangeListenerLocked(listeners,
+ isEnabled, mIsCecAvailable);
+ }
}
});
} else {
mIsCecAvailable = false;
- }
- if (!listeners.isEmpty()) {
- invokeHdmiControlStatusChangeListenerLocked(listeners, isEnabled, mIsCecAvailable);
+ if (!listeners.isEmpty()) {
+ invokeHdmiControlStatusChangeListenerLocked(listeners, isEnabled, mIsCecAvailable);
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/BubbleExtractor.java b/services/core/java/com/android/server/notification/BubbleExtractor.java
index 2caad50..41e067e 100644
--- a/services/core/java/com/android/server/notification/BubbleExtractor.java
+++ b/services/core/java/com/android/server/notification/BubbleExtractor.java
@@ -167,20 +167,20 @@
// TODO: check the shortcut intent / ensure it can show in activity view
return true;
}
- return canLaunchInActivityView(mContext, metadata.getIntent(), pkg);
+ return canLaunchInTaskView(mContext, metadata.getIntent(), pkg);
}
/**
* Whether an intent is properly configured to display in an {@link
- * android.app.ActivityView} for bubbling.
+ * com.android.wm.shell.TaskView} for bubbling.
*
* @param context the context to use.
* @param pendingIntent the pending intent of the bubble.
* @param packageName the notification package name for this bubble.
*/
- // Keep checks in sync with BubbleController#canLaunchInActivityView.
+ // Keep checks in sync with BubbleController#canLaunchInTaskView.
@VisibleForTesting
- protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
+ protected boolean canLaunchInTaskView(Context context, PendingIntent pendingIntent,
String packageName) {
if (pendingIntent == null) {
Slog.w(TAG, "Unable to create bubble -- no intent");
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b26485b..a3f3a3a 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4785,7 +4785,7 @@
}
@Override
- public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
+ public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String pkg) {
Objects.requireNonNull(automaticZenRule, "automaticZenRule is null");
Objects.requireNonNull(automaticZenRule.getName(), "Name is null");
if (automaticZenRule.getOwner() == null
@@ -4794,6 +4794,7 @@
"Rule must have a conditionproviderservice and/or configuration activity");
}
Objects.requireNonNull(automaticZenRule.getConditionId(), "ConditionId is null");
+ checkCallerIsSameApp(pkg);
if (automaticZenRule.getZenPolicy() != null
&& automaticZenRule.getInterruptionFilter() != INTERRUPTION_FILTER_PRIORITY) {
throw new IllegalArgumentException("ZenPolicy is only applicable to "
@@ -4801,7 +4802,7 @@
}
enforcePolicyAccess(Binder.getCallingUid(), "addAutomaticZenRule");
- return mZenModeHelper.addAutomaticZenRule(automaticZenRule,
+ return mZenModeHelper.addAutomaticZenRule(pkg, automaticZenRule,
"addAutomaticZenRule");
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 4cb6c3b..a98f113 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -307,7 +307,8 @@
return null;
}
- public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
+ public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule,
+ String reason) {
if (!isSystemRule(automaticZenRule)) {
PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
if (component == null) {
@@ -340,7 +341,7 @@
}
newConfig = mConfig.copy();
ZenRule rule = new ZenRule();
- populateZenRule(automaticZenRule, rule, true);
+ populateZenRule(pkg, automaticZenRule, rule, true);
newConfig.automaticRules.put(rule.id, rule);
if (setConfigLocked(newConfig, reason, rule.component, true)) {
return rule.id;
@@ -376,7 +377,7 @@
? AUTOMATIC_RULE_STATUS_ENABLED : AUTOMATIC_RULE_STATUS_DISABLED);
}
- populateZenRule(automaticZenRule, rule, false);
+ populateZenRule(rule.pkg, automaticZenRule, rule, false);
return setConfigLocked(newConfig, reason, rule.component, true);
}
}
@@ -585,7 +586,8 @@
return null;
}
- private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) {
+ private void populateZenRule(String pkg, AutomaticZenRule automaticZenRule, ZenRule rule,
+ boolean isNew) {
rule.name = automaticZenRule.getName();
rule.condition = null;
rule.conditionId = automaticZenRule.getConditionId();
@@ -600,9 +602,7 @@
rule.id = ZenModeConfig.newRuleId();
rule.creationTime = System.currentTimeMillis();
rule.component = automaticZenRule.getOwner();
- rule.pkg = (rule.component != null)
- ? rule.component.getPackageName()
- : rule.configurationActivity.getPackageName();
+ rule.pkg = pkg;
}
if (rule.enabled != automaticZenRule.isEnabled()) {
@@ -611,10 +611,13 @@
}
protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
- return new AutomaticZenRule(rule.name, rule.component, rule.configurationActivity,
+ AutomaticZenRule azr = new AutomaticZenRule(rule.name, rule.component,
+ rule.configurationActivity,
rule.conditionId, rule.zenPolicy,
NotificationManager.zenModeToInterruptionFilter(rule.zenMode),
rule.enabled, rule.creationTime);
+ azr.setPackageName(rule.pkg);
+ return azr;
}
public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 293c59d..346f311 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -20,6 +20,7 @@
import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.AppOpsManager;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
@@ -31,6 +32,7 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.TelephonyManager;
import android.util.ArraySet;
@@ -81,7 +83,7 @@
== BugreportParams.BUGREPORT_MODE_TELEPHONY /* checkCarrierPrivileges */);
final long identity = Binder.clearCallingIdentity();
try {
- ensureIsPrimaryUser();
+ ensureUserCanTakeBugReport(bugreportMode);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -166,11 +168,12 @@
}
/**
- * Validates that the current user is the primary user.
+ * Validates that the current user is the primary user or when bugreport is requested remotely
+ * and current user is affiliated user.
*
* @throws IllegalArgumentException if the current user is not the primary user
*/
- private void ensureIsPrimaryUser() {
+ private void ensureUserCanTakeBugReport(int bugreportMode) {
UserInfo currentUser = null;
try {
currentUser = ActivityManager.getService().getCurrentUser();
@@ -186,11 +189,40 @@
logAndThrow("No primary user. Only primary user is allowed to take bugreports.");
}
if (primaryUser.id != currentUser.id) {
+ if (bugreportMode == BugreportParams.BUGREPORT_MODE_REMOTE
+ && isCurrentUserAffiliated(currentUser.id)) {
+ return;
+ }
logAndThrow("Current user not primary user. Only primary user"
+ " is allowed to take bugreports.");
}
}
+ /**
+ * Returns {@code true} if the device has device owner and the current user is affiliated
+ * with the device owner.
+ */
+ private boolean isCurrentUserAffiliated(int currentUserId) {
+ DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+ int deviceOwnerUid = dpm.getDeviceOwnerUserId();
+ if (deviceOwnerUid == UserHandle.USER_NULL) {
+ return false;
+ }
+
+ int callingUserId = UserHandle.getUserId(Binder.getCallingUid());
+
+ Slog.i(TAG, "callingUid: " + callingUserId + " deviceOwnerUid: " + deviceOwnerUid
+ + " currentUserId: " + currentUserId);
+
+ if (callingUserId != deviceOwnerUid) {
+ logAndThrow("Caller is not device owner on provisioned device.");
+ }
+ if (!dpm.isAffiliatedUser(currentUserId)) {
+ logAndThrow("Current user is not affiliated to the device owner.");
+ }
+ return true;
+ }
+
@GuardedBy("mLock")
private void startBugreportLocked(int callingUid, String callingPackage,
FileDescriptor bugreportFd, FileDescriptor screenshotFd,
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 06ff691..d1d1eb0 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -17,6 +17,7 @@
package com.android.server.pm;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.os.UserHandle.USER_ALL;
import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
@@ -685,7 +686,7 @@
synchronized (mCacheLock) {
if (mShouldFilterCache != null) {
updateShouldFilterCacheForPackage(mShouldFilterCache, null, newPkgSetting,
- settings, users, settings.size());
+ settings, users, USER_ALL, settings.size());
if (additionalChangedPackages != null) {
for (int index = 0; index < additionalChangedPackages.size(); index++) {
String changedPackage = additionalChangedPackages.valueAt(index);
@@ -698,7 +699,8 @@
}
updateShouldFilterCacheForPackage(mShouldFilterCache, null,
- changedPkgSetting, settings, users, settings.size());
+ changedPkgSetting, settings, users, USER_ALL,
+ settings.size());
}
}
} // else, rebuild entire cache when system is ready
@@ -830,24 +832,51 @@
}
}
}
-
private void updateEntireShouldFilterCache() {
+ updateEntireShouldFilterCache(USER_ALL);
+ }
+
+ private void updateEntireShouldFilterCache(int subjectUserId) {
mStateProvider.runWithState((settings, users) -> {
+ int userId = subjectUserId;
+ if (!ArrayUtils.contains(users, subjectUserId)) {
+ Slog.e(TAG, "We encountered a new user that isn't a member of known users, "
+ + "updating the whole cache");
+ userId = USER_ALL;
+ }
WatchedSparseBooleanMatrix cache =
- updateEntireShouldFilterCacheInner(settings, users);
+ updateEntireShouldFilterCacheInner(settings, users, userId);
synchronized (mCacheLock) {
+ if (userId != USER_ALL) {
+ // if we're only updating a single user id, we need to copy over the prior
+ // cached values for the other users.
+ int[] uids = mShouldFilterCache.keys();
+ for (int i = 0; i < uids.length; i++) {
+ int uid1 = uids[i];
+ if (UserHandle.getUserId(uid1) == userId) {
+ continue;
+ }
+ for (int j = 0; j < uids.length; j++) {
+ int uid2 = uids[j];
+ if (UserHandle.getUserId(uid2) == userId) {
+ continue;
+ }
+ cache.setValueAt(uid1, uid2, mShouldFilterCache.valueAt(uid1, uid2));
+ }
+ }
+ }
mShouldFilterCache = cache;
}
});
}
private WatchedSparseBooleanMatrix updateEntireShouldFilterCacheInner(
- ArrayMap<String, PackageSetting> settings, UserInfo[] users) {
+ ArrayMap<String, PackageSetting> settings, UserInfo[] users, int subjectUserId) {
WatchedSparseBooleanMatrix cache =
new WatchedSparseBooleanMatrix(users.length * settings.size());
for (int i = settings.size() - 1; i >= 0; i--) {
updateShouldFilterCacheForPackage(cache,
- null /*skipPackage*/, settings.valueAt(i), settings, users, i);
+ null /*skipPackage*/, settings.valueAt(i), settings, users, subjectUserId, i);
}
return cache;
}
@@ -868,8 +897,8 @@
packagesCache.put(settings.keyAt(i), pkg);
}
});
- WatchedSparseBooleanMatrix cache =
- updateEntireShouldFilterCacheInner(settingsCopy, usersRef[0]);
+ WatchedSparseBooleanMatrix cache = updateEntireShouldFilterCacheInner(
+ settingsCopy, usersRef[0], USER_ALL);
boolean[] changed = new boolean[1];
// We have a cache, let's make sure the world hasn't changed out from under us.
mStateProvider.runWithState((settings, users) -> {
@@ -899,10 +928,10 @@
});
}
- public void onUsersChanged() {
+ public void onUserCreated(int newUserId) {
synchronized (mCacheLock) {
if (mShouldFilterCache != null) {
- updateEntireShouldFilterCache();
+ updateEntireShouldFilterCache(newUserId);
onChanged();
}
}
@@ -913,7 +942,7 @@
if (mShouldFilterCache != null) {
mStateProvider.runWithState((settings, users) -> {
updateShouldFilterCacheForPackage(mShouldFilterCache, null /* skipPackage */,
- settings.get(packageName), settings, users,
+ settings.get(packageName), settings, users, USER_ALL,
settings.size() /*maxIndex*/);
});
}
@@ -922,7 +951,7 @@
private void updateShouldFilterCacheForPackage(WatchedSparseBooleanMatrix cache,
@Nullable String skipPackageName, PackageSetting subjectSetting, ArrayMap<String,
- PackageSetting> allSettings, UserInfo[] allUsers, int maxIndex) {
+ PackageSetting> allSettings, UserInfo[] allUsers, int subjectUserId, int maxIndex) {
for (int i = Math.min(maxIndex, allSettings.size() - 1); i >= 0; i--) {
PackageSetting otherSetting = allSettings.valueAt(i);
if (subjectSetting.appId == otherSetting.appId) {
@@ -932,25 +961,34 @@
if (subjectSetting.name == skipPackageName || otherSetting.name == skipPackageName) {
continue;
}
- final int userCount = allUsers.length;
- final int appxUidCount = userCount * allSettings.size();
- for (int su = 0; su < userCount; su++) {
- int subjectUser = allUsers[su].id;
- for (int ou = 0; ou < userCount; ou++) {
- int otherUser = allUsers[ou].id;
- int subjectUid = UserHandle.getUid(subjectUser, subjectSetting.appId);
- int otherUid = UserHandle.getUid(otherUser, otherSetting.appId);
- cache.put(subjectUid, otherUid,
- shouldFilterApplicationInternal(
- subjectUid, subjectSetting, otherSetting, otherUser));
- cache.put(otherUid, subjectUid,
- shouldFilterApplicationInternal(
- otherUid, otherSetting, subjectSetting, subjectUser));
+ if (subjectUserId == USER_ALL) {
+ for (int su = 0; su < allUsers.length; su++) {
+ updateShouldFilterCacheForUser(cache, subjectSetting, allUsers, otherSetting,
+ allUsers[su].id);
}
+ } else {
+ updateShouldFilterCacheForUser(cache, subjectSetting, allUsers, otherSetting,
+ subjectUserId);
}
}
}
+ private void updateShouldFilterCacheForUser(WatchedSparseBooleanMatrix cache,
+ PackageSetting subjectSetting, UserInfo[] allUsers, PackageSetting otherSetting,
+ int subjectUserId) {
+ for (int ou = 0; ou < allUsers.length; ou++) {
+ int otherUser = allUsers[ou].id;
+ int subjectUid = UserHandle.getUid(subjectUserId, subjectSetting.appId);
+ int otherUid = UserHandle.getUid(otherUser, otherSetting.appId);
+ cache.put(subjectUid, otherUid,
+ shouldFilterApplicationInternal(
+ subjectUid, subjectSetting, otherSetting, otherUser));
+ cache.put(otherUid, subjectUid,
+ shouldFilterApplicationInternal(
+ otherUid, otherSetting, subjectSetting, subjectUserId));
+ }
+ }
+
private static boolean isSystemSigned(@NonNull PackageParser.SigningDetails sysSigningDetails,
PackageSetting pkgSetting) {
return pkgSetting.isSystem()
@@ -1145,7 +1183,7 @@
continue;
}
updateShouldFilterCacheForPackage(mShouldFilterCache, setting.name,
- siblingSetting, settings, users, settings.size());
+ siblingSetting, settings, users, USER_ALL, settings.size());
}
}
@@ -1162,7 +1200,7 @@
}
updateShouldFilterCacheForPackage(mShouldFilterCache, null,
- changedPkgSetting, settings, users, settings.size());
+ changedPkgSetting, settings, users, USER_ALL, settings.size());
}
}
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index cd383b9..8fd545f 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -80,6 +80,17 @@
/** Indicates that dexopt may be run with different performance / priority tuned for restore */
public static final int DEXOPT_FOR_RESTORE = 1 << 13; // TODO(b/135202722): remove
+ /** The result of the profile analysis indicating that the app should be optimized. */
+ public static final int PROFILE_ANALYSIS_OPTIMIZE = 1;
+ /** The result of the profile analysis indicating that the app should not be optimized. */
+ public static final int PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA = 2;
+ /**
+ * The result of the profile analysis indicating that the app should not be optimized because
+ * the profiles are empty.
+ */
+ public static final int PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES = 3;
+
+
public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE;
public static final int FLAG_STORAGE_EXTERNAL = IInstalld.FLAG_STORAGE_EXTERNAL;
@@ -496,9 +507,18 @@
}
}
- public boolean mergeProfiles(int uid, String packageName, String profileName)
+ /**
+ * Analyzes the ART profiles of the given package, possibly merging the information
+ * into the reference profile. Returns whether or not we should optimize the package
+ * based on how much information is in the profile.
+ *
+ * @return one of {@link #PROFILE_ANALYSIS_OPTIMIZE},
+ * {@link #PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA},
+ * {@link #PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES}
+ */
+ public int mergeProfiles(int uid, String packageName, String profileName)
throws InstallerException {
- if (!checkBeforeRemote()) return false;
+ if (!checkBeforeRemote()) return PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
try {
return mInstalld.mergeProfiles(uid, packageName, profileName);
} catch (Exception e) {
@@ -645,13 +665,17 @@
}
}
- public void deleteOdex(String apkPath, String instructionSet, String outputPath)
+ /**
+ * Deletes the optimized artifacts generated by ART and returns the number
+ * of freed bytes.
+ */
+ public long deleteOdex(String apkPath, String instructionSet, String outputPath)
throws InstallerException {
- if (!checkBeforeRemote()) return;
+ if (!checkBeforeRemote()) return -1;
BlockGuard.getVmPolicy().onPathAccess(apkPath);
BlockGuard.getVmPolicy().onPathAccess(outputPath);
try {
- mInstalld.deleteOdex(apkPath, instructionSet, outputPath);
+ return mInstalld.deleteOdex(apkPath, instructionSet, outputPath);
} catch (Exception e) {
throw InstallerException.from(e);
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 131539e..5fd8e3c 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -31,6 +31,9 @@
import static com.android.server.pm.Installer.DEXOPT_SECONDARY_DEX;
import static com.android.server.pm.Installer.DEXOPT_STORAGE_CE;
import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE;
+import static com.android.server.pm.Installer.PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES;
+import static com.android.server.pm.Installer.PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
+import static com.android.server.pm.Installer.PROFILE_ANALYSIS_OPTIMIZE;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
@@ -248,8 +251,12 @@
|| packageUseInfo.isUsedByOtherApps(path);
final String compilerFilter = getRealCompilerFilter(pkg,
options.getCompilerFilter(), isUsedByOtherApps);
- final boolean profileUpdated = options.isCheckForProfileUpdates() &&
- isProfileUpdated(pkg, sharedGid, profileName, compilerFilter);
+ // If we don't have to check for profiles updates assume
+ // PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA which will be a no-op with respect to
+ // profiles.
+ final int profileAnalysisResult = options.isCheckForProfileUpdates()
+ ? analyseProfiles(pkg, sharedGid, profileName, compilerFilter)
+ : PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
// Get the dexopt flags after getRealCompilerFilter to make sure we get the correct
// flags.
@@ -257,7 +264,7 @@
for (String dexCodeIsa : dexCodeInstructionSets) {
int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter,
- profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid,
+ profileAnalysisResult, classLoaderContexts[i], dexoptFlags, sharedGid,
packageStats, options.isDowngrade(), profileName, dexMetadataPath,
options.getCompilationReason());
@@ -306,11 +313,11 @@
*/
@GuardedBy("mInstallLock")
private int dexOptPath(AndroidPackage pkg, @NonNull PackageSetting pkgSetting, String path,
- String isa, String compilerFilter, boolean profileUpdated, String classLoaderContext,
+ String isa, String compilerFilter, int profileAnalysisResult, String classLoaderContext,
int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade,
String profileName, String dexMetadataPath, int compilationReason) {
int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext,
- profileUpdated, downgrade);
+ profileAnalysisResult, downgrade);
if (Math.abs(dexoptNeeded) == DexFile.NO_DEXOPT_NEEDED) {
return DEX_OPT_SKIPPED;
}
@@ -364,7 +371,7 @@
isa,
options.getCompilerFilter(),
dexUseInfo.getClassLoaderContext(),
- /* newProfile= */false,
+ PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES,
/* downgrade= */ false);
if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
@@ -750,11 +757,25 @@
* configuration (isa, compiler filter, profile).
*/
private int getDexoptNeeded(String path, String isa, String compilerFilter,
- String classLoaderContext, boolean newProfile, boolean downgrade) {
+ String classLoaderContext, int profileAnalysisResult, boolean downgrade) {
int dexoptNeeded;
try {
- dexoptNeeded = DexFile.getDexOptNeeded(path, isa, compilerFilter, classLoaderContext,
- newProfile, downgrade);
+ // A profile guided optimizations with an empty profile is essentially 'verify' and
+ // dex2oat already makes this transformation. However DexFile.getDexOptNeeded() cannot
+ // check the profiles because system server does not have access to them.
+ // As such, we rely on the previous profile analysis (done with dexoptanalyzer) and
+ // manually adjust the actual filter before checking.
+ //
+ // TODO: ideally. we'd move this check in dexoptanalyzer, but that's a large change,
+ // and in the interim we can still improve things here.
+ String actualCompilerFilter = compilerFilter;
+ if (compilerFilterDependsOnProfiles(compilerFilter)
+ && profileAnalysisResult == PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES) {
+ actualCompilerFilter = "verify";
+ }
+ boolean newProfile = profileAnalysisResult == PROFILE_ANALYSIS_OPTIMIZE;
+ dexoptNeeded = DexFile.getDexOptNeeded(path, isa, actualCompilerFilter,
+ classLoaderContext, newProfile, downgrade);
} catch (IOException ioe) {
Slog.w(TAG, "IOException reading apk: " + path, ioe);
return DEX_OPT_FAILED;
@@ -765,27 +786,34 @@
return adjustDexoptNeeded(dexoptNeeded);
}
+ /** Returns true if the compiler filter depends on profiles (e.g speed-profile). */
+ private boolean compilerFilterDependsOnProfiles(String compilerFilter) {
+ return compilerFilter.endsWith("-profile");
+ }
+
/**
* Checks if there is an update on the profile information of the {@code pkg}.
- * If the compiler filter is not profile guided the method returns false.
+ * If the compiler filter is not profile guided the method returns a safe default:
+ * PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA.
*
* Note that this is a "destructive" operation with side effects. Under the hood the
* current profile and the reference profile will be merged and subsequent calls
* may return a different result.
*/
- private boolean isProfileUpdated(AndroidPackage pkg, int uid, String profileName,
+ private int analyseProfiles(AndroidPackage pkg, int uid, String profileName,
String compilerFilter) {
// Check if we are allowed to merge and if the compiler filter is profile guided.
if (!isProfileGuidedCompilerFilter(compilerFilter)) {
- return false;
+ return PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
}
// Merge profiles. It returns whether or not there was an updated in the profile info.
try {
return mInstaller.mergeProfiles(uid, pkg.getPackageName(), profileName);
} catch (InstallerException e) {
Slog.w(TAG, "Failed to merge profiles", e);
+ // We don't need to optimize if we failed to merge.
+ return PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
}
- return false;
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a8cc5fd..b02b704 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -341,6 +341,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
+import com.android.internal.content.F2fsUtils;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.content.om.OverlayConfig;
@@ -896,6 +897,20 @@
* Only non-null during an OTA, and even then it is nulled again once systemReady().
*/
private @Nullable ArraySet<String> mExistingPackages = null;
+
+ /**
+ * List of code paths that need to be released when the system becomes ready.
+ * <p>
+ * NOTE: We have to delay releasing cblocks for no other reason than we cannot
+ * retrieve the setting {@link Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL}. When
+ * we no longer need to read that setting, cblock release can occur in the
+ * constructor.
+ *
+ * @see Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL
+ * @see #systemReady()
+ */
+ private @Nullable List<File> mReleaseOnSystemReady;
+
/**
* Whether or not system app permissions should be promoted from install to runtime.
*/
@@ -7966,6 +7981,21 @@
IoUtils.closeQuietly(handle);
}
}
+ if (ret == PackageManager.INSTALL_SUCCEEDED) {
+ // NOTE: During boot, we have to delay releasing cblocks for no other reason than
+ // we cannot retrieve the setting {@link Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL}.
+ // When we no longer need to read that setting, cblock release can occur always
+ // occur here directly
+ if (!mSystemReady) {
+ if (mReleaseOnSystemReady == null) {
+ mReleaseOnSystemReady = new ArrayList<>();
+ }
+ mReleaseOnSystemReady.add(dstCodePath);
+ } else {
+ final ContentResolver resolver = mContext.getContentResolver();
+ F2fsUtils.releaseCompressedBlocks(resolver, dstCodePath);
+ }
+ }
if (ret != PackageManager.INSTALL_SUCCEEDED) {
if (!dstCodePath.exists()) {
return null;
@@ -12958,6 +12988,15 @@
@Override
public void dumpProfiles(String packageName) {
+ /* Only the shell, root, or the app user should be able to dump profiles. */
+ final int callingUid = Binder.getCallingUid();
+ final String[] callerPackageNames = getPackagesForUid(callingUid);
+ if (callingUid != Process.SHELL_UID
+ && callingUid != Process.ROOT_UID
+ && !ArrayUtils.contains(callerPackageNames, packageName)) {
+ throw new SecurityException("dumpProfiles");
+ }
+
AndroidPackage pkg;
synchronized (mLock) {
pkg = mPackages.get(packageName);
@@ -12965,13 +13004,6 @@
throw new IllegalArgumentException("Unknown package: " + packageName);
}
}
- /* Only the shell, root, or the app user should be able to dump profiles. */
- int callingUid = Binder.getCallingUid();
- if (callingUid != Process.SHELL_UID &&
- callingUid != Process.ROOT_UID &&
- callingUid != pkg.getUid()) {
- throw new SecurityException("dumpProfiles");
- }
synchronized (mInstallLock) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dump profiles");
@@ -17097,10 +17129,7 @@
callerPackageName);
synchronized (mLock) {
PackageSetting ps = mSettings.getPackageLPr(packageName);
- if (ps == null) {
- throw new IllegalArgumentException("Unknown target package " + packageName);
- }
- if (shouldFilterApplicationLocked(
+ if (ps == null || shouldFilterApplicationLocked(
ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
throw new IllegalArgumentException("Unknown target package " + packageName);
}
@@ -17853,6 +17882,10 @@
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
mRet = args.copyApk();
}
+ if (mRet == PackageManager.INSTALL_SUCCEEDED) {
+ F2fsUtils.releaseCompressedBlocks(
+ mContext.getContentResolver(), new File(args.getCodePath()));
+ }
if (mParentInstallParams != null) {
mParentInstallParams.tryProcessInstallRequest(args, mRet);
} else {
@@ -17860,7 +17893,6 @@
processInstallRequestsAsync(
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
Collections.singletonList(new InstallRequest(args, res)));
-
}
}
}
@@ -23158,16 +23190,17 @@
if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
return;
}
+ final String[] callerPackageNames = getPackagesForUid(callingUid);
+ if (!ArrayUtils.contains(callerPackageNames, pkg)) {
+ throw new SecurityException("Calling uid " + callingUid
+ + " does not own package " + pkg);
+ }
final int callingUserId = UserHandle.getUserId(callingUid);
PackageInfo pi = getPackageInfo(pkg, 0, callingUserId);
if (pi == null) {
throw new IllegalArgumentException("Unknown package " + pkg + " on user "
+ callingUserId);
}
- if (!UserHandle.isSameApp(pi.applicationInfo.uid, callingUid)) {
- throw new SecurityException("Calling uid " + callingUid
- + " does not own package " + pkg);
- }
}
@Override
@@ -23983,6 +24016,13 @@
final int permission = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
+ if (!allowedByPermission
+ && !ArrayUtils.contains(getPackagesForUid(callingUid), packageName)) {
+ throw new SecurityException(
+ "Permission Denial: attempt to change stopped state from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + callingUid + ", package=" + packageName);
+ }
enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */,
true /* checkShell */, "stop package");
boolean shouldUnhibernate = false;
@@ -23993,8 +24033,7 @@
shouldUnhibernate = true;
}
if (!shouldFilterApplicationLocked(ps, callingUid, userId)
- && mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
- allowedByPermission, callingUid, userId)) {
+ && mSettings.setPackageStoppedStateLPw(this, packageName, stopped, userId)) {
scheduleWritePackageRestrictionsLocked(userId);
}
}
@@ -24235,8 +24274,15 @@
public void systemReady() {
enforceSystemOrRoot("Only the system can claim the system is ready");
- mSystemReady = true;
final ContentResolver resolver = mContext.getContentResolver();
+ if (mReleaseOnSystemReady != null) {
+ for (int i = mReleaseOnSystemReady.size() - 1; i >= 0; --i) {
+ final File dstCodePath = mReleaseOnSystemReady.get(i);
+ F2fsUtils.releaseCompressedBlocks(resolver, dstCodePath);
+ }
+ mReleaseOnSystemReady = null;
+ }
+ mSystemReady = true;
ContentObserver co = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
@@ -26326,7 +26372,7 @@
synchronized (mLock) {
scheduleWritePackageRestrictionsLocked(userId);
scheduleWritePackageListLocked(userId);
- mAppsFilter.onUsersChanged();
+ mAppsFilter.onUserCreated(userId);
}
}
@@ -26421,16 +26467,12 @@
}
synchronized(mLock) {
final AndroidPackage pkg = mPackages.get(packageName);
- if (pkg == null) {
+ if (pkg == null
+ || shouldFilterApplicationLocked(getPackageSetting(pkg.getPackageName()),
+ Binder.getCallingUid(), UserHandle.getCallingUserId())) {
Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- final PackageSetting ps = getPackageSetting(pkg.getPackageName());
- if (shouldFilterApplicationLocked(
- ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
- Slog.w(TAG, "KeySet requested for filtered package: " + packageName);
- throw new IllegalArgumentException("Unknown package: " + packageName);
- }
final KeySetManagerService ksms = mSettings.getKeySetManagerService();
return new KeySet(ksms.getKeySetByAliasAndPackageNameLPr(packageName, alias));
}
@@ -26445,14 +26487,10 @@
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
final AndroidPackage pkg = mPackages.get(packageName);
- if (pkg == null) {
- Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
- throw new IllegalArgumentException("Unknown package: " + packageName);
- }
- final PackageSetting ps = getPackageSetting(pkg.getPackageName());
- if (shouldFilterApplicationLocked(ps, callingUid, callingUserId)) {
- // filter and pretend the package doesn't exist
- Slog.w(TAG, "KeySet requested for filtered package: " + packageName
+ if (pkg == null
+ || shouldFilterApplicationLocked(getPackageSetting(pkg.getPackageName()),
+ callingUid, callingUserId)) {
+ Slog.w(TAG, "KeySet requested for unknown package: " + packageName
+ ", uid:" + callingUid);
throw new IllegalArgumentException("Unknown package: " + packageName);
}
@@ -27892,7 +27930,7 @@
@Override
public List<String> getMimeGroup(String packageName, String mimeGroup) {
- return PackageManagerService.this.getMimeGroup(packageName, mimeGroup);
+ return PackageManagerService.this.getMimeGroupInternal(packageName, mimeGroup);
}
@Override
@@ -28391,14 +28429,14 @@
}
}
- void deleteOatArtifactsOfPackage(String packageName) {
+ long deleteOatArtifactsOfPackage(String packageName) {
final AndroidPackage pkg;
final PackageSetting pkgSetting;
synchronized (mLock) {
pkg = mPackages.get(packageName);
pkgSetting = mSettings.getPackageLPr(packageName);
}
- mDexManager.deleteOptimizedFiles(ArtUtils.createArtPackageInfo(pkg, pkgSetting));
+ return mDexManager.deleteOptimizedFiles(ArtUtils.createArtPackageInfo(pkg, pkgSetting));
}
Set<String> getUnusedPackages(long downgradeTimeThresholdMillis) {
@@ -28518,9 +28556,11 @@
@Override
public void setMimeGroup(String packageName, String mimeGroup, List<String> mimeTypes) {
- boolean changed = mSettings.getPackageLPr(packageName)
- .setMimeGroup(mimeGroup, mimeTypes);
-
+ enforceOwnerRights(packageName, Binder.getCallingUid());
+ final boolean changed;
+ synchronized (mLock) {
+ changed = mSettings.getPackageLPr(packageName).setMimeGroup(mimeGroup, mimeTypes);
+ }
if (changed) {
applyMimeGroupChanges(packageName, mimeGroup);
}
@@ -28528,7 +28568,14 @@
@Override
public List<String> getMimeGroup(String packageName, String mimeGroup) {
- return mSettings.getPackageLPr(packageName).getMimeGroup(mimeGroup);
+ enforceOwnerRights(packageName, Binder.getCallingUid());
+ return getMimeGroupInternal(packageName, mimeGroup);
+ }
+
+ private List<String> getMimeGroupInternal(String packageName, String mimeGroup) {
+ synchronized (mLock) {
+ return mSettings.getPackageLPr(packageName).getMimeGroup(mimeGroup);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 7aa1c3a..26aebbc 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4188,18 +4188,11 @@
}
boolean setPackageStoppedStateLPw(PackageManagerService pm, String packageName,
- boolean stopped, boolean allowedByPermission, int uid, int userId) {
- int appId = UserHandle.getAppId(uid);
+ boolean stopped, int userId) {
final PackageSetting pkgSetting = mPackages.get(packageName);
if (pkgSetting == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- if (!allowedByPermission && (appId != pkgSetting.appId)) {
- throw new SecurityException(
- "Permission Denial: attempt to change stopped state from pid="
- + Binder.getCallingPid()
- + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
- }
if (DEBUG_STOPPED) {
if (stopped) {
RuntimeException e = new RuntimeException("here");
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index b7a069e..47cce9f 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -52,6 +52,14 @@
]
},
{
+ "name": "GtsContentTestCases",
+ "options": [
+ {
+ "include-filter": "com.google.android.content.gts"
+ }
+ ]
+ },
+ {
"name": "GtsSecurityHostTestCases",
"options": [
{
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e8897ca..d4feb3a 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3902,6 +3902,17 @@
isFirstBoot, isUpgrade, existingPackages);
}
+ @Override
+ public String[] getPreInstallableSystemPackages(@NonNull String userType) {
+ checkManageOrCreateUsersPermission("getPreInstallableSystemPackages");
+ final Set<String> installableSystemPackages =
+ mSystemPackageInstaller.getInstallablePackagesForUserType(userType);
+ if (installableSystemPackages == null) {
+ return null;
+ }
+ return installableSystemPackages.toArray(new String[installableSystemPackages.size()]);
+ }
+
private long getCreationTime() {
final long now = System.currentTimeMillis();
return (now > EPOCH_PLUS_30_YEARS) ? now : 0;
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 32ba26c..5820489 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -1034,18 +1034,26 @@
/**
* Deletes all the optimizations files generated by ART.
+ * This is best effort, and the method will log but not throw errors
+ * for individual deletes
+ *
* @param packageInfo the package information.
+ * @return the number of freed bytes or -1 if there was an error in the process.
*/
- public void deleteOptimizedFiles(ArtPackageInfo packageInfo) {
+ public long deleteOptimizedFiles(ArtPackageInfo packageInfo) {
+ long freedBytes = 0;
+ boolean hadErrors = false;
for (String codePath : packageInfo.getCodePaths()) {
for (String isa : packageInfo.getInstructionSets()) {
try {
- mInstaller.deleteOdex(codePath, isa, packageInfo.getOatDir());
+ freedBytes += mInstaller.deleteOdex(codePath, isa, packageInfo.getOatDir());
} catch (InstallerException e) {
Log.e(TAG, "Failed deleting oat files for " + codePath, e);
+ hadErrors = true;
}
}
}
+ return hadErrors ? -1 : freedBytes;
}
public static class RegisterDexModuleResult {
diff --git a/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java b/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
index e1e6195..f653e4b 100644
--- a/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
+++ b/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
@@ -30,6 +30,9 @@
"RssAnon:",
"VmSwap:"
};
+ private static final String[] VMSTAT_KEYS = new String[] {
+ "oom_kill"
+ };
private ProcfsMemoryUtil() {}
@@ -99,4 +102,22 @@
public int anonRssInKilobytes;
public int swapInKilobytes;
}
+
+ /** Reads and parses selected entries of /proc/vmstat. */
+ @Nullable
+ static VmStat readVmStat() {
+ long[] vmstat = new long[VMSTAT_KEYS.length];
+ vmstat[0] = -1;
+ Process.readProcLines("/proc/vmstat", VMSTAT_KEYS, vmstat);
+ if (vmstat[0] == -1) {
+ return null;
+ }
+ VmStat result = new VmStat();
+ result.oomKillCount = (int) vmstat[0];
+ return result;
+ }
+
+ static final class VmStat {
+ public int oomKillCount;
+ }
}
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 dc868b3..cd0ce2b 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -544,6 +544,8 @@
return pullProcessDmabufMemory(atomTag, data);
case FrameworkStatsLog.SYSTEM_MEMORY:
return pullSystemMemory(atomTag, data);
+ case FrameworkStatsLog.VMSTAT:
+ return pullVmStat(atomTag, data);
case FrameworkStatsLog.TEMPERATURE:
synchronized (mTemperatureLock) {
return pullTemperatureLocked(atomTag, data);
@@ -842,6 +844,7 @@
registerProcessSystemIonHeapSize();
registerSystemMemory();
registerProcessDmabufMemory();
+ registerVmStat();
registerTemperature();
registerCoolingDevice();
registerBinderCallsStats();
@@ -2273,6 +2276,27 @@
return StatsManager.PULL_SUCCESS;
}
+ private void registerVmStat() {
+ int tagId = FrameworkStatsLog.VMSTAT;
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl
+ );
+ }
+
+ int pullVmStat(int atomTag, List<StatsEvent> pulledData) {
+ ProcfsMemoryUtil.VmStat vmStat = ProcfsMemoryUtil.readVmStat();
+ if (vmStat != null) {
+ pulledData.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ vmStat.oomKillCount));
+ }
+ return StatsManager.PULL_SUCCESS;
+ }
+
private void registerTemperature() {
int tagId = FrameworkStatsLog.TEMPERATURE;
mStatsManager.setPullAtomCallback(
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 2f0ed19..79706ea 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -723,6 +723,12 @@
* VibrationAttributes.USAGE_* values.
*/
private boolean shouldCancelVibration(VibrationAttributes attrs, int usageFilter) {
+ if (attrs.getUsage() == VibrationAttributes.USAGE_UNKNOWN) {
+ // Special case, usage UNKNOWN would match all filters. Instead it should only match if
+ // it's cancelling that usage specifically, or if cancelling all usages.
+ return usageFilter == VibrationAttributes.USAGE_UNKNOWN
+ || usageFilter == VibrationAttributes.USAGE_FILTER_MATCH_ALL;
+ }
return (usageFilter & attrs.getUsage()) == attrs.getUsage();
}
@@ -1535,7 +1541,7 @@
}
private int runCancel() {
- cancelVibrate(/* usageFilter= */ -1, mToken);
+ cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, mToken);
return 0;
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 71e31c3..ac0665a 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -703,7 +703,7 @@
Slog.i(LOG_TAG, "Rotation: " + Surface.rotationToString(rotation)
+ " displayId: " + displayContent.getDisplayId());
}
- mMagnifedViewport.onRotationChanged(displayContent.getPendingTransaction());
+ mMagnifedViewport.onRotationChanged();
mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_ROTATION_CHANGED);
}
@@ -858,7 +858,7 @@
private final RectF mTempRectF = new RectF();
- private final Point mTempPoint = new Point();
+ private final Point mScreenSize = new Point();
private final Matrix mTempMatrix = new Matrix();
@@ -887,8 +887,8 @@
if (mDisplayContext.getResources().getConfiguration().isScreenRound()) {
mCircularPath = new Path();
- mDisplay.getRealSize(mTempPoint);
- final int centerXY = mTempPoint.x / 2;
+ mDisplay.getRealSize(mScreenSize);
+ final int centerXY = mScreenSize.x / 2;
mCircularPath.addCircle(centerXY, centerXY, centerXY, Path.Direction.CW);
} else {
mCircularPath = null;
@@ -917,9 +917,9 @@
}
void recomputeBounds() {
- mDisplay.getRealSize(mTempPoint);
- final int screenWidth = mTempPoint.x;
- final int screenHeight = mTempPoint.y;
+ mDisplay.getRealSize(mScreenSize);
+ final int screenWidth = mScreenSize.x;
+ final int screenHeight = mScreenSize.y;
mMagnificationRegion.set(0, 0, 0, 0);
final Region availableBounds = mTempRegion1;
@@ -1052,7 +1052,7 @@
|| windowType == TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
}
- void onRotationChanged(SurfaceControl.Transaction t) {
+ void onRotationChanged() {
// If we are showing the magnification border, hide it immediately so
// the user does not see strange artifacts during rotation. The screenshot
// used for rotation already has the border. After the rotation is complete
@@ -1066,7 +1066,7 @@
mHandler.sendMessageDelayed(message, delay);
}
recomputeBounds();
- mWindow.updateSize(t);
+ mWindow.updateSize();
}
void setMagnifiedRegionBorderShown(boolean shown, boolean animate) {
@@ -1148,9 +1148,9 @@
/* ignore */
}
mSurfaceControl = surfaceControl;
- mDisplay.getRealSize(mTempPoint);
+ mDisplay.getRealSize(mScreenSize);
mBlastBufferQueue = new BLASTBufferQueue(SURFACE_TITLE, mSurfaceControl,
- mTempPoint.x, mTempPoint.y, PixelFormat.RGBA_8888);
+ mScreenSize.x, mScreenSize.y, PixelFormat.RGBA_8888);
final SurfaceControl.Transaction t = mService.mTransactionFactory.get();
final int layer =
@@ -1224,10 +1224,11 @@
}
}
- void updateSize(SurfaceControl.Transaction t) {
+ void updateSize() {
synchronized (mService.mGlobalLock) {
- mDisplay.getRealSize(mTempPoint);
- t.setBufferSize(mSurfaceControl, mTempPoint.x, mTempPoint.y);
+ mDisplay.getRealSize(mScreenSize);
+ mBlastBufferQueue.update(mSurfaceControl, mScreenSize.x, mScreenSize.y,
+ PixelFormat.RGBA_8888);
invalidate(mDirtyRect);
}
}
@@ -1296,8 +1297,8 @@
pw.println(prefix
+ " mBounds= " + mBounds
+ " mDirtyRect= " + mDirtyRect
- + " mWidth= " + mSurfaceControl.getWidth()
- + " mHeight= " + mSurfaceControl.getHeight());
+ + " mWidth= " + mScreenSize.x
+ + " mHeight= " + mScreenSize.y);
}
private final class AnimationController extends Handler {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 64401bb..2cebc3b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4594,7 +4594,7 @@
if (visible) {
displayContent.mOpeningApps.add(this);
mEnteringAnimation = true;
- } else {
+ } else if (mVisible) {
displayContent.mClosingApps.add(this);
mEnteringAnimation = false;
}
@@ -7530,10 +7530,6 @@
if (getUid() == SYSTEM_UID) {
return false;
}
- // Do not sandbox to activity window bounds if the feature is disabled.
- if (mDisplayContent != null && !mDisplayContent.sandboxDisplayApis()) {
- return false;
- }
// Never apply sandboxing to an app that should be explicitly excluded from the config.
if (info != null && info.neverSandboxDisplayApis()) {
return false;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 81992d8..e0bae9d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -358,13 +358,6 @@
boolean mIsSizeForced = false;
/**
- * Overridden display size and metrics to activity window bounds. Set via
- * "adb shell wm set-sandbox-display-apis". Default to true, since only disable for debugging.
- * @see WindowManagerService#setSandboxDisplayApis(int, boolean)
- */
- private boolean mSandboxDisplayApis = true;
-
- /**
* Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity}
* but can be set from Settings or via shell command "adb shell wm density".
* @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
@@ -5810,21 +5803,6 @@
return true;
}
- /**
- * Sets if Display APIs should be sandboxed to the activity window bounds.
- */
- void setSandboxDisplayApis(boolean sandboxDisplayApis) {
- mSandboxDisplayApis = sandboxDisplayApis;
- }
-
- /**
- * Returns {@code true} is Display APIs should be sandboxed to the activity window bounds,
- * {@code false} otherwise. Default to true, unless set for debugging purposes.
- */
- boolean sandboxDisplayApis() {
- return mSandboxDisplayApis;
- }
-
/** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */
class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 977df93..97c19ab 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1771,7 +1771,7 @@
}
// Voice interaction overrides both top fullscreen and top docked.
- if (affectsSystemUi && attrs.type == TYPE_VOICE_INTERACTION) {
+ if (affectsSystemUi && attrs.type == TYPE_VOICE_INTERACTION && attrs.isFullscreen()) {
if (mTopFullscreenOpaqueWindowState == null) {
mTopFullscreenOpaqueWindowState = win;
if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 6f2f698..8c781a1 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -394,10 +394,23 @@
/**
* Called when the current input focus changes.
*/
- private void updateInputFocusRequest() {
+ private void updateInputFocusRequest(InputConsumerImpl recentsAnimationInputConsumer) {
final WindowState focus = mDisplayContent.mCurrentFocus;
- final IBinder focusToken = focus != null ? focus.mInputChannelToken : null;
+ // Request focus for the recents animation input consumer if an input consumer should
+ // be applied for the window.
+ if (recentsAnimationInputConsumer != null && focus != null) {
+ final RecentsAnimationController recentsAnimationController =
+ mService.getRecentsAnimationController();
+ final boolean shouldApplyRecentsInputConsumer = recentsAnimationController != null
+ && recentsAnimationController.shouldApplyInputConsumer(focus.mActivityRecord);
+ if (shouldApplyRecentsInputConsumer) {
+ requestFocus(recentsAnimationInputConsumer.mWindowHandle.token,
+ recentsAnimationInputConsumer.mName);
+ return;
+ }
+ }
+ final IBinder focusToken = focus != null ? focus.mInputChannelToken : null;
if (focusToken == null) {
mInputFocus = null;
return;
@@ -474,8 +487,6 @@
boolean mInDrag;
- private boolean mRecentsAnimationFocusOverride;
-
private void updateInputWindows(boolean inDrag) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateInputWindows");
@@ -491,16 +502,8 @@
mInDrag = inDrag;
resetInputConsumers(mInputTransaction);
- mRecentsAnimationFocusOverride = false;
mDisplayContent.forAllWindows(this, true /* traverseTopToBottom */);
-
- if (mRecentsAnimationFocusOverride) {
- requestFocus(mRecentsAnimationInputConsumer.mWindowHandle.token,
- mRecentsAnimationInputConsumer.mName);
- } else {
- updateInputFocusRequest();
- }
-
+ updateInputFocusRequest(mRecentsAnimationInputConsumer);
if (!mUpdateInputWindowsImmediately) {
mDisplayContent.getPendingTransaction().merge(mInputTransaction);
@@ -538,7 +541,6 @@
mRecentsAnimationInputConsumer.mWindowHandle)) {
mRecentsAnimationInputConsumer.show(mInputTransaction, w.mActivityRecord);
mAddRecentsAnimationInputConsumerHandle = false;
- mRecentsAnimationFocusOverride = true;
}
}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 0112f79..f8238c1 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -48,6 +48,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
+import android.view.Display;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -163,16 +164,27 @@
aodShowing ? 1 : 0,
mKeyguardGoingAway ? 1 : 0,
"setKeyguardShown");
+
+ // Update the task snapshot if the screen will not be turned off. To make sure that the
+ // unlocking animation can animate consistent content. The conditions are:
+ // - Either AOD or keyguard changes to be showing. So if the states change individually,
+ // the later one can be skipped to avoid taking snapshot again. While it still accepts
+ // if both of them change to show at the same time.
+ // - Keyguard was not going away. Because if it was, the closing transition is able to
+ // handle the snapshot.
+ // - The display state is ON. Because if AOD is not on or pulsing, the display state will
+ // be OFF or DOZE (the path of screen off may have handled it).
+ if (((aodShowing ^ keyguardShowing) || (aodShowing && aodChanged && keyguardChanged))
+ && !mKeyguardGoingAway && Display.isOnState(
+ mRootWindowContainer.getDefaultDisplay().getDisplayInfo().state)) {
+ mWindowManager.mTaskSnapshotController.snapshotForSleeping(DEFAULT_DISPLAY);
+ }
+
mKeyguardShowing = keyguardShowing;
mAodShowing = aodShowing;
if (aodChanged) {
// Ensure the new state takes effect.
mWindowManager.mWindowPlacerLocked.performSurfacePlacement();
- // If the device can enter AOD and keyguard at the same time, the screen will not be
- // turned off, so the snapshot needs to be refreshed when these states are changed.
- if (aodShowing && keyguardShowing && keyguardChanged) {
- mWindowManager.mTaskSnapshotController.snapshotForSleeping(DEFAULT_DISPLAY);
- }
}
if (keyguardChanged) {
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index eb7087c..7174e68 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -21,6 +21,7 @@
import android.graphics.Color;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -104,20 +105,12 @@
* com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio} will be ignored and
* the framework implementation will be used to determine the aspect ratio.
*/
+ @VisibleForTesting
void setFixedOrientationLetterboxAspectRatio(float aspectRatio) {
mFixedOrientationLetterboxAspectRatio = aspectRatio;
}
/**
- * Resets the aspect ratio of letterbox for fixed orientation to {@link
- * com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio}.
- */
- void resetFixedOrientationLetterboxAspectRatio() {
- mFixedOrientationLetterboxAspectRatio = mContext.getResources().getFloat(
- com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio);
- }
-
- /**
* Gets the aspect ratio of letterbox for fixed orientation.
*/
float getFixedOrientationLetterboxAspectRatio() {
@@ -125,25 +118,6 @@
}
/**
- * Overrides corners raidus for activities presented in the letterbox mode. If given value < 0,
- * both it and a value of {@link
- * com.android.internal.R.integer.config_letterboxActivityCornersRadius} will be ignored and
- * and corners of the activity won't be rounded.
- */
- void setLetterboxActivityCornersRadius(int cornersRadius) {
- mLetterboxActivityCornersRadius = cornersRadius;
- }
-
- /**
- * Resets corners raidus for activities presented in the letterbox mode to {@link
- * com.android.internal.R.integer.config_letterboxActivityCornersRadius}.
- */
- void resetLetterboxActivityCornersRadius() {
- mLetterboxActivityCornersRadius = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_letterboxActivityCornersRadius);
- }
-
- /**
* Whether corners of letterboxed activities are rounded.
*/
boolean isLetterboxActivityCornersRounded() {
@@ -166,25 +140,6 @@
return mLetterboxBackgroundColor;
}
-
- /**
- * Sets color of letterbox background which is used when {@link
- * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as
- * fallback for other backfround types.
- */
- void setLetterboxBackgroundColor(Color color) {
- mLetterboxBackgroundColor = color;
- }
-
- /**
- * Resets color of letterbox background to {@link
- * com.android.internal.R.color.config_letterboxBackgroundColor}.
- */
- void resetLetterboxBackgroundColor() {
- mLetterboxBackgroundColor = Color.valueOf(mContext.getResources().getColor(
- com.android.internal.R.color.config_letterboxBackgroundColor));
- }
-
/**
* Gets {@link LetterboxBackgroundType} specified in {@link
* com.android.internal.R.integer.config_letterboxBackgroundType} or over via ADB command.
@@ -194,19 +149,6 @@
return mLetterboxBackgroundType;
}
- /** Sets letterbox background type. */
- void setLetterboxBackgroundType(@LetterboxBackgroundType int backgroundType) {
- mLetterboxBackgroundType = backgroundType;
- }
-
- /**
- * Resets cletterbox background type to {@link
- * com.android.internal.R.integer.config_letterboxBackgroundType}.
- */
- void resetLetterboxBackgroundType() {
- mLetterboxBackgroundType = readLetterboxBackgroundTypeFromConfig(mContext);
- }
-
/** Returns a string representing the given {@link LetterboxBackgroundType}. */
static String letterboxBackgroundTypeToString(
@LetterboxBackgroundType int backgroundType) {
@@ -236,27 +178,6 @@
}
/**
- * Overrides alpha of a black scrim shown over wallpaper for {@link
- * #LETTERBOX_BACKGROUND_WALLPAPER} option in {@link mLetterboxBackgroundType}.
- *
- * <p>If given value is < 0 or >= 1, both it and a value of {@link
- * com.android.internal.R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha} are ignored
- * and 0.0 (transparent) is instead.
- */
- void setLetterboxBackgroundWallpaperDarkScrimAlpha(float alpha) {
- mLetterboxBackgroundWallpaperDarkScrimAlpha = alpha;
- }
-
- /**
- * Resets alpha of a black scrim shown over wallpaper letterbox background to {@link
- * com.android.internal.R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha}.
- */
- void resetLetterboxBackgroundWallpaperDarkScrimAlpha() {
- mLetterboxBackgroundWallpaperDarkScrimAlpha = mContext.getResources().getFloat(
- com.android.internal.R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha);
- }
-
- /**
* Gets alpha of a black scrim shown over wallpaper letterbox background.
*/
float getLetterboxBackgroundWallpaperDarkScrimAlpha() {
@@ -264,28 +185,6 @@
}
/**
- * Overrides blur radius for {@link #LETTERBOX_BACKGROUND_WALLPAPER} option in
- * {@link mLetterboxBackgroundType}.
- *
- * <p> If given value <= 0, both it and a value of {@link
- * com.android.internal.R.dimen.config_letterboxBackgroundWallpaperBlurRadius} are ignored
- * and 0 is used instead.
- */
- void setLetterboxBackgroundWallpaperBlurRadius(int radius) {
- mLetterboxBackgroundWallpaperBlurRadius = radius;
- }
-
- /**
- * Resets blur raidus for {@link #LETTERBOX_BACKGROUND_WALLPAPER} option in {@link
- * mLetterboxBackgroundType} to {@link
- * com.android.internal.R.dimen.config_letterboxBackgroundWallpaperBlurRadius}.
- */
- void resetLetterboxBackgroundWallpaperBlurRadius() {
- mLetterboxBackgroundWallpaperBlurRadius = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.config_letterboxBackgroundWallpaperBlurRadius);
- }
-
- /**
* Gets blur raidus for {@link #LETTERBOX_BACKGROUND_WALLPAPER} option in {@link
* mLetterboxBackgroundType}.
*/
@@ -312,17 +211,9 @@
* com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier} are ignored and
* central position (0.5) is used.
*/
+ @VisibleForTesting
void setLetterboxHorizontalPositionMultiplier(float multiplier) {
mLetterboxHorizontalPositionMultiplier = multiplier;
}
- /**
- * Resets horizontal position of a center of the letterboxed app window to {@link
- * com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier}.
- */
- void resetLetterboxHorizontalPositionMultiplier() {
- mLetterboxHorizontalPositionMultiplier = mContext.getResources().getFloat(
- com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier);
- }
-
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6d51849..e9dd521 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5391,25 +5391,6 @@
}
}
- void setSandboxDisplayApis(int displayId, boolean sandboxDisplayApis) {
- if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
- }
-
- final long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mGlobalLock) {
- final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
- if (displayContent != null) {
- displayContent.setSandboxDisplayApis(sandboxDisplayApis);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
/** The global settings only apply to default display. */
private boolean applyForcedPropertiesForDefaultDisplay() {
boolean changed = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index d5965494..a94fd07 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -19,12 +19,6 @@
import static android.os.Build.IS_USER;
import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED;
-import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
-import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
-import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR;
-import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER;
-
-import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.ParcelFileDescriptor;
@@ -42,7 +36,6 @@
import com.android.internal.protolog.ProtoLogImpl;
import com.android.server.LocalServices;
import com.android.server.statusbar.StatusBarManagerInternal;
-import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType;
import java.io.IOException;
import java.io.PrintWriter;
@@ -65,12 +58,10 @@
// Internal service impl -- must perform security checks before touching.
private final WindowManagerService mInternal;
- private final LetterboxConfiguration mLetterboxConfiguration;
public WindowManagerShellCommand(WindowManagerService service) {
mInterface = service;
mInternal = service;
- mLetterboxConfiguration = service.mLetterboxConfiguration;
}
@Override
@@ -122,14 +113,6 @@
return runGetIgnoreOrientationRequest(pw);
case "dump-visible-window-views":
return runDumpVisibleWindowViews(pw);
- case "set-letterbox-style":
- return runSetLetterboxStyle(pw);
- case "get-letterbox-style":
- return runGetLetterboxStyle(pw);
- case "reset-letterbox-style":
- return runResetLetterboxStyle(pw);
- case "set-sandbox-display-apis":
- return runSandboxDisplayApis(pw);
case "set-multi-window-config":
return runSetMultiWindowConfig();
case "get-multi-window-config":
@@ -348,37 +331,6 @@
return 0;
}
- /**
- * Override display size and metrics to reflect the DisplayArea of the calling activity.
- */
- private int runSandboxDisplayApis(PrintWriter pw) throws RemoteException {
- int displayId = Display.DEFAULT_DISPLAY;
- String arg = getNextArgRequired();
- if ("-d".equals(arg)) {
- displayId = Integer.parseInt(getNextArgRequired());
- arg = getNextArgRequired();
- }
-
- final boolean sandboxDisplayApis;
- switch (arg) {
- case "true":
- case "1":
- sandboxDisplayApis = true;
- break;
- case "false":
- case "0":
- sandboxDisplayApis = false;
- break;
- default:
- getErrPrintWriter().println("Error: expecting true, 1, false, 0, but we "
- + "get " + arg);
- return -1;
- }
-
- mInternal.setSandboxDisplayApis(displayId, sandboxDisplayApis);
- return 0;
- }
-
private int runDismissKeyguard(PrintWriter pw) throws RemoteException {
mInterface.dismissKeyguard(null /* callback */, null /* message */);
return 0;
@@ -596,231 +548,6 @@
return 0;
}
- private int runSetFixedOrientationLetterboxAspectRatio(PrintWriter pw) throws RemoteException {
- final float aspectRatio;
- try {
- String arg = getNextArgRequired();
- aspectRatio = Float.parseFloat(arg);
- } catch (NumberFormatException e) {
- getErrPrintWriter().println("Error: bad aspect ratio format " + e);
- return -1;
- } catch (IllegalArgumentException e) {
- getErrPrintWriter().println(
- "Error: 'reset' or aspect ratio should be provided as an argument " + e);
- return -1;
- }
- synchronized (mInternal.mGlobalLock) {
- mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(aspectRatio);
- }
- return 0;
- }
-
- private int runSetLetterboxActivityCornersRadius(PrintWriter pw) throws RemoteException {
- final int cornersRadius;
- try {
- String arg = getNextArgRequired();
- cornersRadius = Integer.parseInt(arg);
- } catch (NumberFormatException e) {
- getErrPrintWriter().println("Error: bad corners radius format " + e);
- return -1;
- } catch (IllegalArgumentException e) {
- getErrPrintWriter().println(
- "Error: 'reset' or corners radius should be provided as an argument " + e);
- return -1;
- }
- synchronized (mInternal.mGlobalLock) {
- mLetterboxConfiguration.setLetterboxActivityCornersRadius(cornersRadius);
- }
- return 0;
- }
-
- private int runSetLetterboxBackgroundType(PrintWriter pw) throws RemoteException {
- @LetterboxBackgroundType final int backgroundType;
- try {
- String arg = getNextArgRequired();
- switch (arg) {
- case "solid_color":
- backgroundType = LETTERBOX_BACKGROUND_SOLID_COLOR;
- break;
- case "app_color_background":
- backgroundType = LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
- break;
- case "app_color_background_floating":
- backgroundType = LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
- break;
- case "wallpaper":
- backgroundType = LETTERBOX_BACKGROUND_WALLPAPER;
- break;
- default:
- getErrPrintWriter().println(
- "Error: 'reset', 'solid_color', 'app_color_background' or "
- + "'wallpaper' should be provided as an argument");
- return -1;
- }
- } catch (IllegalArgumentException e) {
- getErrPrintWriter().println(
- "Error: 'reset', 'solid_color', 'app_color_background' or "
- + "'wallpaper' should be provided as an argument" + e);
- return -1;
- }
- synchronized (mInternal.mGlobalLock) {
- mLetterboxConfiguration.setLetterboxBackgroundType(backgroundType);
- }
- return 0;
- }
-
- private int runSetLetterboxBackgroundColor(PrintWriter pw) throws RemoteException {
- final Color color;
- try {
- String arg = getNextArgRequired();
- color = Color.valueOf(Color.parseColor(arg));
- } catch (IllegalArgumentException e) {
- getErrPrintWriter().println(
- "Error: 'reset' or color in #RRGGBB format should be provided as "
- + "an argument " + e);
- return -1;
- }
- synchronized (mInternal.mGlobalLock) {
- mLetterboxConfiguration.setLetterboxBackgroundColor(color);
- }
- return 0;
- }
-
- private int runSetLetterboxBackgroundWallpaperBlurRadius(PrintWriter pw)
- throws RemoteException {
- final int radius;
- try {
- String arg = getNextArgRequired();
- radius = Integer.parseInt(arg);
- } catch (NumberFormatException e) {
- getErrPrintWriter().println("Error: blur radius format " + e);
- return -1;
- } catch (IllegalArgumentException e) {
- getErrPrintWriter().println(
- "Error: 'reset' or blur radius should be provided as an argument " + e);
- return -1;
- }
- synchronized (mInternal.mGlobalLock) {
- mLetterboxConfiguration.setLetterboxBackgroundWallpaperBlurRadius(radius);
- }
- return 0;
- }
-
- private int runSetLetterboxBackgroundWallpaperDarkScrimAlpha(PrintWriter pw)
- throws RemoteException {
- final float alpha;
- try {
- String arg = getNextArgRequired();
- alpha = Float.parseFloat(arg);
- } catch (NumberFormatException e) {
- getErrPrintWriter().println("Error: bad alpha format " + e);
- return -1;
- } catch (IllegalArgumentException e) {
- getErrPrintWriter().println(
- "Error: 'reset' or alpha should be provided as an argument " + e);
- return -1;
- }
- synchronized (mInternal.mGlobalLock) {
- mLetterboxConfiguration.setLetterboxBackgroundWallpaperDarkScrimAlpha(alpha);
- }
- return 0;
- }
-
- private int runSeLetterboxHorizontalPositionMultiplier(PrintWriter pw) throws RemoteException {
- final float multiplier;
- try {
- String arg = getNextArgRequired();
- multiplier = Float.parseFloat(arg);
- } catch (NumberFormatException e) {
- getErrPrintWriter().println("Error: bad multiplier format " + e);
- return -1;
- } catch (IllegalArgumentException e) {
- getErrPrintWriter().println(
- "Error: 'reset' or multiplier should be provided as an argument " + e);
- return -1;
- }
- synchronized (mInternal.mGlobalLock) {
- mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(multiplier);
- }
- return 0;
- }
-
- private int runSetLetterboxStyle(PrintWriter pw) throws RemoteException {
- if (peekNextArg() == null) {
- getErrPrintWriter().println("Error: No arguments provided.");
- }
- while (peekNextArg() != null) {
- String arg = getNextArg();
- switch (arg) {
- case "--aspectRatio":
- runSetFixedOrientationLetterboxAspectRatio(pw);
- break;
- case "--cornerRadius":
- runSetLetterboxActivityCornersRadius(pw);
- break;
- case "--backgroundType":
- runSetLetterboxBackgroundType(pw);
- break;
- case "--backgroundColor":
- runSetLetterboxBackgroundColor(pw);
- break;
- case "--wallpaperBlurRadius":
- runSetLetterboxBackgroundWallpaperBlurRadius(pw);
- break;
- case "--wallpaperDarkScrimAlpha":
- runSetLetterboxBackgroundWallpaperDarkScrimAlpha(pw);
- break;
- case "--horizontalPositionMultiplier":
- runSeLetterboxHorizontalPositionMultiplier(pw);
- break;
- default:
- getErrPrintWriter().println(
- "Error: Unrecognized letterbox style option: " + arg);
- return -1;
- }
- }
- return 0;
- }
-
- private int runResetLetterboxStyle(PrintWriter pw) throws RemoteException {
- if (peekNextArg() == null) {
- resetLetterboxStyle();
- }
- synchronized (mInternal.mGlobalLock) {
- while (peekNextArg() != null) {
- String arg = getNextArg();
- switch (arg) {
- case "aspectRatio":
- mLetterboxConfiguration.resetFixedOrientationLetterboxAspectRatio();
- break;
- case "cornerRadius":
- mLetterboxConfiguration.resetLetterboxActivityCornersRadius();
- break;
- case "backgroundType":
- mLetterboxConfiguration.resetLetterboxBackgroundType();
- break;
- case "backgroundColor":
- mLetterboxConfiguration.resetLetterboxBackgroundColor();
- break;
- case "wallpaperBlurRadius":
- mLetterboxConfiguration.resetLetterboxBackgroundWallpaperBlurRadius();
- break;
- case "wallpaperDarkScrimAlpha":
- mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha();
- break;
- case "horizontalPositionMultiplier":
- mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
- break;
- default:
- getErrPrintWriter().println(
- "Error: Unrecognized letterbox style option: " + arg);
- return -1;
- }
- }
- }
- return 0;
- }
-
private int runSetMultiWindowConfig() {
if (peekNextArg() == null) {
getErrPrintWriter().println("Error: No arguments provided.");
@@ -895,40 +622,6 @@
return 0;
}
- private void resetLetterboxStyle() {
- synchronized (mInternal.mGlobalLock) {
- mLetterboxConfiguration.resetFixedOrientationLetterboxAspectRatio();
- mLetterboxConfiguration.resetLetterboxActivityCornersRadius();
- mLetterboxConfiguration.resetLetterboxBackgroundType();
- mLetterboxConfiguration.resetLetterboxBackgroundColor();
- mLetterboxConfiguration.resetLetterboxBackgroundWallpaperBlurRadius();
- mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha();
- mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
- }
- }
-
- private int runGetLetterboxStyle(PrintWriter pw) throws RemoteException {
- synchronized (mInternal.mGlobalLock) {
- pw.println("Corner radius: "
- + mLetterboxConfiguration.getLetterboxActivityCornersRadius());
- pw.println("Horizontal position multiplier: "
- + mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier());
- pw.println("Aspect ratio: "
- + mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio());
-
- pw.println("Background type: "
- + LetterboxConfiguration.letterboxBackgroundTypeToString(
- mLetterboxConfiguration.getLetterboxBackgroundType()));
- pw.println(" Background color: " + Integer.toHexString(
- mLetterboxConfiguration.getLetterboxBackgroundColor().toArgb()));
- pw.println(" Wallpaper blur radius: "
- + mLetterboxConfiguration.getLetterboxBackgroundWallpaperBlurRadius());
- pw.println(" Wallpaper dark scrim alpha: "
- + mLetterboxConfiguration.getLetterboxBackgroundWallpaperDarkScrimAlpha());
- }
- return 0;
- }
-
private int runReset(PrintWriter pw) throws RemoteException {
int displayId = getDisplayId(getNextArg());
@@ -953,12 +646,6 @@
// set-ignore-orientation-request
mInterface.setIgnoreOrientationRequest(displayId, false /* ignoreOrientationRequest */);
- // set-letterbox-style
- resetLetterboxStyle();
-
- // set-sandbox-display-apis
- mInternal.setSandboxDisplayApis(displayId, /* sandboxDisplayApis= */ true);
-
// set-multi-window-config
runResetMultiWindowConfig();
@@ -993,12 +680,7 @@
pw.println(" set-ignore-orientation-request [-d DISPLAY_ID] [true|1|false|0]");
pw.println(" get-ignore-orientation-request [-d DISPLAY_ID] ");
pw.println(" If app requested orientation should be ignored.");
- pw.println(" set-sandbox-display-apis [true|1|false|0]");
- pw.println(" Sets override of Display APIs getRealSize / getRealMetrics to reflect ");
- pw.println(" DisplayArea of the activity, or the window bounds if in letterbox or");
- pw.println(" Size Compat Mode.");
- printLetterboxHelp(pw);
printMultiWindowConfigHelp(pw);
pw.println(" reset [-d DISPLAY_ID]");
@@ -1011,49 +693,6 @@
}
}
- private void printLetterboxHelp(PrintWriter pw) {
- pw.println(" set-letterbox-style");
- pw.println(" Sets letterbox style using the following options:");
- pw.println(" --aspectRatio aspectRatio");
- pw.println(" Aspect ratio of letterbox for fixed orientation. If aspectRatio <= "
- + LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO);
- pw.println(" both it and R.dimen.config_fixedOrientationLetterboxAspectRatio will");
- pw.println(" be ignored and framework implementation will determine aspect ratio.");
- pw.println(" --cornerRadius radius");
- pw.println(" Corners radius for activities in the letterbox mode. If radius < 0,");
- pw.println(" both it and R.integer.config_letterboxActivityCornersRadius will be");
- pw.println(" ignored and corners of the activity won't be rounded.");
- pw.println(" --backgroundType [reset|solid_color|app_color_background");
- pw.println(" |app_color_background_floating|wallpaper]");
- pw.println(" Type of background used in the letterbox mode.");
- pw.println(" --backgroundColor color");
- pw.println(" Color of letterbox which is be used when letterbox background type");
- pw.println(" is 'solid-color'. Use (set)get-letterbox-style to check and control");
- pw.println(" letterbox background type. See Color#parseColor for allowed color");
- pw.println(" formats (#RRGGBB and some colors by name, e.g. magenta or olive).");
- pw.println(" --wallpaperBlurRadius radius");
- pw.println(" Blur radius for 'wallpaper' letterbox background. If radius <= 0");
- pw.println(" both it and R.dimen.config_letterboxBackgroundWallpaperBlurRadius");
- pw.println(" are ignored and 0 is used.");
- pw.println(" --wallpaperDarkScrimAlpha alpha");
- pw.println(" Alpha of a black translucent scrim shown over 'wallpaper'");
- pw.println(" letterbox background. If alpha < 0 or >= 1 both it and");
- pw.println(" R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha are ignored");
- pw.println(" and 0.0 (transparent) is used instead.");
- pw.println(" --horizontalPositionMultiplier multiplier");
- pw.println(" Horizontal position of app window center. If multiplier < 0 or > 1,");
- pw.println(" both it and R.dimen.config_letterboxHorizontalPositionMultiplier");
- pw.println(" are ignored and central position (0.5) is used.");
- pw.println(" reset-letterbox-style [aspectRatio|cornerRadius|backgroundType");
- pw.println(" |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha");
- pw.println(" |horizontalPositionMultiplier]");
- pw.println(" Resets overrides to default values for specified properties separated");
- pw.println(" by space, e.g. 'reset-letterbox-style aspectRatio cornerRadius'.");
- pw.println(" If no arguments provided, all values will be reset.");
- pw.println(" get-letterbox-style");
- pw.println(" Prints letterbox style configuration.");
- }
-
private void printMultiWindowConfigHelp(PrintWriter pw) {
pw.println(" set-multi-window-config");
pw.println(" Sets options to determine if activity should be shown in multi window:");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 1a468d9..07ac73b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5512,7 +5512,19 @@
mSurfacePlacementNeeded = false;
transformFrameToSurfacePosition(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top,
mSurfacePosition);
- mSurfacePosition.offset(mXOffset, mYOffset);
+
+ if (mWallpaperScale != 1f) {
+ DisplayInfo displayInfo = getDisplayInfo();
+ Matrix matrix = mTmpMatrix;
+ matrix.setTranslate(mXOffset, mYOffset);
+ matrix.postScale(mWallpaperScale, mWallpaperScale, displayInfo.logicalWidth / 2f,
+ displayInfo.logicalHeight / 2f);
+ matrix.getValues(mTmpMatrixArray);
+ mSurfacePosition.offset(Math.round(mTmpMatrixArray[Matrix.MTRANS_X]),
+ Math.round(mTmpMatrixArray[Matrix.MTRANS_Y]));
+ } else {
+ mSurfacePosition.offset(mXOffset, mYOffset);
+ }
// Freeze position while we're unrotated, so the surface remains at the position it was
// prior to the rotation.
diff --git a/services/core/jni/com_android_server_sensor_SensorService.cpp b/services/core/jni/com_android_server_sensor_SensorService.cpp
index d0f56e6..63b7dfb 100644
--- a/services/core/jni/com_android_server_sensor_SensorService.cpp
+++ b/services/core/jni/com_android_server_sensor_SensorService.cpp
@@ -32,6 +32,7 @@
namespace android {
+static JavaVM* sJvm = nullptr;
static jmethodID sMethodIdOnProximityActive;
class NativeSensorService {
@@ -93,8 +94,8 @@
}
void NativeSensorService::ProximityActiveListenerDelegate::onProximityActive(bool isActive) {
- AndroidRuntime::getJNIEnv()->CallVoidMethod(mListener, sMethodIdOnProximityActive,
- static_cast<jboolean>(isActive));
+ auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+ jniEnv->CallVoidMethod(mListener, sMethodIdOnProximityActive, static_cast<jboolean>(isActive));
}
static jlong startSensorServiceNative(JNIEnv* env, jclass, jobject listener) {
@@ -128,7 +129,8 @@
};
-int register_android_server_sensor_SensorService(JNIEnv* env) {
+int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env) {
+ sJvm = vm;
jclass listenerClass = FindClassOrDie(env, PROXIMITY_ACTIVE_CLASS);
sMethodIdOnProximityActive = GetMethodIDOrDie(env, listenerClass, "onProximityActive", "(Z)V");
return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods,
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index b8961d5..ff61abc 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -62,7 +62,7 @@
int register_android_server_FaceService(JNIEnv* env);
int register_android_server_GpuService(JNIEnv* env);
int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env);
-int register_android_server_sensor_SensorService(JNIEnv* env);
+int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env);
};
using namespace android;
@@ -118,6 +118,6 @@
register_android_server_FaceService(env);
register_android_server_GpuService(env);
register_android_server_stats_pull_StatsPullAtomService(env);
- register_android_server_sensor_SensorService(env);
+ register_android_server_sensor_SensorService(vm, env);
return JNI_VERSION_1_4;
}
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index c6dfe9d..3e2e37c 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -129,14 +129,30 @@
<xs:complexType name="sensorDetails">
<xs:sequence>
<xs:element type="xs:string" name="type" minOccurs="0" maxOccurs="1">
- <xs:annotation name="nullable" />
+ <xs:annotation name="nullable"/>
<xs:annotation name="final"/>
</xs:element>
<xs:element type="xs:string" name="name" minOccurs="0" maxOccurs="1">
- <xs:annotation name="nullable" />
+ <xs:annotation name="nullable"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ <xs:element type="refreshRateRange" name="refreshRate" minOccurs="0" maxOccurs="1">
+ <xs:annotation name="nullable"/>
<xs:annotation name="final"/>
</xs:element>
</xs:sequence>
</xs:complexType>
+ <xs:complexType name="refreshRateRange">
+ <xs:sequence>
+ <xs:element type="xs:nonNegativeInteger" name="minimum" minOccurs="1" maxOccurs="1">
+ <xs:annotation name="final"/>
+ </xs:element>
+ <xs:element type="xs:nonNegativeInteger" name="maximum" minOccurs="1" maxOccurs="1">
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+
</xs:schema>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 7c2436d..d40854a 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -65,11 +65,21 @@
method public final void setValue(@NonNull java.math.BigDecimal);
}
+ public class RefreshRateRange {
+ ctor public RefreshRateRange();
+ method public final java.math.BigInteger getMaximum();
+ method public final java.math.BigInteger getMinimum();
+ method public final void setMaximum(java.math.BigInteger);
+ method public final void setMinimum(java.math.BigInteger);
+ }
+
public class SensorDetails {
ctor public SensorDetails();
method @Nullable public final String getName();
+ method @Nullable public final com.android.server.display.config.RefreshRateRange getRefreshRate();
method @Nullable public final String getType();
method public final void setName(@Nullable String);
+ method public final void setRefreshRate(@Nullable com.android.server.display.config.RefreshRateRange);
method public final void setType(@Nullable String);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index fa24e52..25d3769 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -169,6 +169,7 @@
import android.app.admin.DevicePolicyManager.PasswordComplexity;
import android.app.admin.DevicePolicyManager.PersonalAppsSuspensionReason;
import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.DevicePolicyManagerLiteInternal;
import android.app.admin.DevicePolicySafetyChecker;
import android.app.admin.DeviceStateCache;
import android.app.admin.FactoryResetProtectionPolicy;
@@ -1748,6 +1749,8 @@
mTransferOwnershipMetadataManager = mInjector.newTransferOwnershipMetadataManager();
mBugreportCollectionManager = new RemoteBugreportManager(this, mInjector);
+ // "Lite" interface is available even when the device doesn't have the feature
+ LocalServices.addService(DevicePolicyManagerLiteInternal.class, mLocalService);
if (!mHasFeature) {
// Skip the rest of the initialization
mSetupContentObserver = null;
@@ -8027,6 +8030,8 @@
inForeground = true;
receiverComponent = resolveDelegateReceiver(
DELEGATION_SECURITY_LOGGING, action, userId);
+ // STOPSHIP(b/185004808): remove excessive log.
+ Slogf.d(LOG_TAG, "Delegate for security logs broadcast: " + receiverComponent);
}
if (receiverComponent == null) {
receiverComponent = getOwnerComponent(userId);
@@ -12612,7 +12617,8 @@
}
@VisibleForTesting
- final class LocalService extends DevicePolicyManagerInternal {
+ final class LocalService extends DevicePolicyManagerInternal
+ implements DevicePolicyManagerLiteInternal {
private List<OnCrossProfileWidgetProvidersChangeListener> mWidgetProviderListeners;
@Override
@@ -14313,7 +14319,7 @@
}
@Override
- public boolean isAffiliatedUser() {
+ public boolean isCallingUserAffiliated() {
if (!mHasFeature) {
return false;
}
@@ -14323,6 +14329,17 @@
}
}
+ @Override
+ public boolean isAffiliatedUser(@UserIdInt int userId) {
+ if (!mHasFeature) {
+ return false;
+ }
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasCrossUsersPermission(caller, userId));
+
+ return isUserAffiliatedWithDeviceLocked(userId);
+ }
+
private boolean isUserAffiliatedWithDeviceLocked(@UserIdInt int userId) {
if (!mOwners.hasDeviceOwner()) {
return false;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java b/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java
index 86437a2..1cbc634 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java
@@ -21,7 +21,7 @@
import android.app.admin.DevicePolicyManager.DevicePolicyOperation;
import android.app.admin.DevicePolicyManager.OperationSafetyReason;
-import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.DevicePolicyManagerLiteInternal;
import android.app.admin.DevicePolicySafetyChecker;
import android.os.Handler;
import android.os.Looper;
@@ -80,8 +80,8 @@
+ ", should be " + operationToString(mOperation));
}
String reasonName = operationSafetyReasonToString(reason);
- DevicePolicyManagerInternal dpmi = LocalServices
- .getService(DevicePolicyManagerInternal.class);
+ DevicePolicyManagerLiteInternal dpmi = LocalServices
+ .getService(DevicePolicyManagerLiteInternal.class);
Slog.i(TAG, "notifying " + reasonName + " is UNSAFE");
dpmi.notifyUnsafeOperationStateChanged(this, reason, /* isSafe= */ false);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index c29de90..0741c81b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -64,7 +64,7 @@
mLastForceNanos = System.nanoTime();
}
- private static final boolean DEBUG = false; // STOPSHIP if true.
+ private static final boolean DEBUG = true; // STOPSHIP if true.
private static final String TAG = "SecurityLogMonitor";
/**
* Each log entry can hold up to 4K bytes (but as of {@link android.os.Build.VERSION_CODES#N}
@@ -427,7 +427,7 @@
while (!Thread.currentThread().isInterrupted()) {
try {
final boolean force = mForceSemaphore.tryAcquire(POLLING_INTERVAL_MS, MILLISECONDS);
-
+ if (DEBUG) Slog.d(TAG, "Retrieving next batch, force=" + force);
getNextBatch(newLogs);
mLock.lockInterruptibly();
@@ -469,6 +469,11 @@
return;
}
final int logSize = mPendingLogs.size();
+ if (DEBUG) {
+ Slog.d(TAG, String.format(
+ "notifyDeviceOwnerOrProfileOwnerIfNeeded, size: %d now: %d next: %d",
+ logSize, SystemClock.elapsedRealtime(), mNextAllowedRetrievalTimeMillis));
+ }
if (logSize >= BUFFER_ENTRIES_NOTIFICATION_LEVEL || (force && logSize > 0)) {
// Allow DO to retrieve logs if too many pending logs or if forced.
if (!mAllowedToRetrieve) {
@@ -507,6 +512,7 @@
synchronized (mForceSemaphore) {
final long toWaitNanos = mLastForceNanos + FORCE_FETCH_THROTTLE_NS - nowNanos;
if (toWaitNanos > 0) {
+ if (DEBUG) Slog.d(TAG, "Forcing security logs throttled");
return NANOSECONDS.toMillis(toWaitNanos) + 1; // Round up.
}
mLastForceNanos = nowNanos;
@@ -515,6 +521,7 @@
if (mForceSemaphore.availablePermits() == 0) {
mForceSemaphore.release();
}
+ if (DEBUG) Slog.d(TAG, "Forcing security logs semaphore released");
return 0;
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index 21de791..280204d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -2309,12 +2309,14 @@
public void minWindowChangeDisabled() {
mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, false);
final long minWindow = 73;
+ final long futurity = 10_000;
setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
// 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC.
for (int window = 1; window <= minWindow; window++) {
final PendingIntent pi = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME, 0, window, pi, 0, 0, TEST_CALLING_UID, null);
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, pi, 0, 0,
+ TEST_CALLING_UID, null);
assertEquals(1, mService.mAlarmStore.size());
final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0);
@@ -2323,18 +2325,61 @@
}
@Test
+ public void minWindowExempted() {
+ mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, true);
+ final long minWindow = 73;
+ final long futurity = 10_000;
+
+ setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
+
+ final int coreUid = 2312;
+ doReturn(true).when(() -> UserHandle.isCore(coreUid));
+
+ final int allowlisted = 54239;
+ when(mDeviceIdleInternal.isAppOnWhitelist(UserHandle.getAppId(allowlisted))).thenReturn(
+ true);
+
+ for (final int callingUid : new int[]{SYSTEM_UI_UID, coreUid, coreUid}) {
+ // 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC.
+ for (int window = 1; window <= minWindow; window++) {
+ final PendingIntent pi = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, pi, 0, 0,
+ callingUid, null);
+
+ assertEquals(1, mService.mAlarmStore.size());
+ final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0);
+ assertEquals(window, a.windowLength);
+ }
+ }
+
+ // 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC.
+ for (int window = 1; window <= minWindow; window++) {
+ final PendingIntent pi = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, pi, 0, 0,
+ TEST_CALLING_UID, null);
+
+ assertEquals(1, mService.mAlarmStore.size());
+ final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0);
+ assertEquals(minWindow, a.windowLength);
+ }
+ }
+
+ @Test
public void minWindowPriorityAlarm() {
mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, true);
final long minWindow = 73;
+ final long futurity = 10_000;
setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
// 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC.
for (int window = 1; window <= minWindow; window++) {
- setPrioritizedAlarm(ELAPSED_REALTIME, 0, window, new IAlarmListener.Stub() {
- @Override
- public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
- }
- });
+ setPrioritizedAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window,
+ new IAlarmListener.Stub() {
+ @Override
+ public void doAlarm(IAlarmCompleteListener callback)
+ throws RemoteException {
+ }
+ });
assertEquals(1, mService.mAlarmStore.size());
final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0);
assertEquals(window, a.windowLength);
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index e1012a9..0efcc57 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -35,6 +35,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -589,8 +590,8 @@
new DisplayModeDirector.DesiredDisplayModeSpecs(
/*baseModeId*/ baseModeId,
/*allowGroupSwitching*/ false,
- new DisplayModeDirector.RefreshRateRange(60f, 60f),
- new DisplayModeDirector.RefreshRateRange(60f, 60f)
+ new RefreshRateRange(60f, 60f),
+ new RefreshRateRange(60f, 60f)
));
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
verify(mSurfaceControlProxy).setDesiredDisplayModeSpecs(display.token,
@@ -624,8 +625,8 @@
new DisplayModeDirector.DesiredDisplayModeSpecs(
/*baseModeId*/ baseModeId,
/*allowGroupSwitching*/ false,
- new DisplayModeDirector.RefreshRateRange(60f, 60f),
- new DisplayModeDirector.RefreshRateRange(60f, 60f)
+ new RefreshRateRange(60f, 60f),
+ new RefreshRateRange(60f, 60f)
));
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
index 8666fa6..aadaba4 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
@@ -42,6 +42,7 @@
import com.android.compatibility.common.util.SystemUtil;
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
+import com.android.server.appsearch.visibilitystore.VisibilityStore;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -66,6 +67,7 @@
private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
private AppSearchImpl mAppSearchImpl;
+ private VisibilityStore mVisibilityStore;
private int mGlobalQuerierUid;
@Before
@@ -89,13 +91,9 @@
};
// Give ourselves global query permissions
- mAppSearchImpl =
- AppSearchImpl.create(
- mTemporaryFolder.newFolder(),
- mContext,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
-
+ mAppSearchImpl = AppSearchImpl.create(
+ mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
+ mVisibilityStore = VisibilityStore.create(mAppSearchImpl, mContext);
mGlobalQuerierUid =
mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
}
@@ -128,6 +126,7 @@
"package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
+ mVisibilityStore,
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
/*schemasPackageAccessible=*/ ImmutableMap.of(
"schema1",
@@ -136,26 +135,20 @@
/*schemaVersion=*/ 0);
// "schema1" is platform hidden now and package visible to package1
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- mContext.getPackageName(),
- mGlobalQuerierUid))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ mGlobalQuerierUid,
+ /*callerHasSystemAccess=*/ true))
.isFalse();
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- packageNameFoo,
- uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isTrue();
// Add a new schema, and include the already-existing "schema1"
@@ -165,6 +158,7 @@
ImmutableList.of(
new AppSearchSchema.Builder("schema1").build(),
new AppSearchSchema.Builder("schema2").build()),
+ mVisibilityStore,
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
/*schemasPackageAccessible=*/ ImmutableMap.of(
"schema1",
@@ -174,50 +168,40 @@
// Check that "schema1" still has the same visibility settings
SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- mContext.getPackageName(),
- mGlobalQuerierUid))
+ mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ mGlobalQuerierUid,
+ /*callerHasSystemAccess=*/ true))
.isFalse(),
READ_GLOBAL_APP_SEARCH_DATA);
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- packageNameFoo,
- uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isTrue();
// "schema2" has default visibility settings
SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema2",
- mContext.getPackageName(),
- mGlobalQuerierUid))
+ mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema2",
+ mGlobalQuerierUid,
+ /*callerHasSystemAccess=*/ true))
.isTrue(),
READ_GLOBAL_APP_SEARCH_DATA);
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema2",
- packageNameFoo,
- uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema2",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isFalse();
}
@@ -248,6 +232,7 @@
"package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
+ mVisibilityStore,
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
/*schemasPackageAccessible=*/ ImmutableMap.of(
"schema1",
@@ -256,26 +241,20 @@
/*schemaVersion=*/ 0);
// "schema1" is platform hidden now and package accessible
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- mContext.getPackageName(),
- mGlobalQuerierUid))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ mGlobalQuerierUid,
+ /*callerHasSystemAccess=*/ true))
.isFalse();
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- packageNameFoo,
- uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isTrue();
// Remove "schema1" by force overriding
@@ -283,32 +262,27 @@
"package",
"database",
/*schemas=*/ Collections.emptyList(),
+ mVisibilityStore,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ true,
/*schemaVersion=*/ 0);
// Check that "schema1" is no longer considered platform hidden or package accessible
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- mContext.getPackageName(),
- mGlobalQuerierUid))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ mGlobalQuerierUid,
+ /*callerHasSystemAccess=*/ true))
.isTrue();
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- packageNameFoo,
- uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isFalse();
// Add "schema1" back, it gets default visibility settings which means it's not platform
@@ -317,30 +291,25 @@
"package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
+ mVisibilityStore,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*schemaVersion=*/ 0);
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- mContext.getPackageName(),
- mGlobalQuerierUid))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ mGlobalQuerierUid,
+ /*callerHasSystemAccess=*/ true))
.isTrue();
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- packageNameFoo,
- uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isFalse();
}
@@ -357,20 +326,18 @@
"package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+ mVisibilityStore,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*schemaVersion=*/ 0);
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "Schema",
- mContext.getPackageName(),
- mGlobalQuerierUid))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "Schema",
+ mGlobalQuerierUid,
+ /*callerHasSystemAccess=*/ true))
.isTrue();
}
@@ -387,20 +354,18 @@
"package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+ mVisibilityStore,
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("Schema"),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*schemaVersion=*/ 0);
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "Schema",
- mContext.getPackageName(),
- mGlobalQuerierUid))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "Schema",
+ mGlobalQuerierUid,
+ /*callerHasSystemAccess=*/ true))
.isFalse();
}
@@ -418,19 +383,18 @@
"package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+ mVisibilityStore,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*schemaVersion=*/ 0);
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
+ assertThat(mVisibilityStore
.isSchemaSearchableByCaller(
"package",
"database",
prefix + "Schema",
- packageName,
- /*callerUid=*/ 42))
+ /*callerUid=*/ 42,
+ /*callerHasSystemAccess=*/ false))
.isFalse();
}
@@ -458,21 +422,20 @@
"package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+ mVisibilityStore,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ ImmutableMap.of(
"Schema",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
/*forceOverride=*/ false,
/*schemaVersion=*/ 0);
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
+ assertThat(mVisibilityStore
.isSchemaSearchableByCaller(
"package",
"database",
prefix + "Schema",
- packageNameFoo,
- uidFoo))
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isTrue();
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
index 4faffc0..b67ebe4 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
@@ -88,15 +88,10 @@
};
// Give ourselves global query permissions
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- mTemporaryFolder.newFolder(),
- mContext,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
-
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(
+ mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
+ mVisibilityStore = VisibilityStore.create(appSearchImpl, mContext);
mUid = mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
- mVisibilityStore = appSearchImpl.getVisibilityStoreLocked();
}
/**
@@ -122,12 +117,28 @@
}
@Test
+ public void testDoesCallerHaveSystemAccess() {
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
+ assertThat(mVisibilityStore.doesCallerHaveSystemAccess(mContext.getPackageName())).isTrue();
+
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_DENIED);
+ assertThat(mVisibilityStore.doesCallerHaveSystemAccess(mContext.getPackageName()))
+ .isFalse();
+ }
+
+ @Test
public void testSetVisibility_platformSurfaceable() throws Exception {
// Make sure we have global query privileges
PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
when(mockPackageManager
.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
.thenReturn(PERMISSION_GRANTED);
+ assertThat(mVisibilityStore.doesCallerHaveSystemAccess(mContext.getPackageName())).isTrue();
mVisibilityStore.setVisibility(
"package",
@@ -140,16 +151,16 @@
"package",
"database",
"prefix/schema1",
- mContext.getPackageName(),
- mUid))
+ mUid,
+ /*callerHasSystemAccess=*/ true))
.isFalse();
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package",
"database",
"prefix/schema2",
- mContext.getPackageName(),
- mUid))
+ mUid,
+ /*callerHasSystemAccess=*/ true))
.isFalse();
// New .setVisibility() call completely overrides previous visibility settings.
@@ -165,24 +176,24 @@
"package",
"database",
"prefix/schema1",
- mContext.getPackageName(),
- mUid))
+ mUid,
+ /*callerHasSystemAccess=*/ true))
.isFalse();
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package",
"database",
"prefix/schema2",
- mContext.getPackageName(),
- mUid))
+ mUid,
+ /*callerHasSystemAccess=*/ true))
.isTrue();
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package",
"database",
"prefix/schema3",
- mContext.getPackageName(),
- mUid))
+ mUid,
+ /*callerHasSystemAccess=*/ true))
.isFalse();
// Everything defaults to visible again.
@@ -196,24 +207,24 @@
"package",
"database",
"prefix/schema1",
- mContext.getPackageName(),
- mUid))
+ mUid,
+ /*callerHasSystemAccess=*/ true))
.isTrue();
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package",
"database",
"prefix/schema2",
- mContext.getPackageName(),
- mUid))
+ mUid,
+ /*callerHasSystemAccess=*/ true))
.isTrue();
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package",
"database",
"prefix/schema3",
- mContext.getPackageName(),
- mUid))
+ mUid,
+ /*callerHasSystemAccess=*/ true))
.isTrue();
}
@@ -242,13 +253,19 @@
.thenReturn(PERMISSION_DENIED);
// By default, a schema isn't package accessible.
- assertThat(
- mVisibilityStore.isSchemaSearchableByCaller(
- "package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ "prefix/schemaFoo",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isFalse();
- assertThat(
- mVisibilityStore.isSchemaSearchableByCaller(
- "package", "database", "prefix/schemaBar", packageNameBar, uidBar))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ "prefix/schemaBar",
+ uidBar,
+ /*callerHasSystemAccess=*/ false))
.isFalse();
// Grant package access
@@ -268,9 +285,12 @@
when(mockPackageManager.hasSigningCertificate(
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
.thenReturn(false);
- assertThat(
- mVisibilityStore.isSchemaSearchableByCaller(
- "package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ "prefix/schemaFoo",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isFalse();
// Should fail if PackageManager doesn't think the package belongs to the uid
@@ -279,9 +299,12 @@
when(mockPackageManager.hasSigningCertificate(
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
.thenReturn(true);
- assertThat(
- mVisibilityStore.isSchemaSearchableByCaller(
- "package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ "prefix/schemaFoo",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isFalse();
// But if uid and certificate match, then we should have access
@@ -290,9 +313,12 @@
when(mockPackageManager.hasSigningCertificate(
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
.thenReturn(true);
- assertThat(
- mVisibilityStore.isSchemaSearchableByCaller(
- "package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ "prefix/schemaFoo",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isTrue();
when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
@@ -300,9 +326,12 @@
when(mockPackageManager.hasSigningCertificate(
packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
.thenReturn(true);
- assertThat(
- mVisibilityStore.isSchemaSearchableByCaller(
- "package", "database", "prefix/schemaBar", packageNameBar, uidBar))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ "prefix/schemaBar",
+ uidBar,
+ /*callerHasSystemAccess=*/ false))
.isTrue();
// New .setVisibility() call completely overrides previous visibility settings. So
@@ -320,9 +349,12 @@
when(mockPackageManager.hasSigningCertificate(
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
.thenReturn(true);
- assertThat(
- mVisibilityStore.isSchemaSearchableByCaller(
- "package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ "prefix/schemaFoo",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isTrue();
when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
@@ -330,9 +362,12 @@
when(mockPackageManager.hasSigningCertificate(
packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
.thenReturn(true);
- assertThat(
- mVisibilityStore.isSchemaSearchableByCaller(
- "package", "database", "prefix/schemaBar", packageNameBar, uidBar))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ "prefix/schemaBar",
+ uidBar,
+ /*callerHasSystemAccess=*/ false))
.isFalse();
}
@@ -363,9 +398,12 @@
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))));
// If we can't verify the Foo package that has access, assume it doesn't have access.
- assertThat(
- mVisibilityStore.isSchemaSearchableByCaller(
- "package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
+ assertThat(mVisibilityStore.isSchemaSearchableByCaller(
+ "package",
+ "database",
+ "prefix/schemaFoo",
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isFalse();
}
@@ -397,8 +435,8 @@
/*packageName=*/ "",
/*databaseName=*/ "",
"schema",
- mContext.getPackageName(),
- mUid))
+ mUid,
+ /*callerHasSystemAccess=*/ true))
.isTrue();
when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
@@ -411,8 +449,8 @@
/*packageName=*/ "",
/*databaseName=*/ "",
"schema",
- packageNameFoo,
- uidFoo))
+ uidFoo,
+ /*callerHasSystemAccess=*/ false))
.isTrue();
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index e26cfea..f032402 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -83,15 +83,9 @@
@Before
public void setUp() throws Exception {
- Context context = ApplicationProvider.getApplicationContext();
-
- // Give ourselves global query permissions.
mAppSearchImpl =
AppSearchImpl.create(
- mTemporaryFolder.newFolder(),
- context,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
+ mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
}
/**
@@ -149,7 +143,7 @@
.build();
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
- mAppSearchImpl.rewriteSchema(
+ AppSearchImpl.rewriteSchema(
createPrefix("package", "newDatabase"), existingSchemaBuilder, newSchema);
// We rewrote all the new types that were added. And nothing was removed.
@@ -249,7 +243,7 @@
.build();
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
- mAppSearchImpl.rewriteSchema(
+ AppSearchImpl.rewriteSchema(
createPrefix("package", "existingDatabase"),
existingSchemaBuilder,
newSchema);
@@ -284,7 +278,7 @@
.build();
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
- mAppSearchImpl.rewriteSchema(
+ AppSearchImpl.rewriteSchema(
createPrefix("package", "existingDatabase"),
existingSchemaBuilder,
newSchema);
@@ -386,7 +380,7 @@
}
@Test
- public void testRemoveDatabasesFromDocumentThrowsException() throws Exception {
+ public void testRemoveDatabasesFromDocumentThrowsException() {
// Set two different database names in the document, which should never happen
DocumentProto documentProto =
DocumentProto.newBuilder()
@@ -403,7 +397,7 @@
}
@Test
- public void testNestedRemoveDatabasesFromDocumentThrowsException() throws Exception {
+ public void testNestedRemoveDatabasesFromDocumentThrowsException() {
// Set two different database names in the outer and inner document, which should never
// happen.
DocumentProto insideDocument =
@@ -436,6 +430,7 @@
"package",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -473,11 +468,7 @@
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir,
- context,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
+ AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
// Insert schema
List<AppSearchSchema> schemas =
@@ -488,6 +479,7 @@
context.getPackageName(),
"database1",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -506,7 +498,9 @@
/*queryExpression=*/ "",
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
context.getPackageName(),
+ /*visibilityStore=*/ null,
VisibilityStore.NO_OP_UID,
+ /*callerHasSystemAccess=*/ false,
/*logger=*/ null);
assertThat(results.getResults()).hasSize(1);
assertThat(results.getResults().get(0).getGenericDocument()).isEqualTo(validDoc);
@@ -532,18 +526,13 @@
PutResultProto putResultProto = appSearchImpl.mIcingSearchEngineLocked.put(invalidDoc);
assertThat(putResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK);
- // Create a logger for capturing initialization to make sure we are logging the recovery
- // process correctly.
- AppSearchLoggerTest.TestLogger testLogger = new AppSearchLoggerTest.TestLogger();
-
// Initialize AppSearchImpl. This should cause a reset.
+ InitializeStats.Builder initStatsBuilder = new InitializeStats.Builder();
appSearchImpl.close();
- appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, testLogger, ALWAYS_OPTIMIZE);
+ appSearchImpl = AppSearchImpl.create(appsearchDir, initStatsBuilder, ALWAYS_OPTIMIZE);
// Check recovery state
- InitializeStats initStats = testLogger.mInitializeStats;
+ InitializeStats initStats = initStatsBuilder.build();
assertThat(initStats).isNotNull();
assertThat(initStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_INTERNAL_ERROR);
assertThat(initStats.hasDeSync()).isFalse();
@@ -568,7 +557,9 @@
/*queryExpression=*/ "",
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
context.getPackageName(),
+ /*visibilityStore=*/ null,
VisibilityStore.NO_OP_UID,
+ /*callerHasSystemAccess=*/ false,
/*logger=*/ null);
assertThat(results.getResults()).isEmpty();
@@ -577,6 +568,7 @@
context.getPackageName(),
"database1",
Collections.singletonList(new AppSearchSchema.Builder("Type1").build()),
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -592,7 +584,9 @@
/*queryExpression=*/ "",
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
context.getPackageName(),
+ /*visibilityStore=*/ null,
VisibilityStore.NO_OP_UID,
+ /*callerHasSystemAccess=*/ false,
/*logger=*/ null);
assertThat(results.getResults()).hasSize(1);
assertThat(results.getResults().get(0).getGenericDocument()).isEqualTo(validDoc);
@@ -609,6 +603,7 @@
"package",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -642,6 +637,7 @@
"package",
"database1",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -650,6 +646,7 @@
"package",
"database2",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -694,6 +691,7 @@
"package",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -735,6 +733,7 @@
"package1",
"database1",
schema1,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -747,6 +746,7 @@
"package2",
"database2",
schema2,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -789,6 +789,7 @@
"package1",
"database1",
schema1,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -801,6 +802,7 @@
"package2",
"database2",
schema2,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -848,7 +850,9 @@
"",
searchSpec,
/*callerPackageName=*/ "",
+ /*visibilityStore=*/ null,
VisibilityStore.NO_OP_UID,
+ /*callerHasSystemAccess=*/ false,
/*logger=*/ null);
assertThat(searchResultPage.getResults()).isEmpty();
}
@@ -888,6 +892,7 @@
"package",
"database1",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -911,9 +916,6 @@
@Test
public void testSetSchema_incompatible() throws Exception {
- List<SchemaTypeConfigProto> existingSchemas =
- mAppSearchImpl.getSchemaProtoLocked().getTypesList();
-
List<AppSearchSchema> oldSchemas = new ArrayList<>();
oldSchemas.add(
new AppSearchSchema.Builder("Email")
@@ -935,6 +937,7 @@
"package",
"database1",
oldSchemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -950,6 +953,7 @@
"package",
"database1",
newSchemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ true,
@@ -972,6 +976,7 @@
"package",
"database1",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1004,6 +1009,7 @@
"package",
"database1",
finalSchemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1017,6 +1023,7 @@
"package",
"database1",
finalSchemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ true,
@@ -1054,6 +1061,7 @@
"package",
"database1",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1062,6 +1070,7 @@
"package",
"database2",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1101,6 +1110,7 @@
"package",
"database1",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ true,
@@ -1145,6 +1155,7 @@
"package",
"database",
schema,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1206,6 +1217,7 @@
"packageA",
"database",
schema,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1214,6 +1226,7 @@
"packageB",
"database",
schema,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1259,6 +1272,7 @@
"package1",
"database1",
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1272,6 +1286,7 @@
"package1",
"database2",
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1285,6 +1300,7 @@
"package2",
"database1",
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1343,6 +1359,7 @@
"package",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1493,6 +1510,7 @@
"package1",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1515,6 +1533,7 @@
"package1",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1530,6 +1549,7 @@
"package2",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1578,6 +1598,7 @@
"package1",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1600,6 +1621,7 @@
"package1",
"database1",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1621,6 +1643,7 @@
"package1",
"database1",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1629,6 +1652,7 @@
"package1",
"database2",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1664,13 +1688,9 @@
@Test
public void testThrowsExceptionIfClosed() throws Exception {
- Context context = ApplicationProvider.getApplicationContext();
AppSearchImpl appSearchImpl =
AppSearchImpl.create(
- mTemporaryFolder.newFolder(),
- context,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
+ mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
// Initial check that we could do something at first.
List<AppSearchSchema> schemas =
@@ -1679,6 +1699,7 @@
"package",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1689,140 +1710,115 @@
// Check all our public APIs
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.setSchema(
- "package",
- "database",
- schemas,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
- /*forceOverride=*/ false,
- /*version=*/ 0);
- });
+ () ->
+ appSearchImpl.setSchema(
+ "package",
+ "database",
+ schemas,
+ /*visibilityStore=*/ null,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false,
+ /*version=*/ 0));
+
+ expectThrows(
+ IllegalStateException.class, () -> appSearchImpl.getSchema("package", "database"));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.getSchema("package", "database");
- });
+ () ->
+ appSearchImpl.putDocument(
+ "package",
+ "database",
+ new GenericDocument.Builder<>("namespace", "id", "type").build(),
+ /*logger=*/ null));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.putDocument(
- "package",
- "database",
- new GenericDocument.Builder<>("namespace", "id", "type").build(),
- /*logger=*/ null);
- });
+ () ->
+ appSearchImpl.getDocument(
+ "package", "database", "namespace", "id", Collections.emptyMap()));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.getDocument(
- "package", "database", "namespace", "id", Collections.emptyMap());
- });
+ () ->
+ appSearchImpl.query(
+ "package",
+ "database",
+ "query",
+ new SearchSpec.Builder().build(),
+ /*logger=*/ null));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.query(
- "package",
- "database",
- "query",
- new SearchSpec.Builder()
- .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
- .build(),
- /*logger=*/ null);
- });
+ () ->
+ appSearchImpl.globalQuery(
+ "query",
+ new SearchSpec.Builder().build(),
+ "package",
+ /*visibilityStore=*/ null,
+ VisibilityStore.NO_OP_UID,
+ /*callerHasSystemAccess=*/ false,
+ /*logger=*/ null));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.globalQuery(
- "query",
- new SearchSpec.Builder()
- .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
- .build(),
- "package",
- VisibilityStore.NO_OP_UID,
- /*logger=*/ null);
- });
+ () -> appSearchImpl.getNextPage(/*nextPageToken=*/ 1L));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.getNextPage(/*nextPageToken=*/ 1L);
- });
+ () -> appSearchImpl.invalidateNextPageToken(/*nextPageToken=*/ 1L));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.invalidateNextPageToken(/*nextPageToken=*/ 1L);
- });
+ () ->
+ appSearchImpl.reportUsage(
+ "package",
+ "database",
+ "namespace",
+ "id",
+ /*usageTimestampMillis=*/ 1000L,
+ /*systemUsage=*/ false));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.reportUsage(
- "package",
- "database",
- "namespace",
- "id",
- /*usageTimestampMillis=*/ 1000L,
- /*systemUsage=*/ false);
- });
+ () ->
+ appSearchImpl.remove(
+ "package",
+ "database",
+ "namespace",
+ "id",
+ /*removeStatsBuilder=*/ null));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.remove(
- "package", "database", "namespace", "id", /*statsBuilder=*/ null);
- });
+ () ->
+ appSearchImpl.removeByQuery(
+ "package",
+ "database",
+ "query",
+ new SearchSpec.Builder().build(),
+ /*removeStatsBuilder=*/ null));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.removeByQuery(
- "package",
- "database",
- "query",
- new SearchSpec.Builder()
- .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
- .build(),
- /*statsBuilder=*/ null);
- });
+ () -> appSearchImpl.getStorageInfoForPackage("package"));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.getStorageInfoForPackage("package");
- });
+ () -> appSearchImpl.getStorageInfoForDatabase("package", "database"));
expectThrows(
IllegalStateException.class,
- () -> {
- appSearchImpl.getStorageInfoForDatabase("package", "database");
- });
-
- expectThrows(
- IllegalStateException.class,
- () -> {
- appSearchImpl.persistToDisk(PersistType.Code.FULL);
- });
+ () -> appSearchImpl.persistToDisk(PersistType.Code.FULL));
}
@Test
public void testPutPersistsWithLiteFlush() throws Exception {
// Setup the index
- Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir,
- context,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
+ AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1830,6 +1826,7 @@
"package",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1848,11 +1845,7 @@
// That document should be visible even from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir,
- context,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
+ AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
getResult =
appSearchImpl2.getDocument(
"package", "database", "namespace1", "id1", Collections.emptyMap());
@@ -1862,14 +1855,9 @@
@Test
public void testDeletePersistsWithLiteFlush() throws Exception {
// Setup the index
- Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir,
- context,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
+ AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1877,6 +1865,7 @@
"package",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -1919,11 +1908,7 @@
// Only the second document should be retrievable from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir,
- context,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
+ AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
expectThrows(
AppSearchException.class,
() ->
@@ -1942,14 +1927,9 @@
@Test
public void testDeleteByQueryPersistsWithLiteFlush() throws Exception {
// Setup the index
- Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir,
- context,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
+ AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1957,6 +1937,7 @@
"package",
"database",
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -2007,11 +1988,7 @@
// Only the second document should be retrievable from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir,
- context,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
+ AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
expectThrows(
AppSearchException.class,
() ->
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
index c6726c6..f20e8c6 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
@@ -25,9 +25,6 @@
import android.app.appsearch.GenericDocument;
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
-import android.content.Context;
-
-import androidx.test.core.app.ApplicationProvider;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
@@ -60,15 +57,9 @@
@Before
public void setUp() throws Exception {
- Context context = ApplicationProvider.getApplicationContext();
-
- // Give ourselves global query permissions
mAppSearchImpl =
AppSearchImpl.create(
- mTemporaryFolder.newFolder(),
- context,
- /*logger=*/ null,
- ALWAYS_OPTIMIZE);
+ mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
mLogger = new TestLogger();
}
@@ -289,20 +280,15 @@
//
@Test
public void testLoggingStats_initialize() throws Exception {
- Context context = ApplicationProvider.getApplicationContext();
-
// Create an unused AppSearchImpl to generated an InitializeStats.
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- mTemporaryFolder.newFolder(),
- context,
- mLogger,
- ALWAYS_OPTIMIZE);
+ InitializeStats.Builder initStatsBuilder = new InitializeStats.Builder();
+ AppSearchImpl.create(mTemporaryFolder.newFolder(), initStatsBuilder, ALWAYS_OPTIMIZE);
+ InitializeStats iStats = initStatsBuilder.build();
- InitializeStats iStats = mLogger.mInitializeStats;
assertThat(iStats).isNotNull();
assertThat(iStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
- assertThat(iStats.getTotalLatencyMillis()).isGreaterThan(0);
+ // Total latency captured in LocalStorage
+ assertThat(iStats.getTotalLatencyMillis()).isEqualTo(0);
assertThat(iStats.hasDeSync()).isFalse();
assertThat(iStats.getNativeLatencyMillis()).isGreaterThan(0);
assertThat(iStats.getDocumentStoreDataStatus())
@@ -322,6 +308,7 @@
testPackageName,
testDatabase,
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -350,10 +337,12 @@
testPackageName,
testDatabase,
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
+
GenericDocument document = new GenericDocument.Builder<>("namespace", "id", "type").build();
mAppSearchImpl.putDocument(testPackageName, testDatabase, document, mLogger);
@@ -401,6 +390,7 @@
testPackageName,
testDatabase,
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
@@ -432,6 +422,7 @@
testPackageName,
testDatabase,
schemas,
+ /*visibilityStore=*/ null,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
index fa3f45c..a2b1c1c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
@@ -34,6 +34,7 @@
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.DevicePolicyManagerLiteInternal;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -158,6 +159,7 @@
final long ident = mContext.binder.clearCallingIdentity();
try {
+ LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext);
@@ -271,6 +273,7 @@
final long ident = mContext.binder.clearCallingIdentity();
try {
+ LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext);
@@ -339,6 +342,7 @@
// (Need clearCallingIdentity() to pass permission checks.)
final long ident = mContext.binder.clearCallingIdentity();
try {
+ LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext);
@@ -499,6 +503,7 @@
DevicePolicyManagerServiceTestable dpms;
final long ident = mContext.binder.clearCallingIdentity();
try {
+ LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 5447a58..cedf636 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -84,6 +84,7 @@
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.DevicePolicyManagerLiteInternal;
import android.app.admin.FactoryResetProtectionPolicy;
import android.app.admin.PasswordMetrics;
import android.app.admin.SystemUpdatePolicy;
@@ -280,6 +281,7 @@
private void initializeDpms() {
// Need clearCallingIdentity() to pass permission checks.
final long ident = mContext.binder.clearCallingIdentity();
+ LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext);
@@ -369,10 +371,14 @@
.thenReturn(false);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+ LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class);
new DevicePolicyManagerServiceTestable(getServices(), mContext);
// If the device has no DPMS feature, it shouldn't register the local service.
assertThat(LocalServices.getService(DevicePolicyManagerInternal.class)).isNull();
+
+ // But should still register the lite one
+ assertThat(LocalServices.getService(DevicePolicyManagerLiteInternal.class)).isNotNull();
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index f156779..5ba375b 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -64,6 +64,7 @@
import com.android.server.SystemService;
import com.android.server.display.DisplayManagerService.SyncRoot;
import com.android.server.lights.LightsManager;
+import com.android.server.sensors.SensorManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
@@ -150,6 +151,7 @@
@Mock LightsManager mMockLightsManager;
@Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
@Mock IBinder mMockDisplayToken;
+ @Mock SensorManagerInternal mMockSensorManagerInternal;
@Before
public void setUp() throws Exception {
@@ -161,6 +163,8 @@
LocalServices.addService(WindowManagerInternal.class, mMockWindowManagerInternal);
LocalServices.removeServiceForTest(LightsManager.class);
LocalServices.addService(LightsManager.class, mMockLightsManager);
+ LocalServices.removeServiceForTest(SensorManagerInternal.class);
+ LocalServices.addService(SensorManagerInternal.class, mMockSensorManagerInternal);
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 918979c..c0df2e3 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -49,6 +49,8 @@
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.os.Handler;
import android.os.Looper;
@@ -70,6 +72,8 @@
import com.android.server.display.DisplayModeDirector.BrightnessObserver;
import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
import com.android.server.display.DisplayModeDirector.Vote;
+import com.android.server.sensors.SensorManagerInternal;
+import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.testutils.FakeDeviceConfigInterface;
@@ -105,6 +109,10 @@
public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
@Mock
public StatusBarManagerInternal mStatusBarMock;
+ @Mock
+ public SensorManagerInternal mSensorManagerInternalMock;
+ @Mock
+ public DisplayManagerInternal mDisplayManagerInternalMock;
@Before
public void setUp() throws Exception {
@@ -117,6 +125,10 @@
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
LocalServices.addService(StatusBarManagerInternal.class, mStatusBarMock);
+ LocalServices.removeServiceForTest(SensorManagerInternal.class);
+ LocalServices.addService(SensorManagerInternal.class, mSensorManagerInternalMock);
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+ LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
}
private DisplayModeDirector createDirectorFromRefreshRateArray(
@@ -1214,10 +1226,39 @@
assertThat(desiredSpecs.baseModeId).isEqualTo(8);
}
+ @Test
+ public void testProximitySensorVoting() throws Exception {
+ DisplayModeDirector director =
+ createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
+ director.start(createMockSensorManager());
+
+ ArgumentCaptor<ProximityActiveListener> captor =
+ ArgumentCaptor.forClass(ProximityActiveListener.class);
+ verify(mSensorManagerInternalMock).addProximityActiveListener(any(Executor.class),
+ captor.capture());
+ ProximityActiveListener listener = captor.getValue();
+
+ // Verify that there is no proximity vote initially
+ Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertNull(vote);
+
+ when(mDisplayManagerInternalMock.getRefreshRateForDisplayAndSensor(eq(DISPLAY_ID), eq(null),
+ eq(Sensor.STRING_TYPE_PROXIMITY))).thenReturn(new RefreshRateRange(60, 60));
+
+ // Set the proximity to active and verify that we added a vote.
+ listener.onProximityActive(true);
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertVoteForRefreshRate(vote, 60.f);
+
+ // Turn prox off and verify vote is gone.
+ listener.onProximityActive(false);
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertNull(vote);
+ }
+
private void assertVoteForRefreshRate(Vote vote, float refreshRate) {
assertThat(vote).isNotNull();
- final DisplayModeDirector.RefreshRateRange expectedRange =
- new DisplayModeDirector.RefreshRateRange(refreshRate, refreshRate);
+ final RefreshRateRange expectedRange = new RefreshRateRange(refreshRate, refreshRate);
assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 0cf212c..f53ae52 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -40,6 +40,7 @@
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener;
+import android.hardware.hdmi.IHdmiControlStatusChangeListener;
import android.os.Binder;
import android.os.IPowerManager;
import android.os.IThermalService;
@@ -683,6 +684,100 @@
HdmiControlManager.HDMI_CEC_VERSION_2_0);
}
+ @Test
+ public void initCec_statusListener_CecDisabled() {
+ HdmiControlStatusCallback hdmiControlStatusCallback = new HdmiControlStatusCallback();
+
+ mHdmiControlServiceSpy.addHdmiControlStatusChangeListener(hdmiControlStatusCallback);
+
+ mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+ HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
+ mTestLooper.dispatchAll();
+
+ assertThat(hdmiControlStatusCallback.mCecEnabled).isFalse();
+ assertThat(hdmiControlStatusCallback.mCecAvailable).isFalse();
+ }
+
+ @Test
+ public void initCec_statusListener_CecEnabled_NoCecResponse() {
+ HdmiControlStatusCallback hdmiControlStatusCallback = new HdmiControlStatusCallback();
+
+ mHdmiControlServiceSpy.addHdmiControlStatusChangeListener(hdmiControlStatusCallback);
+
+ mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+ HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
+ mTestLooper.dispatchAll();
+ mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+ HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
+ mTestLooper.dispatchAll();
+ // Hit timeout twice due to retries
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(hdmiControlStatusCallback.mCecEnabled).isTrue();
+ assertThat(hdmiControlStatusCallback.mCecAvailable).isFalse();
+ }
+
+ @Test
+ public void initCec_statusListener_CecEnabled_CecAvailable_TvOn() {
+ HdmiControlStatusCallback hdmiControlStatusCallback = new HdmiControlStatusCallback();
+ mHdmiControlServiceSpy.setControlEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
+ mTestLooper.dispatchAll();
+
+ mHdmiControlServiceSpy.addHdmiControlStatusChangeListener(hdmiControlStatusCallback);
+ mHdmiControlServiceSpy.setControlEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
+ mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
+ Constants.ADDR_TV,
+ mHdmiControlServiceSpy.playback().mAddress, HdmiControlManager.POWER_STATUS_ON);
+ mNativeWrapper.onCecMessage(reportPowerStatus);
+ mTestLooper.dispatchAll();
+
+ assertThat(hdmiControlStatusCallback.mCecEnabled).isTrue();
+ assertThat(hdmiControlStatusCallback.mCecAvailable).isTrue();
+ }
+
+ @Test
+ public void initCec_statusListener_CecEnabled_CecAvailable_TvStandby() {
+ HdmiControlStatusCallback hdmiControlStatusCallback = new HdmiControlStatusCallback();
+ mHdmiControlServiceSpy.setControlEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
+ mTestLooper.dispatchAll();
+
+ mHdmiControlServiceSpy.addHdmiControlStatusChangeListener(hdmiControlStatusCallback);
+ mHdmiControlServiceSpy.setControlEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
+ mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
+ Constants.ADDR_TV,
+ mHdmiControlServiceSpy.playback().mAddress,
+ HdmiControlManager.POWER_STATUS_STANDBY);
+ mNativeWrapper.onCecMessage(reportPowerStatus);
+ mTestLooper.dispatchAll();
+
+ assertThat(hdmiControlStatusCallback.mCecEnabled).isTrue();
+ assertThat(hdmiControlStatusCallback.mCecAvailable).isTrue();
+ }
+
+ private static class HdmiControlStatusCallback extends IHdmiControlStatusChangeListener.Stub {
+ boolean mCecEnabled = false;
+ boolean mCecAvailable = false;
+
+ @Override
+ public void onStatusChange(int isCecEnabled, boolean isCecAvailable)
+ throws RemoteException {
+ mCecEnabled = isCecEnabled == HdmiControlManager.HDMI_CEC_CONTROL_ENABLED;
+ mCecAvailable = isCecAvailable;
+ }
+ }
+
private static class VolumeControlFeatureCallback extends
IHdmiCecVolumeControlFeatureListener.Stub {
boolean mCallbackReceived = false;
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 2efebbf..8eb3cf3 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -4,7 +4,9 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyString;
@@ -102,6 +104,20 @@
}
@Test
+ public void testStringToIntArrayAndIntArrayToString() {
+ final int[] netCapabilitiesIntArray = { 1, 3, 5, 7, 9 };
+ final String netCapabilitiesStr = "1,3,5,7,9";
+ final String netCapabilitiesStrWithErrorInt = "1,3,a,7,9";
+ final String emptyString = "";
+ final String str1 = JobStore.intArrayToString(netCapabilitiesIntArray);
+ assertArrayEquals(netCapabilitiesIntArray, JobStore.stringToIntArray(str1));
+ assertEquals(0, JobStore.stringToIntArray(emptyString).length);
+ assertThrows(NumberFormatException.class,
+ () -> JobStore.stringToIntArray(netCapabilitiesStrWithErrorInt));
+ assertEquals(netCapabilitiesStr, JobStore.intArrayToString(netCapabilitiesIntArray));
+ }
+
+ @Test
public void testMaybeWriteStatusToDisk() throws Exception {
int taskId = 5;
long runByMillis = 20000L; // 20s
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 67dd055..dc745cd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -83,9 +83,17 @@
private static final int DUMMY_OVERLAY_APPID = 10756;
private static final int SYSTEM_USER = 0;
private static final int SECONDARY_USER = 10;
+ private static final int ADDED_USER = 11;
private static final int[] USER_ARRAY = {SYSTEM_USER, SECONDARY_USER};
- private static final UserInfo[] USER_INFO_LIST = Arrays.stream(USER_ARRAY).mapToObj(
- id -> new UserInfo(id, Integer.toString(id), 0)).toArray(UserInfo[]::new);
+ private static final int[] USER_ARRAY_WITH_ADDED = {SYSTEM_USER, SECONDARY_USER, ADDED_USER};
+ private static final UserInfo[] USER_INFO_LIST = toUserInfos(USER_ARRAY);
+ private static final UserInfo[] USER_INFO_LIST_WITH_ADDED = toUserInfos(USER_ARRAY_WITH_ADDED);
+
+ private static UserInfo[] toUserInfos(int[] userIds) {
+ return Arrays.stream(userIds)
+ .mapToObj(id -> new UserInfo(id, Integer.toString(id), 0))
+ .toArray(UserInfo[]::new);
+ }
@Mock
AppsFilter.FeatureConfig mFeatureConfigMock;
@@ -319,6 +327,47 @@
}
@Test
+ public void testOnUserCreated_FilterMatches() throws Exception {
+ final AppsFilter appsFilter =
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
+ simulateAddBasicAndroid(appsFilter);
+
+ appsFilter.onSystemReady();
+
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_APPID);
+ PackageSetting calling = simulateAddPackage(appsFilter,
+ pkgQueriesProvider("com.some.other.package", "com.some.authority"),
+ DUMMY_CALLING_APPID);
+
+ for (int subjectUserId : USER_ARRAY) {
+ for (int otherUserId : USER_ARRAY) {
+ assertFalse(appsFilter.shouldFilterApplication(
+ UserHandle.getUid(DUMMY_CALLING_APPID, subjectUserId), calling, target,
+ otherUserId));
+ }
+ }
+
+ // adds new user
+ doAnswer(invocation -> {
+ ((AppsFilter.StateProvider.CurrentStateCallback) invocation.getArgument(0))
+ .currentState(mExisting, USER_INFO_LIST_WITH_ADDED);
+ return new Object();
+ }).when(mStateProvider)
+ .runWithState(any(AppsFilter.StateProvider.CurrentStateCallback.class));
+ appsFilter.onUserCreated(ADDED_USER);
+
+ for (int subjectUserId : USER_ARRAY_WITH_ADDED) {
+ for (int otherUserId : USER_ARRAY_WITH_ADDED) {
+ assertFalse(appsFilter.shouldFilterApplication(
+ UserHandle.getUid(DUMMY_CALLING_APPID, subjectUserId), calling, target,
+ otherUserId));
+ }
+ }
+ }
+
+ @Test
public void testQueriesDifferentProvider_Filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index ea2dc0a..9117ae6 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -234,7 +234,7 @@
CombinedVibration effect = CombinedVibration.createParallel(
VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
vibrate(service, effect, HAPTIC_FEEDBACK_ATTRS);
- service.cancelVibrate(/* usageFilter= */ -1, service);
+ service.cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, service);
assertTrue(service.setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS));
@@ -889,13 +889,13 @@
mockVibrators(1);
VibratorManagerService service = createSystemReadyService();
- service.cancelVibrate(/* usageFilter= */ -1, service);
+ service.cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, service);
assertFalse(service.isVibrating(1));
vibrate(service, VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100), ALARM_ATTRS);
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
- service.cancelVibrate(/* usageFilter= */ -1, service);
+ service.cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, service);
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
}
@@ -924,6 +924,39 @@
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
}
+ @Test
+ public void cancelVibrate_withoutUnknownUsage_onlyStopsIfFilteringUnknownOrAllUsages()
+ throws Exception {
+ mockVibrators(1);
+ VibrationAttributes attrs = new VibrationAttributes.Builder()
+ .setUsage(VibrationAttributes.USAGE_UNKNOWN)
+ .build();
+ VibratorManagerService service = createSystemReadyService();
+
+ vibrate(service, VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100), attrs);
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ // Do not cancel UNKNOWN vibration when filter is being applied for other usages.
+ service.cancelVibrate(VibrationAttributes.USAGE_RINGTONE, service);
+ assertFalse(waitUntil(s -> !s.isVibrating(1), service, /* timeout= */ 50));
+
+ service.cancelVibrate(
+ VibrationAttributes.USAGE_CLASS_ALARM | ~VibrationAttributes.USAGE_CLASS_MASK,
+ service);
+ assertFalse(waitUntil(s -> !s.isVibrating(1), service, /* timeout= */ 50));
+
+ // Cancel UNKNOWN vibration when filtered for that vibration specifically.
+ service.cancelVibrate(VibrationAttributes.USAGE_UNKNOWN, service);
+ assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ vibrate(service, VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100), attrs);
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ // Cancel UNKNOWN vibration when all vibrations are being cancelled.
+ service.cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, service);
+ assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+ }
+
private void mockCapabilities(long... capabilities) {
when(mNativeWrapperMock.getCapabilities()).thenReturn(
Arrays.stream(capabilities).reduce(0, (a, b) -> a | b));
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 70ba2cf..a522b5c 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -6472,7 +6472,7 @@
zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
try {
- mBinderService.addAutomaticZenRule(rule);
+ mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
fail("Zen policy only applies to priority only mode");
} catch (IllegalArgumentException e) {
// yay
@@ -6480,11 +6480,11 @@
rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
- mBinderService.addAutomaticZenRule(rule);
+ mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
- mBinderService.addAutomaticZenRule(rule);
+ mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
index 5262465..d0bf63a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -190,7 +190,7 @@
ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
rule.configurationActivity = new ComponentName("a", "a");
- rule.component = new ComponentName("a", "b");
+ rule.component = new ComponentName("b", "b");
rule.conditionId = new Uri.Builder().scheme("hello").build();
rule.condition = new Condition(rule.conditionId, "", Condition.STATE_TRUE);
rule.enabled = true;
@@ -200,6 +200,7 @@
rule.modified = true;
rule.name = "name";
rule.snoozing = true;
+ rule.pkg = "b";
TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -215,8 +216,7 @@
new ByteArrayInputStream(baos.toByteArray())), null);
parser.nextTag();
ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
- // read from backing component
- assertEquals("a", fromXml.pkg);
+ assertEquals("b", fromXml.pkg);
// always resets on reboot
assertFalse(fromXml.snoozing);
//should all match original
@@ -232,6 +232,55 @@
assertEquals(rule.zenMode, fromXml.zenMode);
}
+ @Test
+ public void testRuleXml_pkg_component() throws Exception {
+ String tag = "tag";
+
+ ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+ rule.configurationActivity = new ComponentName("a", "a");
+ rule.component = new ComponentName("b", "b");
+
+ TypedXmlSerializer out = Xml.newFastSerializer();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ out.setOutput(new BufferedOutputStream(baos), "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, tag);
+ ZenModeConfig.writeRuleXml(rule, out);
+ out.endTag(null, tag);
+ out.endDocument();
+
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(
+ new ByteArrayInputStream(baos.toByteArray())), null);
+ parser.nextTag();
+ ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
+ assertEquals("b", fromXml.pkg);
+ }
+
+ @Test
+ public void testRuleXml_pkg_configActivity() throws Exception {
+ String tag = "tag";
+
+ ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+ rule.configurationActivity = new ComponentName("a", "a");
+
+ TypedXmlSerializer out = Xml.newFastSerializer();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ out.setOutput(new BufferedOutputStream(baos), "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, tag);
+ ZenModeConfig.writeRuleXml(rule, out);
+ out.endTag(null, tag);
+ out.endDocument();
+
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(
+ new ByteArrayInputStream(baos.toByteArray())), null);
+ parser.nextTag();
+ ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
+ assertNull(fromXml.pkg);
+ }
+
private ZenModeConfig getMutedRingerConfig() {
ZenModeConfig config = new ZenModeConfig();
// Allow alarms, media
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 72c6028..00dbaf6 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -1597,7 +1597,7 @@
new ComponentName("android", "ScheduleConditionProvider"),
ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
- String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+ String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
assertTrue(id != null);
ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id);
@@ -1617,12 +1617,12 @@
new ComponentName("android", "ScheduleConditionProvider"),
sharedUri,
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
- String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+ String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
new ComponentName("android", "ScheduleConditionProvider"),
sharedUri,
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
- String id2 = mZenModeHelperSpy.addAutomaticZenRule(zenRule2, "test");
+ String id2 = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule2, "test");
Condition condition = new Condition(sharedUri, "", Condition.STATE_TRUE);
mZenModeHelperSpy.setAutomaticZenRuleState(sharedUri, condition);
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 8216830..b7713a9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2699,6 +2699,85 @@
assertFalse("Starting window should not be present", activity.hasStartingWindow());
}
+ @Test
+ public void testSetVisibility_visibleToVisible() {
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setCreateTask(true).build();
+ // By default, activity is visible.
+ assertTrue(activity.isVisible());
+ assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+ assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+
+ // Request the activity to be visible. Although the activity is already visible, app
+ // transition animation should be applied on this activity. This might be unnecessary, but
+ // until we verify no logic relies on this behavior, we'll keep this as is.
+ activity.setVisibility(true);
+ assertTrue(activity.isVisible());
+ assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+ assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+ }
+
+ @Test
+ public void testSetVisibility_visibleToInvisible() {
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setCreateTask(true).build();
+ // By default, activity is visible.
+ assertTrue(activity.isVisible());
+ assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+ assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+
+ // Request the activity to be invisible. Since the visibility changes, app transition
+ // animation should be applied on this activity.
+ activity.setVisibility(false);
+ assertTrue(activity.isVisible());
+ assertFalse(activity.mVisibleRequested);
+ assertFalse(activity.mDisplayContent.mOpeningApps.contains(activity));
+ assertTrue(activity.mDisplayContent.mClosingApps.contains(activity));
+ }
+
+ @Test
+ public void testSetVisibility_invisibleToVisible() {
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setCreateTask(true).setVisible(false).build();
+ // Activiby is invisible. However ATMS requests it to become visible, since this is a top
+ // activity.
+ assertFalse(activity.isVisible());
+ assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+ assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+
+ // Request the activity to be visible. Since the visibility changes, app transition
+ // animation should be applied on this activity.
+ activity.setVisibility(true);
+ assertFalse(activity.isVisible());
+ assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+ assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+ }
+
+ @Test
+ public void testSetVisibility_invisibleToInvisible() {
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setCreateTask(true).setVisible(false).build();
+ // Activiby is invisible. However ATMS requests it to become visible, since this is a top
+ // activity.
+ assertFalse(activity.isVisible());
+ assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+ assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+
+ // Request the activity to be invisible. Since the activity is already invisible, no app
+ // transition should be applied on this activity.
+ activity.setVisibility(false);
+ assertFalse(activity.isVisible());
+ assertFalse(activity.mVisibleRequested);
+ assertFalse(activity.mDisplayContent.mOpeningApps.contains(activity));
+ assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+ }
+
private void assertHasStartingWindow(ActivityRecord atoken) {
assertNotNull(atoken.mStartingSurface);
assertNotNull(atoken.mStartingData);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index d2270b5..4e261de 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -1534,30 +1534,6 @@
}
@Test
- public void testSandboxDisplayApis_unresizableAppNotSandboxed() {
- // Set up a display in landscape with an unresizable app.
- setUpDisplaySizeWithApp(2500, 1000);
- mActivity.mDisplayContent.setSandboxDisplayApis(false /* sandboxDisplayApis */);
- prepareUnresizable(mActivity, 1.5f, SCREEN_ORIENTATION_LANDSCAPE);
- assertFitted();
-
- // Activity max bounds not be sandboxed since sandboxing is disabled.
- assertMaxBoundsInheritDisplayAreaBounds();
- }
-
- @Test
- public void testSandboxDisplayApis_unresizableAppSandboxed() {
- // Set up a display in landscape with an unresizable app.
- setUpDisplaySizeWithApp(2500, 1000);
- mActivity.mDisplayContent.setSandboxDisplayApis(true /* sandboxDisplayApis */);
- prepareUnresizable(mActivity, 1.5f, SCREEN_ORIENTATION_LANDSCAPE);
- assertFitted();
-
- // Activity max bounds should be sandboxed since sandboxing is enabled.
- assertActivityMaxBoundsSandboxed();
- }
-
- @Test
public void testResizableApp_notSandboxed() {
// Set up a display in landscape with a fully resizable app.
setUpDisplaySizeWithApp(2500, 1000);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 111449d..5880899 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -805,6 +805,7 @@
private Bundle mIntentExtras;
private boolean mOnTop = false;
private ActivityInfo.WindowLayout mWindowLayout;
+ private boolean mVisible = true;
ActivityBuilder(ActivityTaskManagerService service) {
mService = service;
@@ -930,6 +931,11 @@
return this;
}
+ ActivityBuilder setVisible(boolean visible) {
+ mVisible = visible;
+ return this;
+ }
+
ActivityRecord build() {
SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock);
try {
@@ -1012,9 +1018,10 @@
// root tasks (e.g. home root task).
mTask.moveToFront("createActivity");
}
- // Make visible by default...
- activity.mVisibleRequested = true;
- activity.setVisible(true);
+ if (mVisible) {
+ activity.mVisibleRequested = true;
+ activity.setVisible(true);
+ }
}
final WindowProcessController wpc;