Merge "Reinitialize dimens to fix issues with changing display/font size." into sc-dev
diff --git a/Android.bp b/Android.bp
index 2321cc5..71023bf 100644
--- a/Android.bp
+++ b/Android.bp
@@ -581,4 +581,5 @@
"StubLibraries.bp",
"ApiDocs.bp",
"ProtoLibraries.bp",
+ "TestProtoLibraries.bp",
]
diff --git a/StubLibraries.bp b/StubLibraries.bp
index e82a322..941a1fa 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -205,6 +205,7 @@
api_lint: {
enabled: true,
new_since: ":android.api.module-lib.latest",
+ baseline_file: "core/api/module-lib-lint-baseline.txt",
},
},
dists: [
diff --git a/TestProtoLibraries.bp b/TestProtoLibraries.bp
new file mode 100644
index 0000000..8e269d0
--- /dev/null
+++ b/TestProtoLibraries.bp
@@ -0,0 +1,36 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+java_library_host {
+ name: "platformtestprotos",
+ srcs: [
+ ":libstats_atom_enum_protos",
+ ":libstats_atom_message_protos",
+ ":libstats_internal_protos",
+ ":statsd_internal_protos",
+ ],
+ libs: [
+ "libprotobuf-java-full",
+ ],
+ proto: {
+ include_dirs: [
+ "external/protobuf/src",
+ "frameworks/proto_logging/stats",
+ ],
+ type: "full",
+ },
+ errorprone: {
+ javacflags: ["-Xep:MissingOverride:OFF"], // b/72714520
+ },
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
index 6e81afc..d5271a6 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
@@ -44,6 +44,8 @@
* @hide
*/
public final class AppSearchConfig implements AutoCloseable {
+ private static volatile AppSearchConfig sConfig;
+
/**
* It would be used as default min time interval between samples in millis if there is no value
* set for {@link AppSearchConfig#KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS} in DeviceConfig.
@@ -101,12 +103,16 @@
updateCachedValues(properties);
};
+ private AppSearchConfig() {
+ }
+
/**
* Creates an instance of {@link AppSearchConfig}.
*
* @param executor used to fetch and cache the flag values from DeviceConfig during creation or
* config change.
*/
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@NonNull
public static AppSearchConfig create(@NonNull Executor executor) {
Objects.requireNonNull(executor);
@@ -115,7 +121,23 @@
return configManager;
}
- private AppSearchConfig() {
+ /**
+ * Gets an instance of {@link AppSearchConfig} 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 AppSearchConfig getInstance(@NonNull Executor executor) {
+ Objects.requireNonNull(executor);
+ if (sConfig == null) {
+ synchronized (AppSearchConfig.class) {
+ if (sConfig == null) {
+ sConfig = create(executor);
+ }
+ }
+ }
+ return sConfig;
}
/**
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 0c07fa0..c7c1d68 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -17,11 +17,10 @@
import static android.app.appsearch.AppSearchResult.throwableToFailedResult;
import static android.os.Process.INVALID_UID;
-import static android.os.UserHandle.USER_NULL;
+import android.Manifest;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
-import android.app.ActivityManager;
import android.app.appsearch.AppSearchBatchResult;
import android.app.appsearch.AppSearchMigrationHelper;
import android.app.appsearch.AppSearchResult;
@@ -63,6 +62,7 @@
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.usage.StorageStatsManagerLocal;
import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
@@ -124,8 +124,10 @@
}
private void registerReceivers() {
- mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL,
- new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null,
+ mContext.registerReceiverForAllUsers(
+ new UserActionReceiver(),
+ new IntentFilter(Intent.ACTION_USER_REMOVED),
+ /*broadcastPermission=*/ null,
/*scheduler=*/ null);
//TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
@@ -135,8 +137,10 @@
packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
packageChangedFilter.addDataScheme("package");
packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiverAsUser(new PackageChangedReceiver(), UserHandle.ALL,
- packageChangedFilter, /*broadcastPermission=*/ null,
+ mContext.registerReceiverForAllUsers(
+ new PackageChangedReceiver(),
+ packageChangedFilter,
+ /*broadcastPermission=*/ null,
/*scheduler=*/ null);
}
@@ -148,12 +152,13 @@
switch (intent.getAction()) {
case Intent.ACTION_USER_REMOVED:
- int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
- if (userId == USER_NULL) {
- Log.e(TAG, "userId is missing in the intent: " + intent);
+ UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
+ if (userHandle == null) {
+ Log.e(TAG, "Extra "
+ + Intent.EXTRA_USER + " is missing in the intent: " + intent);
return;
}
- handleUserRemoved(UserHandle.of(userId));
+ handleUserRemoved(userHandle);
break;
default:
Log.e(TAG, "Received unknown intent: " + intent);
@@ -174,7 +179,7 @@
*/
private void handleUserRemoved(@NonNull UserHandle userHandle) {
try {
- mImplInstanceManager.removeAppSearchImplForUser(userHandle);
+ mImplInstanceManager.closeAndRemoveAppSearchImplForUser(userHandle);
mLoggerInstanceManager.removePlatformLoggerForUser(userHandle);
Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
} catch (Throwable t) {
@@ -219,7 +224,7 @@
if (ImplInstanceManager.getAppSearchDir(userHandle).exists()) {
// Only clear the package's data if AppSearch exists for this user.
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
- userHandle);
+ userHandle, AppSearchConfig.getInstance(EXECUTOR));
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
userHandle, logger);
//TODO(b/145759910) clear visibility setting for package.
@@ -1142,7 +1147,8 @@
try {
verifyUserUnlocked(callingUser);
logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
- mContext, callingUser);
+ mContext, callingUser,
+ AppSearchConfig.getInstance(EXECUTOR));
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUser, logger);
++operationSuccessCount;
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
@@ -1183,13 +1189,9 @@
Objects.requireNonNull(actualCallingUser);
Objects.requireNonNull(claimedCallingPackage);
- int claimedCallingUid;
- try {
- Context claimedCallingContext =
- mContext.createContextAsUser(actualCallingUser, /*flags=*/ 0);
- claimedCallingUid = claimedCallingContext.getPackageManager().getPackageUid(
- claimedCallingPackage, /*flags=*/ 0);
- } catch (PackageManager.NameNotFoundException e) {
+ int claimedCallingUid = PackageUtil.getPackageUidAsUser(
+ mContext, claimedCallingPackage, actualCallingUser);
+ if (claimedCallingUid == INVALID_UID) {
throw new SecurityException(
"Specified calling package [" + claimedCallingPackage + "] not found");
}
@@ -1257,23 +1259,44 @@
*
* <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user.
*
+ * @param requestedUser The user which the caller is requesting to execute as.
+ * @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 static UserHandle handleIncomingUser(@NonNull UserHandle userHandle, int callingUid) {
+ private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
int callingPid = Binder.getCallingPid();
- int finalUserId = ActivityManager.handleIncomingUser(
+ UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
+ if (callingUser.equals(requestedUser)) {
+ return requestedUser;
+ }
+ // Duplicates UserController#ensureNotSpecialUser
+ if (requestedUser.getIdentifier() < 0) {
+ throw new IllegalArgumentException(
+ "Call does not support special user " + requestedUser);
+ }
+ boolean canInteractAcrossUsers = mContext.checkPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS,
callingPid,
- callingUid,
- userHandle.getIdentifier(),
- /*allowAll=*/ false,
- /*requireFull=*/ false,
- /*name=*/ null,
- /*callerPackage=*/ null);
- return UserHandle.of(finalUserId);
+ callingUid) == PackageManager.PERMISSION_GRANTED;
+ if (!canInteractAcrossUsers) {
+ canInteractAcrossUsers = mContext.checkPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ callingPid,
+ callingUid) == PackageManager.PERMISSION_GRANTED;
+ }
+ if (canInteractAcrossUsers) {
+ return requestedUser;
+ }
+ throw new SecurityException(
+ "Permission denied while calling from uid " + callingUid
+ + " with " + requestedUser + "; Need to run as either the calling user ("
+ + callingUser + "), or with one of the following permissions: "
+ + Manifest.permission.INTERACT_ACROSS_USERS + " or "
+ + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
}
// TODO(b/179160886): Cache the previous storage stats.
@@ -1291,7 +1314,8 @@
try {
verifyUserUnlocked(userHandle);
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
- mContext, userHandle);
+ mContext, userHandle,
+ AppSearchConfig.getInstance(EXECUTOR));
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(
mContext, userHandle, logger);
stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
@@ -1319,7 +1343,8 @@
return;
}
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
- mContext, userHandle);
+ mContext, userHandle,
+ AppSearchConfig.getInstance(EXECUTOR));
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(
mContext, userHandle, logger);
for (int i = 0; i < packagesForUid.length; i++) {
@@ -1348,7 +1373,8 @@
return;
}
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
- mContext, userHandle);
+ mContext, userHandle,
+ AppSearchConfig.getInstance(EXECUTOR));
AppSearchImpl impl =
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userHandle, logger);
for (int i = 0; i < packagesForUser.size(); i++) {
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
index beb4d24..e7845d5 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
@@ -104,25 +104,6 @@
}
/**
- * Remove an instance of {@link AppSearchImpl} for the given user.
- *
- * <p>This method should only be called if {@link AppSearchManagerService} receives an
- * ACTION_USER_REMOVED, which the instance of given user should be removed.
- *
- * <p>If the user is removed, the "credential encrypted" system directory where icing lives will
- * be auto-deleted. So we shouldn't worry about persist data or close the AppSearchImpl.
- *
- * @param userHandle The multi-user user handle of the user that need to be removed.
- */
- public void removeAppSearchImplForUser(@NonNull UserHandle userHandle) {
- Objects.requireNonNull(userHandle);
- synchronized (mInstancesLocked) {
- // no need to close and persist data to disk since we are removing them now.
- mInstancesLocked.remove(userHandle);
- }
- }
-
- /**
* 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.
@@ -172,11 +153,6 @@
@Nullable AppSearchLogger logger)
throws AppSearchException {
File appSearchDir = getAppSearchDir(userHandle);
- // TODO(b/181787682): Swap AppSearchImpl and VisibilityStore to accept a UserHandle too
- return AppSearchImpl.create(
- appSearchDir,
- userContext,
- userHandle.getIdentifier(),
- /*logger=*/ null);
+ return AppSearchImpl.create(appSearchDir, userContext, /*logger=*/ null);
}
}
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 a940dde..29cb57c 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
@@ -201,7 +201,6 @@
public static AppSearchImpl create(
@NonNull File icingDir,
@NonNull Context userContext,
- int userId,
@Nullable AppSearchLogger logger)
throws AppSearchException {
Objects.requireNonNull(icingDir);
@@ -213,8 +212,7 @@
initStatsBuilder = new InitializeStats.Builder();
}
- AppSearchImpl appSearchImpl =
- new AppSearchImpl(icingDir, userContext, userId, initStatsBuilder);
+ AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir, userContext, initStatsBuilder);
long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime();
appSearchImpl.initializeVisibilityStore();
@@ -238,7 +236,6 @@
private AppSearchImpl(
@NonNull File icingDir,
@NonNull Context userContext,
- int userId,
@Nullable InitializeStats.Builder initStatsBuilder)
throws AppSearchException {
mReadWriteLock.writeLock().lock();
@@ -256,7 +253,7 @@
"Constructing IcingSearchEngine, response",
Objects.hashCode(mIcingSearchEngineLocked));
- mVisibilityStoreLocked = new VisibilityStore(this, userContext, userId);
+ mVisibilityStoreLocked = new VisibilityStore(this, userContext);
// The core initialization procedure. If any part of this fails, we bail into
// resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up).
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
index cb65e42..ea00f50 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/stats/LoggerInstanceManager.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/stats/LoggerInstanceManager.java
@@ -20,9 +20,9 @@
import android.content.Context;
import android.os.UserHandle;
import android.util.ArrayMap;
-import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.server.appsearch.AppSearchConfig;
import com.android.server.appsearch.AppSearchManagerService;
import java.util.Map;
@@ -34,12 +34,6 @@
* <p>These instances are managed per unique device-user.
*/
public final class LoggerInstanceManager {
- // TODO(b/173532925) flags to control those three
- // So probably we can't pass those three in the constructor but need to fetch the latest value
- // every time we need them in the logger.
- private static final int MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS = 100;
- private static final int DEFAULT_SAMPLING_RATIO = 10;
-
private static volatile LoggerInstanceManager sLoggerInstanceManager;
@GuardedBy("mInstancesLocked")
@@ -70,23 +64,19 @@
/**
* 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
+ * @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 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, new PlatformLogger.Config(
- MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- DEFAULT_SAMPLING_RATIO,
- // TODO(b/173532925) re-enable sampling ratios for different stats types
- // once we have P/H flag manager setup in ag/13977824
- /*samplingRatios=*/ new SparseIntArray()));
+ instance = new PlatformLogger(context, userHandle, config);
mInstancesLocked.put(userHandle, instance);
}
return instance;
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
index 7d0ce41..5a0199f 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -30,12 +29,14 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.appsearch.AppSearchConfig;
import com.android.server.appsearch.external.localstorage.AppSearchLogger;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
+import com.android.server.appsearch.util.PackageUtil;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
@@ -60,15 +61,15 @@
// User we're logging for.
private final UserHandle mUserHandle;
- // Configuration for the logger
- private final Config mConfig;
+ // Manager holding the configuration flags
+ private final AppSearchConfig mConfig;
private final Random mRng = new Random();
private final Object mLock = new Object();
/**
* SparseArray to track how many stats we skipped due to
- * {@link Config#mMinTimeIntervalBetweenSamplesMillis}.
+ * {@link AppSearchConfig#getCachedMinTimeIntervalBetweenSamplesMillis()}.
*
* <p> We can have correct extrapolated number by adding those counts back when we log
* the same type of stats next time. E.g. the true count of an event could be estimated as:
@@ -98,53 +99,6 @@
private long mLastPushTimeMillisLocked = 0;
/**
- * Class to configure the {@link PlatformLogger}
- */
- public static final class Config {
- // Minimum time interval (in millis) since last message logged to Westworld before
- // logging again.
- private final long mMinTimeIntervalBetweenSamplesMillis;
-
- // Default sampling interval for all types of stats
- private final int mDefaultSamplingInterval;
-
- /**
- * Sampling intervals for different types of stats
- *
- * <p>This SparseArray is passed by client and is READ-ONLY. The key to that SparseArray is
- * {@link CallStats.CallType}
- *
- * <p>If sampling interval is missing for certain stats type,
- * {@link Config#mDefaultSamplingInterval} will be used.
- *
- * <p>E.g. sampling interval=10 means that one out of every 10 stats was logged. If sampling
- * interval is 1, we will log each sample and it acts as if the sampling is disabled.
- */
- @NonNull
- private final SparseIntArray mSamplingIntervals;
-
- /**
- * Configuration for {@link PlatformLogger}
- *
- * @param minTimeIntervalBetweenSamplesMillis minimum time interval apart in Milliseconds
- * required for two consecutive stats logged
- * @param defaultSamplingInterval default sampling interval
- * @param samplingIntervals SparseArray to customize sampling interval for
- * different stat types
- */
- public Config(long minTimeIntervalBetweenSamplesMillis,
- int defaultSamplingInterval,
- @NonNull SparseIntArray samplingIntervals) {
- // TODO(b/173532925) Probably we can get rid of those three after we have p/h flags
- // for them.
- // e.g. we can just call DeviceConfig.get(SAMPLING_INTERVAL_FOR_PUT_DOCUMENTS).
- mMinTimeIntervalBetweenSamplesMillis = minTimeIntervalBetweenSamplesMillis;
- mDefaultSamplingInterval = defaultSamplingInterval;
- mSamplingIntervals = samplingIntervals;
- }
- }
-
- /**
* Helper class to hold platform specific stats for Westworld.
*/
static final class ExtraStats {
@@ -166,7 +120,8 @@
* Westworld constructor
*/
public PlatformLogger(
- @NonNull Context context, @NonNull UserHandle userHandle, @NonNull Config config) {
+ @NonNull Context context, @NonNull UserHandle userHandle,
+ @NonNull AppSearchConfig config) {
mContext = Objects.requireNonNull(context);
mUserHandle = Objects.requireNonNull(userHandle);
mConfig = Objects.requireNonNull(config);
@@ -215,7 +170,7 @@
}
@Override
- public void logStats(@androidx.annotation.NonNull RemoveStats stats) throws AppSearchException {
+ public void logStats(@NonNull RemoveStats stats) throws AppSearchException {
// TODO(b/173532925): Log stats
}
@@ -372,7 +327,9 @@
stats.getSchemaStoreRecoveryLatencyMillis(),
stats.getDocumentStoreDataStatus(),
stats.getDocumentCount(),
- stats.getSchemaTypeCount());
+ stats.getSchemaTypeCount(),
+ stats.hasReset(),
+ stats.getResetStatusCode());
}
/**
@@ -428,9 +385,12 @@
packageUid = getPackageUidAsUserLocked(packageName);
}
- int samplingInterval = mConfig.mSamplingIntervals.get(callType,
- mConfig.mDefaultSamplingInterval);
-
+ // The sampling ratio here might be different from the one used in
+ // shouldLogForTypeLocked if there is a config change in the middle.
+ // Since it is only one sample, we can just ignore this difference.
+ // Or we can retrieve samplingRatio at beginning and pass along
+ // as function parameter, but it will make code less cleaner with some duplication.
+ int samplingInterval = getSamplingIntervalFromConfig(callType);
int skippedSampleCount = mSkippedSampleCountLocked.get(callType,
/*valueOfKeyIfNotFound=*/ 0);
mSkippedSampleCountLocked.put(callType, 0);
@@ -450,9 +410,7 @@
// rate limiting.
@VisibleForTesting
boolean shouldLogForTypeLocked(@CallStats.CallType int callType) {
- int samplingInterval = mConfig.mSamplingIntervals.get(callType,
- mConfig.mDefaultSamplingInterval);
-
+ int samplingInterval = getSamplingIntervalFromConfig(callType);
// Sampling
if (!shouldSample(samplingInterval)) {
return false;
@@ -462,7 +420,7 @@
// Check the timestamp to see if it is too close to last logged sample
long currentTimeMillis = SystemClock.elapsedRealtime();
if (mLastPushTimeMillisLocked
- > currentTimeMillis - mConfig.mMinTimeIntervalBetweenSamplesMillis) {
+ > currentTimeMillis - mConfig.getCachedMinTimeIntervalBetweenSamplesMillis()) {
int count = mSkippedSampleCountLocked.get(callType, /*valueOfKeyIfNotFound=*/ 0);
++count;
mSkippedSampleCountLocked.put(callType, count);
@@ -493,21 +451,39 @@
@GuardedBy("mLock")
private int getPackageUidAsUserLocked(@NonNull String packageName) {
Integer packageUid = mPackageUidCacheLocked.get(packageName);
- if (packageUid != null) {
- return packageUid;
+ if (packageUid == null) {
+ packageUid = PackageUtil.getPackageUidAsUser(mContext, packageName, mUserHandle);
+ if (packageUid != Process.INVALID_UID) {
+ mPackageUidCacheLocked.put(packageName, packageUid);
+ }
}
+ return packageUid;
+ }
- // TODO(b/173532925) since VisibilityStore has the same method, we can make this a
- // utility function
- try {
- packageUid = mContext.getPackageManager().getPackageUidAsUser(
- packageName, mUserHandle.getIdentifier());
- mPackageUidCacheLocked.put(packageName, packageUid);
- return packageUid;
- } catch (PackageManager.NameNotFoundException e) {
- // Package doesn't exist, continue
+ /** Returns sampling ratio for stats type specified form {@link AppSearchConfig}. */
+ private int getSamplingIntervalFromConfig(@CallStats.CallType int statsType) {
+ switch (statsType) {
+ case CallStats.CALL_TYPE_PUT_DOCUMENTS:
+ case CallStats.CALL_TYPE_GET_DOCUMENTS:
+ case CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID:
+ case CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH:
+ return mConfig.getCachedSamplingIntervalForBatchCallStats();
+ case CallStats.CALL_TYPE_PUT_DOCUMENT:
+ return mConfig.getCachedSamplingIntervalForPutDocumentStats();
+ case CallStats.CALL_TYPE_UNKNOWN:
+ case CallStats.CALL_TYPE_INITIALIZE:
+ case CallStats.CALL_TYPE_SET_SCHEMA:
+ case CallStats.CALL_TYPE_GET_DOCUMENT:
+ case CallStats.CALL_TYPE_REMOVE_DOCUMENT_BY_ID:
+ case CallStats.CALL_TYPE_SEARCH:
+ case CallStats.CALL_TYPE_OPTIMIZE:
+ case CallStats.CALL_TYPE_FLUSH:
+ case CallStats.CALL_TYPE_GLOBAL_SEARCH:
+ case CallStats.CALL_TYPE_REMOVE_DOCUMENT_BY_SEARCH:
+ // TODO(b/173532925) Some of them above will have dedicated sampling ratio config
+ default:
+ return mConfig.getCachedSamplingIntervalDefault();
}
- return Process.INVALID_UID;
}
//
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java b/apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java
new file mode 100644
index 0000000..53a1bed
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java
@@ -0,0 +1,55 @@
+/*
+ * 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.util;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.os.UserHandle;
+
+/**
+ * Utilities for interacting with {@link android.content.pm.PackageManager},
+ * {@link android.os.UserHandle}, and other parts of dealing with apps and binder.
+ *
+ * @hide
+ */
+public class PackageUtil {
+ private PackageUtil() {}
+
+ /**
+ * Finds the UID of the {@code packageName}. Returns {@link Process#INVALID_UID} if unable to
+ * find the UID.
+ */
+ public static int getPackageUidAsUser(
+ @NonNull Context context, @NonNull String packageName, @NonNull UserHandle user) {
+ Context userContext = context.createContextAsUser(user, /*flags=*/ 0);
+ return getPackageUid(userContext, packageName);
+ }
+
+ /**
+ * Finds the UID of the {@code packageName} in the given {@code context}. Returns
+ * {@link Process#INVALID_UID} if unable to find the UID.
+ */
+ public static int getPackageUid(@NonNull Context context, @NonNull String packageName) {
+ try {
+ return context.getPackageManager().getPackageUid(packageName, /*flags=*/ 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return Process.INVALID_UID;
+ }
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleDocument.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleDocument.java
index bf8051b..0b4e196 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleDocument.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleDocument.java
@@ -16,12 +16,11 @@
package com.android.server.appsearch.visibilitystore;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.PackageIdentifier;
-import androidx.annotation.Nullable;
-
/**
* Holds configuration about a package+cert that can access a schema.
*
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityDocument.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityDocument.java
index f2b2621..1771b1d 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityDocument.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityDocument.java
@@ -16,11 +16,10 @@
package com.android.server.appsearch.visibilitystore;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
-import androidx.annotation.Nullable;
-
/** Holds the visibility settings that apply to a package's databases. */
class VisibilityDocument extends GenericDocument {
/** Schema type for documents that hold AppSearch's metadata, e.g. visibility settings */
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 acff792..95ed368 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
@@ -18,7 +18,6 @@
import static android.Manifest.permission.READ_GLOBAL_APP_SEARCH_DATA;
import android.annotation.NonNull;
-import android.annotation.UserIdInt;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
@@ -27,7 +26,6 @@
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.os.Process;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -35,6 +33,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
+import com.android.server.appsearch.util.PackageUtil;
import com.google.android.icing.proto.PersistType;
@@ -67,9 +66,6 @@
* @hide
*/
public class VisibilityStore {
-
- private static final String TAG = "AppSearchVisibilityStore";
-
/** No-op user id that won't have any visibility settings. */
public static final int NO_OP_USER_ID = -1;
@@ -95,9 +91,6 @@
// Context of the user that the call is being made as.
private final Context mUserContext;
- // User ID of the caller who we're checking visibility settings for.
- private final int mUserId;
-
/** Stores the schemas that are platform-hidden. All values are prefixed. */
private final NotPlatformSurfaceableMap mNotPlatformSurfaceableMap =
new NotPlatformSurfaceableMap();
@@ -112,13 +105,9 @@
* @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,
- @UserIdInt int userId) {
+ public VisibilityStore(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext) {
mAppSearchImpl = appSearchImpl;
- mUserContext = userContext;
- mUserId = userId;
+ mUserContext = Objects.requireNonNull(userContext);
}
/**
@@ -348,6 +337,9 @@
Set<PackageIdentifier> packageIdentifiers =
mPackageAccessibleMap.getAccessiblePackages(
packageName, databaseName, prefixedSchema);
+ if (packageIdentifiers.isEmpty()) {
+ return false;
+ }
for (PackageIdentifier packageIdentifier : packageIdentifiers) {
// TODO(b/169883602): Consider caching the UIDs of packages. Looking this up in the
// package manager could be costly. We would also need to update the cache on
@@ -357,9 +349,10 @@
// the callerUid since clients can createContextAsUser with some other user, and then
// make calls to us. So just check if the appId portion of the uid is the same. This is
// essentially UserHandle.isSameApp, but that's not a system API for us to use.
- int callerAppId = UserHandle.getAppId((callerUid));
- int userAppId =
- UserHandle.getAppId(getPackageUidAsUser(packageIdentifier.getPackageName()));
+ int callerAppId = UserHandle.getAppId(callerUid);
+ int packageUid =
+ PackageUtil.getPackageUid(mUserContext, packageIdentifier.getPackageName());
+ int userAppId = UserHandle.getAppId(packageUid);
if (callerAppId != userAppId) {
continue;
}
@@ -401,17 +394,4 @@
@NonNull String packageName, @NonNull String databaseName) {
return ID_PREFIX + PrefixUtil.createPrefix(packageName, databaseName);
}
-
- /**
- * Finds the UID of the {@code packageName}. Returns {@link Process#INVALID_UID} if unable to
- * find the UID.
- */
- private int getPackageUidAsUser(@NonNull String packageName) {
- try {
- return mUserContext.getPackageManager().getPackageUidAsUser(packageName, mUserId);
- } catch (PackageManager.NameNotFoundException e) {
- // Package doesn't exist, continue
- }
- return Process.INVALID_UID;
- }
}
diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
index 9fa7810..1efe5cb 100644
--- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java
+++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
@@ -662,10 +662,19 @@
* scheduled as exact. Applications are strongly discouraged from using exact
* alarms unnecessarily as they reduce the OS's ability to minimize battery use.
*
- * <p>
- * Starting with {@link Build.VERSION_CODES#S}, apps require the
+ * <p class="note"><strong>Note:</strong>
+ * Starting with {@link Build.VERSION_CODES#S}, apps targeting SDK level 31 or higher
+ * need to request the
* {@link Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM} permission to use this
- * API.
+ * API, unless the app is exempt from battery restrictions.
+ * The user and the system can revoke this permission via the special app access screen in
+ * Settings.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Exact alarms should only be used for user-facing features.
+ * For more details, see <a
+ * href="{@docRoot}about/versions/12/behavior-changes-12#exact-alarm-permission">
+ * Exact alarm permission</a>.
*
* @param type type of alarm.
* @param triggerAtMillis time in milliseconds that the alarm should go
@@ -685,6 +694,7 @@
* @see #ELAPSED_REALTIME_WAKEUP
* @see #RTC
* @see #RTC_WAKEUP
+ * @see Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM
*/
@RequiresPermission(value = Manifest.permission.SCHEDULE_EXACT_ALARM, conditional = true)
public void setExact(@AlarmType int type, long triggerAtMillis, PendingIntent operation) {
@@ -701,10 +711,21 @@
* invoked via the specified target Handler, or on the application's main looper
* if {@code null} is passed as the {@code targetHandler} parameter.
*
- * <p>
- * Starting with {@link Build.VERSION_CODES#S}, apps require the
+ * <p class="note"><strong>Note:</strong>
+ * Starting with {@link Build.VERSION_CODES#S}, apps targeting SDK level 31 or higher
+ * need to request the
* {@link Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM} permission to use this
- * API.
+ * API, unless the app is exempt from battery restrictions.
+ * The user and the system can revoke this permission via the special app access screen in
+ * Settings.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Exact alarms should only be used for user-facing features.
+ * For more details, see <a
+ * href="{@docRoot}about/versions/12/behavior-changes-12#exact-alarm-permission">
+ * Exact alarm permission</a>.
+ *
+ * @see Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM
*/
@RequiresPermission(value = Manifest.permission.SCHEDULE_EXACT_ALARM, conditional = true)
public void setExact(@AlarmType int type, long triggerAtMillis, String tag,
@@ -745,9 +766,21 @@
* This method is like {@link #setExact(int, long, PendingIntent)}, but implies
* {@link #RTC_WAKEUP}.
*
- * <p>
- * Starting from API {@link Build.VERSION_CODES#S}, using this method requires the
- * {@link Manifest.permission#SCHEDULE_EXACT_ALARM} permission. Alarms scheduled via this API
+ * <p class="note"><strong>Note:</strong>
+ * Starting with {@link Build.VERSION_CODES#S}, apps targeting SDK level 31 or higher
+ * need to request the
+ * {@link Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM} permission to use this
+ * API.
+ * The user and the system can revoke this permission via the special app access screen in
+ * Settings.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Exact alarms should only be used for user-facing features.
+ * For more details, see <a
+ * href="{@docRoot}about/versions/12/behavior-changes-12#exact-alarm-permission">
+ * Exact alarm permission</a>.
+ *
+ * <p>Alarms scheduled via this API
* will be allowed to start a foreground service even if the app is in the background.
*
* @param info
@@ -764,6 +797,7 @@
* @see android.content.Context#sendBroadcast
* @see android.content.Context#registerReceiver
* @see android.content.Intent#filterEquals
+ * @see Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM
*/
@RequiresPermission(Manifest.permission.SCHEDULE_EXACT_ALARM)
public void setAlarmClock(AlarmClockInfo info, PendingIntent operation) {
@@ -1090,11 +1124,22 @@
* device is idle it may take even more liberties with scheduling in order to optimize
* for battery life.</p>
*
- * <p>
- * Starting from API {@link Build.VERSION_CODES#S}, using this method requires the
- * {@link Manifest.permission#SCHEDULE_EXACT_ALARM} permission, unless the app is exempt from
- * battery restrictions. Alarms scheduled via this API will be allowed to start a foreground
- * service even if the app is in the background.
+ * <p class="note"><strong>Note:</strong>
+ * Starting with {@link Build.VERSION_CODES#S}, apps targeting SDK level 31 or higher
+ * need to request the
+ * {@link Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM} permission to use this
+ * API, unless the app is exempt from battery restrictions.
+ * The user and the system can revoke this permission via the special app access screen in
+ * Settings.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Exact alarms should only be used for user-facing features.
+ * For more details, see <a
+ * href="{@docRoot}about/versions/12/behavior-changes-12#exact-alarm-permission">
+ * Exact alarm permission</a>.
+ *
+ * <p>Alarms scheduled via this API
+ * will be allowed to start a foreground service even if the app is in the background.
*
* @param type type of alarm.
* @param triggerAtMillis time in milliseconds that the alarm should go
@@ -1114,6 +1159,7 @@
* @see #ELAPSED_REALTIME_WAKEUP
* @see #RTC
* @see #RTC_WAKEUP
+ * @see Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM
*/
@RequiresPermission(value = Manifest.permission.SCHEDULE_EXACT_ALARM, conditional = true)
public void setExactAndAllowWhileIdle(@AlarmType int type, long triggerAtMillis,
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index cef065d..0e9efbc 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -1536,13 +1536,14 @@
@VisibleForTesting
static final int MSG_REPORT_STATIONARY_STATUS = 7;
private static final int MSG_FINISH_IDLE_OP = 8;
- private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED_TO_NPMS = 9;
private static final int MSG_SEND_CONSTRAINT_MONITORING = 10;
@VisibleForTesting
static final int MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR = 11;
@VisibleForTesting
static final int MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR = 12;
private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 13;
+ private static final int MSG_REPORT_TEMP_APP_WHITELIST_ADDED_TO_NPMS = 14;
+ private static final int MSG_REPORT_TEMP_APP_WHITELIST_REMOVED_TO_NPMS = 15;
final class MyHandler extends Handler {
MyHandler(Looper looper) {
@@ -1659,10 +1660,17 @@
}
}
} break;
- case MSG_REPORT_TEMP_APP_WHITELIST_CHANGED_TO_NPMS: {
+ case MSG_REPORT_TEMP_APP_WHITELIST_ADDED_TO_NPMS: {
final int appId = msg.arg1;
- final boolean added = (msg.arg2 == 1);
- mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, added);
+ final int reasonCode = msg.arg2;
+ final String reason = (String) msg.obj;
+ mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, true,
+ reasonCode, reason);
+ } break;
+ case MSG_REPORT_TEMP_APP_WHITELIST_REMOVED_TO_NPMS: {
+ final int appId = msg.arg1;
+ mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, false,
+ REASON_UNKNOWN, /* reason= */ null);
} break;
case MSG_SEND_CONSTRAINT_MONITORING: {
final IDeviceIdleConstraint constraint = (IDeviceIdleConstraint) msg.obj;
@@ -2811,14 +2819,15 @@
// NPMS needs to update its state synchronously in certain situations so we
// can't have it use the TempAllowlistChangeListener path right now.
// TODO: see if there's a way to simplify/consolidate
- mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED_TO_NPMS, appId, 1)
- .sendToTarget();
+ mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_ADDED_TO_NPMS, appId,
+ reasonCode, reason).sendToTarget();
}
reportTempWhitelistChangedLocked(uid, true);
}
}
if (informWhitelistChanged) {
- mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, true);
+ mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, true,
+ reasonCode, reason);
}
}
@@ -2890,8 +2899,8 @@
final int appId = UserHandle.getAppId(uid);
updateTempWhitelistAppIdsLocked(uid, false, 0, 0, REASON_UNKNOWN,
reason, INVALID_UID);
- mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED_TO_NPMS, appId, 0)
- .sendToTarget();
+ mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_REMOVED_TO_NPMS, appId,
+ /* unused= */ 0).sendToTarget();
reportTempWhitelistChangedLocked(uid, false);
try {
mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
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 1169391..fe0c7f7 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -136,6 +136,8 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.usage.AppStandbyInternal;
import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
@@ -215,9 +217,18 @@
final Object mLock = new Object();
- /** Immutable set of app ids that have requested SCHEDULE_EXACT_ALARM permission.*/
+ /** Immutable set of app ids requesting {@link Manifest.permission#SCHEDULE_EXACT_ALARM} */
@VisibleForTesting
volatile Set<Integer> mExactAlarmCandidates = Collections.emptySet();
+
+ /**
+ * A map from uid to the last op-mode we have seen for
+ * {@link AppOpsManager#OP_SCHEDULE_EXACT_ALARM}
+ */
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ SparseIntArray mLastOpScheduleExactAlarm = new SparseIntArray();
+
// List of alarms per uid deferred due to user applied background restrictions on the source app
SparseArray<ArrayList<Alarm>> mPendingBackgroundAlarms = new SparseArray<>();
private long mNextWakeup;
@@ -522,6 +533,9 @@
static final String KEY_MIN_DEVICE_IDLE_FUZZ = "min_device_idle_fuzz";
@VisibleForTesting
static final String KEY_MAX_DEVICE_IDLE_FUZZ = "max_device_idle_fuzz";
+ @VisibleForTesting
+ static final String KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED =
+ "kill_on_schedule_exact_alarm_revoked";
private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
@@ -564,6 +578,8 @@
private static final long DEFAULT_MIN_DEVICE_IDLE_FUZZ = 2 * 60_000;
private static final long DEFAULT_MAX_DEVICE_IDLE_FUZZ = 15 * 60_000;
+ private static final boolean DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = true;
+
// Minimum futurity of a new alarm
public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
@@ -644,6 +660,13 @@
*/
public long MAX_DEVICE_IDLE_FUZZ = DEFAULT_MAX_DEVICE_IDLE_FUZZ;
+ /**
+ * Whether or not to kill app when the permission
+ * {@link Manifest.permission#SCHEDULE_EXACT_ALARM} is revoked.
+ */
+ public boolean KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED =
+ DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED;
+
private long mLastAllowWhileIdleWhitelistDuration = -1;
private int mVersion = 0;
@@ -816,6 +839,11 @@
deviceIdleFuzzBoundariesUpdated = true;
}
break;
+ case KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED:
+ KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = properties.getBoolean(
+ KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED,
+ DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED);
+ break;
default:
if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
// The quotas need to be updated in order, so we can't just rely
@@ -830,17 +858,24 @@
}
private void updateExactAlarmDenyList(String[] newDenyList) {
+ final Set<String> newSet = Collections.unmodifiableSet(new ArraySet<>(newDenyList));
+ final Set<String> removed = new ArraySet<>(EXACT_ALARM_DENY_LIST);
+ final Set<String> added = new ArraySet<>(newDenyList);
+
+ added.removeAll(EXACT_ALARM_DENY_LIST);
+ removed.removeAll(newSet);
+ if (added.size() > 0) {
+ mHandler.obtainMessage(AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_ADDED, added)
+ .sendToTarget();
+ }
+ if (removed.size() > 0) {
+ mHandler.obtainMessage(AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED, removed)
+ .sendToTarget();
+ }
if (newDenyList.length == 0) {
EXACT_ALARM_DENY_LIST = Collections.emptySet();
} else {
- final Set<String> oldSet = EXACT_ALARM_DENY_LIST;
- final Set<String> newlyAdded = new ArraySet<>(newDenyList);
- EXACT_ALARM_DENY_LIST = Collections.unmodifiableSet(new ArraySet<>(newlyAdded));
- newlyAdded.removeAll(oldSet);
- if (newlyAdded.size() > 0) {
- mHandler.obtainMessage(AlarmHandler.EXACT_ALARM_DENY_LIST_CHANGED, newlyAdded)
- .sendToTarget();
- }
+ EXACT_ALARM_DENY_LIST = newSet;
}
}
@@ -1007,6 +1042,20 @@
pw.print(KEY_EXACT_ALARM_DENY_LIST, EXACT_ALARM_DENY_LIST);
pw.println();
+ pw.print(KEY_MIN_DEVICE_IDLE_FUZZ);
+ pw.print("=");
+ TimeUtils.formatDuration(MIN_DEVICE_IDLE_FUZZ, pw);
+ pw.println();
+
+ pw.print(KEY_MAX_DEVICE_IDLE_FUZZ);
+ pw.print("=");
+ TimeUtils.formatDuration(MAX_DEVICE_IDLE_FUZZ, pw);
+ pw.println();
+
+ pw.print(KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED,
+ KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED);
+ pw.println();
+
pw.decreaseIndent();
}
@@ -1667,16 +1716,57 @@
void refreshExactAlarmCandidates() {
final String[] candidates = mLocalPermissionManager.getAppOpPermissionPackages(
Manifest.permission.SCHEDULE_EXACT_ALARM);
- final Set<Integer> appIds = new ArraySet<>(candidates.length);
+ final Set<Integer> newAppIds = new ArraySet<>(candidates.length);
for (final String candidate : candidates) {
final int uid = mPackageManagerInternal.getPackageUid(candidate,
PackageManager.MATCH_ANY_USER, USER_SYSTEM);
if (uid > 0) {
- appIds.add(UserHandle.getAppId(uid));
+ newAppIds.add(UserHandle.getAppId(uid));
+ }
+ }
+ final ArraySet<Integer> removed = new ArraySet<>(mExactAlarmCandidates);
+ removed.removeAll(newAppIds);
+ // This code is only called on package_added and boot. The set {removed} is only expected to
+ // be non-empty when a package was updated and it removed the permission from its manifest.
+ for (int i = 0; i < removed.size(); i++) {
+ final int removedAppId = removed.valueAt(i);
+ synchronized (mLock) {
+ Slog.i(TAG, "App id " + removedAppId + " lost SCHEDULE_EXACT_ALARM on update");
+
+ final Predicate<Alarm> whichAlarms = a -> {
+ if (UserHandle.getAppId(a.uid) != removedAppId || a.windowLength != 0) {
+ return false;
+ }
+ if (!isExactAlarmChangeEnabled(a.packageName, UserHandle.getUserId(a.uid))) {
+ return false;
+ }
+ return a.alarmClock != null || !isExemptFromExactAlarmPermission(a.uid);
+ };
+ removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_EXACT_PERMISSION_REVOKED);
}
}
// No need to lock. Assignment is always atomic.
- mExactAlarmCandidates = Collections.unmodifiableSet(appIds);
+ mExactAlarmCandidates = Collections.unmodifiableSet(newAppIds);
+ }
+
+ @Override
+ public void onUserStarting(TargetUser user) {
+ super.onUserStarting(user);
+ final int userId = user.getUserIdentifier();
+ mHandler.post(() -> {
+ for (final int appId : mExactAlarmCandidates) {
+ final int uid = UserHandle.getUid(userId, appId);
+ final AndroidPackage androidPackage = mPackageManagerInternal.getPackage(uid);
+ // It will be null if it is not installed on the starting user.
+ if (androidPackage != null) {
+ final int mode = mAppOps.checkOpNoThrow(AppOpsManager.OP_SCHEDULE_EXACT_ALARM,
+ uid, androidPackage.getPackageName());
+ synchronized (mLock) {
+ mLastOpScheduleExactAlarm.put(uid, mode);
+ }
+ }
+ }
+ });
}
@Override
@@ -1706,17 +1796,44 @@
@Override
public void opChanged(int op, int uid, String packageName)
throws RemoteException {
- if (op != AppOpsManager.OP_SCHEDULE_EXACT_ALARM) {
+ final int userId = UserHandle.getUserId(uid);
+ if (op != AppOpsManager.OP_SCHEDULE_EXACT_ALARM
+ || !isExactAlarmChangeEnabled(packageName, userId)) {
return;
}
- if (!hasScheduleExactAlarmInternal(packageName, uid)) {
+
+ final boolean requested = mExactAlarmCandidates.contains(
+ UserHandle.getAppId(uid));
+ final boolean denyListed =
+ mConstants.EXACT_ALARM_DENY_LIST.contains(packageName);
+
+ final int newMode = mAppOps.checkOpNoThrow(
+ AppOpsManager.OP_SCHEDULE_EXACT_ALARM, uid, packageName);
+
+ final int oldMode;
+ synchronized (mLock) {
+ final int index = mLastOpScheduleExactAlarm.indexOfKey(uid);
+ if (index < 0) {
+ oldMode = AppOpsManager.opToDefaultMode(
+ AppOpsManager.OP_SCHEDULE_EXACT_ALARM);
+ mLastOpScheduleExactAlarm.put(uid, newMode);
+ } else {
+ oldMode = mLastOpScheduleExactAlarm.valueAt(index);
+ mLastOpScheduleExactAlarm.setValueAt(index, newMode);
+ }
+ }
+
+ final boolean hadPermission = getScheduleExactAlarmState(requested,
+ denyListed, oldMode);
+ final boolean hasPermission = getScheduleExactAlarmState(requested,
+ denyListed, newMode);
+
+ if (hadPermission && !hasPermission) {
mHandler.obtainMessage(AlarmHandler.REMOVE_EXACT_ALARMS,
uid, 0, packageName).sendToTarget();
- } else {
- // TODO(b/187206399) Make sure this won't be sent, if the app
- // already had the appop previously.
+ } else if (!hadPermission && hasPermission) {
sendScheduleExactAlarmPermissionStateChangedBroadcast(
- packageName, UserHandle.getUserId(uid));
+ packageName, userId);
}
}
});
@@ -2256,12 +2373,28 @@
}
}
+ private static boolean getScheduleExactAlarmState(boolean requested, boolean denyListed,
+ int appOpMode) {
+ if (!requested) {
+ return false;
+ }
+ if (appOpMode == AppOpsManager.MODE_DEFAULT) {
+ return !denyListed;
+ }
+ return appOpMode == AppOpsManager.MODE_ALLOWED;
+ }
+
boolean hasScheduleExactAlarmInternal(String packageName, int uid) {
+ // Not using getScheduleExactAlarmState as this can avoid some calls to AppOpsService.
+ // Not using #mLastOpScheduleExactAlarm as it may contain stale values.
+ // No locking needed as all internal containers being queried are immutable.
+
final long start = mStatLogger.getTime();
final boolean hasPermission;
- // No locking needed as all internal containers being queried are immutable.
if (!mExactAlarmCandidates.contains(UserHandle.getAppId(uid))) {
hasPermission = false;
+ } else if (!isExactAlarmChangeEnabled(packageName, UserHandle.getUserId(uid))) {
+ hasPermission = false;
} else {
final int mode = mAppOps.checkOpNoThrow(AppOpsManager.OP_SCHEDULE_EXACT_ALARM, uid,
packageName);
@@ -2368,8 +2501,7 @@
} else if (exact || allowWhileIdle) {
final boolean needsPermission;
boolean lowerQuota;
- if (CompatChanges.isChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
- callingPackage, UserHandle.of(callingUserId))) {
+ if (isExactAlarmChangeEnabled(callingPackage, callingUserId)) {
needsPermission = exact;
lowerQuota = !exact;
idleOptions = exact ? mOptsWithFgs.toBundle() : mOptsWithoutFgs.toBundle();
@@ -2524,6 +2656,11 @@
}
};
+ private static boolean isExactAlarmChangeEnabled(String packageName, int userId) {
+ return CompatChanges.isChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
+ packageName, UserHandle.of(userId));
+ }
+
void dumpImpl(IndentingPrintWriter pw) {
synchronized (mLock) {
pw.println("Current Alarm Manager state:");
@@ -2673,6 +2810,17 @@
pw.println("App ids requesting SCHEDULE_EXACT_ALARM: " + mExactAlarmCandidates);
pw.println();
+ pw.print("Last OP_SCHEDULE_EXACT_ALARM: [");
+ for (int i = 0; i < mLastOpScheduleExactAlarm.size(); i++) {
+ if (i > 0) {
+ pw.print(", ");
+ }
+ UserHandle.formatUid(pw, mLastOpScheduleExactAlarm.keyAt(i));
+ pw.print(":" + AppOpsManager.modeToName(mLastOpScheduleExactAlarm.valueAt(i)));
+ }
+ pw.println("]");
+
+ pw.println();
pw.println("Next alarm clock information: ");
pw.increaseIndent();
final TreeSet<Integer> users = new TreeSet<>();
@@ -3362,30 +3510,58 @@
}
/**
- * Called when some packages are added to the {@link Constants#EXACT_ALARM_DENY_LIST}, as this
- * may cause some of them to lose their permission.
+ * Called when the {@link Constants#EXACT_ALARM_DENY_LIST}, changes with the packages that
+ * either got added or deleted.
+ * These packages may lose or gain the SCHEDULE_EXACT_ALARM permission.
*
- * Note that these packages don't need to be installed on the device, but if they do have an
- * exact alarm scheduled and they lose the permission, this alarm will be canceled.
+ * Note that these packages don't need to be installed on the device, but if they are and they
+ * do undergo a permission change, we will handle them appropriately.
*
+ * This should not be called with the lock held as it calls out to other services.
* This is not expected to get called frequently.
*/
- void handlePackagesAddedToExactAlarmsDenyListLocked(ArraySet<String> packageNames) {
- Slog.w(TAG, "Packages " + packageNames + " added to the exact alarm deny list.");
- final Predicate<Alarm> whichAlarms = a -> {
- if (!packageNames.contains(a.packageName) || a.windowLength != 0) {
- return false;
+ void handleChangesToExactAlarmDenyList(ArraySet<String> changedPackages, boolean added) {
+ Slog.w(TAG, "Packages " + changedPackages + (added ? " added to" : " removed from")
+ + " the exact alarm deny list.");
+
+ final int[] startedUserIds = mActivityManagerInternal.getStartedUserIds();
+
+ for (int i = 0; i < changedPackages.size(); i++) {
+ final String changedPackage = changedPackages.valueAt(i);
+ for (final int userId : startedUserIds) {
+ final int uid = mPackageManagerInternal.getPackageUid(changedPackage, 0, userId);
+ if (uid <= 0) {
+ continue;
+ }
+ if (!isExactAlarmChangeEnabled(changedPackage, userId)) {
+ continue;
+ }
+ final int appOpMode;
+ synchronized (mLock) {
+ appOpMode = mLastOpScheduleExactAlarm.get(uid,
+ AppOpsManager.opToDefaultMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM));
+ }
+ final boolean requested = mExactAlarmCandidates.contains(UserHandle.getAppId(uid));
+
+ // added: true => package was added to the deny list
+ // added: false => package was removed from the deny list
+ final boolean hadPermission = getScheduleExactAlarmState(requested, !added,
+ appOpMode);
+ final boolean hasPermission = getScheduleExactAlarmState(requested, added,
+ appOpMode);
+
+ if (hadPermission == hasPermission) {
+ continue;
+ }
+ if (added) {
+ synchronized (mLock) {
+ removeExactAlarmsOnPermissionRevokedLocked(uid, changedPackage);
+ }
+ } else {
+ sendScheduleExactAlarmPermissionStateChangedBroadcast(changedPackage, userId);
+ }
}
- if (!CompatChanges.isChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
- a.packageName, UserHandle.getUserHandleForUid(a.uid))) {
- return false;
- }
- if (a.alarmClock == null && isExemptFromExactAlarmPermission(a.uid)) {
- return false;
- }
- return !hasScheduleExactAlarmInternal(a.packageName, a.uid);
- };
- removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_EXACT_PERMISSION_REVOKED);
+ }
}
/**
@@ -3396,9 +3572,7 @@
*/
void removeExactAlarmsOnPermissionRevokedLocked(int uid, String packageName) {
Slog.w(TAG, "Package " + packageName + ", uid " + uid + " lost SCHEDULE_EXACT_ALARM!");
- if (!CompatChanges.isChangeEnabled(
- AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
- packageName, UserHandle.getUserHandleForUid(uid))) {
+ if (!isExactAlarmChangeEnabled(packageName, UserHandle.getUserId(uid))) {
return;
}
@@ -3409,6 +3583,11 @@
return false;
};
removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_EXACT_PERMISSION_REVOKED);
+
+ if (mConstants.KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED) {
+ PermissionManagerService.killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid),
+ "schedule_exact_alarm revoked");
+ }
}
private void removeAlarmsInternalLocked(Predicate<Alarm> whichAlarms, int reason) {
@@ -3535,6 +3714,11 @@
mRemovalHistory.removeAt(i);
}
}
+ for (int i = mLastOpScheduleExactAlarm.size() - 1; i >= 0; i--) {
+ if (UserHandle.getUserId(mLastOpScheduleExactAlarm.keyAt(i)) == userHandle) {
+ mLastOpScheduleExactAlarm.removeAt(i);
+ }
+ }
}
void interactiveStateChangedLocked(boolean interactive) {
@@ -4091,8 +4275,9 @@
public static final int CHARGING_STATUS_CHANGED = 6;
public static final int REMOVE_FOR_CANCELED = 7;
public static final int REMOVE_EXACT_ALARMS = 8;
- public static final int EXACT_ALARM_DENY_LIST_CHANGED = 9;
- public static final int REFRESH_EXACT_ALARM_CANDIDATES = 10;
+ public static final int EXACT_ALARM_DENY_LIST_PACKAGES_ADDED = 9;
+ public static final int EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED = 10;
+ public static final int REFRESH_EXACT_ALARM_CANDIDATES = 11;
AlarmHandler() {
super(Looper.myLooper());
@@ -4179,10 +4364,11 @@
removeExactAlarmsOnPermissionRevokedLocked(uid, packageName);
}
break;
- case EXACT_ALARM_DENY_LIST_CHANGED:
- synchronized (mLock) {
- handlePackagesAddedToExactAlarmsDenyListLocked((ArraySet<String>) msg.obj);
- }
+ case EXACT_ALARM_DENY_LIST_PACKAGES_ADDED:
+ handleChangesToExactAlarmDenyList((ArraySet<String>) msg.obj, true);
+ break;
+ case EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED:
+ handleChangesToExactAlarmDenyList((ArraySet<String>) msg.obj, false);
break;
case REFRESH_EXACT_ALARM_CANDIDATES:
refreshExactAlarmCandidates();
@@ -4349,6 +4535,7 @@
case Intent.ACTION_UID_REMOVED:
mLastPriorityAlarmDispatch.delete(uid);
mRemovalHistory.delete(uid);
+ mLastOpScheduleExactAlarm.delete(uid);
return;
case Intent.ACTION_PACKAGE_REMOVED:
if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
diff --git a/apex/media/Android.bp b/apex/media/Android.bp
index a75f1ae..f2e64ce 100644
--- a/apex/media/Android.bp
+++ b/apex/media/Android.bp
@@ -27,7 +27,9 @@
sdk {
name: "media-module-sdk",
+ bootclasspath_fragments: ["com.android.media-bootclasspath-fragment"],
java_sdk_libs: [
"framework-media",
+ "service-media-s",
],
}
diff --git a/apex/media/framework/java/android/media/MediaSession2.java b/apex/media/framework/java/android/media/MediaSession2.java
index 7697359..e76d61c 100644
--- a/apex/media/framework/java/android/media/MediaSession2.java
+++ b/apex/media/framework/java/android/media/MediaSession2.java
@@ -469,7 +469,9 @@
}
mCallbackExecutor.execute(() -> {
if (!controllerInfo.removeRequestedCommandSeqNumber(seq)) {
- resultReceiver.send(RESULT_INFO_SKIPPED, null);
+ if (resultReceiver != null) {
+ resultReceiver.send(RESULT_INFO_SKIPPED, null);
+ }
return;
}
Session2Command.Result result = mCallback.onSessionCommand(
diff --git a/core/api/module-lib-lint-baseline.txt b/core/api/module-lib-lint-baseline.txt
new file mode 100644
index 0000000..0c1ebb3
--- /dev/null
+++ b/core/api/module-lib-lint-baseline.txt
@@ -0,0 +1,39 @@
+// Baseline format: 1.0
+SamShouldBeLast: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.app.ActivityManager.addOnUidImportanceListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.PendingIntent#send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler):
+ SAM-compatible parameters (such as parameter 4, "onFinished", in android.app.PendingIntent.send) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.PendingIntent#send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, String):
+ SAM-compatible parameters (such as parameter 4, "onFinished", in android.app.PendingIntent.send) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.PendingIntent#send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, String, android.os.Bundle):
+ SAM-compatible parameters (such as parameter 4, "onFinished", in android.app.PendingIntent.send) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.PendingIntent#send(int, android.app.PendingIntent.OnFinished, android.os.Handler):
+ SAM-compatible parameters (such as parameter 2, "onFinished", in android.app.PendingIntent.send) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioManager#abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes):
+ SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.abandonAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int):
+ SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.requestAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy):
+ SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.requestAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
+ SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.requestAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName):
+ SAM-compatible parameters (such as parameter 1, "sessionListener", in android.media.session.MediaSessionManager.addOnActiveSessionsChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "sessionListener", in android.media.session.MediaSessionManager.addOnActiveSessionsChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.session.MediaSessionManager#addOnSession2TokensChangedListener(android.media.session.MediaSessionManager.OnSession2TokensChangedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.session.MediaSessionManager.addOnSession2TokensChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.session.MediaSessionManager#setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.session.MediaSessionManager.setOnMediaKeyListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.session.MediaSessionManager#setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.session.MediaSessionManager.setOnVolumeKeyLongPressListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.os.Binder#attachInterface(android.os.IInterface, String):
+ SAM-compatible parameters (such as parameter 1, "owner", in android.os.Binder.attachInterface) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.os.Binder#linkToDeath(android.os.IBinder.DeathRecipient, int):
+ SAM-compatible parameters (such as parameter 1, "recipient", in android.os.Binder.linkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.os.Binder#unlinkToDeath(android.os.IBinder.DeathRecipient, int):
+ SAM-compatible parameters (such as parameter 1, "recipient", in android.os.Binder.unlinkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.os.IBinder#linkToDeath(android.os.IBinder.DeathRecipient, int):
+ SAM-compatible parameters (such as parameter 1, "recipient", in android.os.IBinder.linkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.os.IBinder#unlinkToDeath(android.os.IBinder.DeathRecipient, int):
+ SAM-compatible parameters (such as parameter 1, "recipient", in android.os.IBinder.unlinkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 58f6c52..b435acf 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -1,6 +1,6 @@
// Baseline format: 1.0
ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
-
+
BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex):
@@ -12,23 +12,23 @@
GenericException: android.app.prediction.AppPredictor#finalize():
-
+
GenericException: android.hardware.location.ContextHubClient#finalize():
-
+
GenericException: android.net.IpSecManager.IpSecTunnelInterface#finalize():
-
+
GenericException: android.service.autofill.augmented.FillWindow#finalize():
-
+
IntentBuilderName: android.app.search.SearchAction#getIntent():
-
+
IntentBuilderName: android.app.smartspace.SmartspaceAction#getIntent():
Methods creating an Intent should be named `create<Foo>Intent()`, was `getIntent`
KotlinKeyword: android.app.Notification#when:
-
+
MissingGetterMatchingBuilder: android.security.keystore.KeyGenParameterSpec.Builder#setUid(int):
@@ -42,49 +42,49 @@
MissingNullability: android.media.soundtrigger.SoundTriggerDetectionService#onUnbind(android.content.Intent) parameter #0:
-
+
MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #0:
-
+
MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #1:
-
+
MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #2:
-
+
MissingNullability: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context) parameter #0:
-
+
MissingNullability: android.provider.ContactsContract.MetadataSync#CONTENT_URI:
-
+
MissingNullability: android.provider.ContactsContract.MetadataSync#METADATA_AUTHORITY_URI:
-
+
MissingNullability: android.provider.ContactsContract.MetadataSyncState#CONTENT_URI:
-
+
MissingNullability: android.provider.SearchIndexablesProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo) parameter #0:
-
+
MissingNullability: android.provider.SearchIndexablesProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo) parameter #1:
-
+
MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#onUnbind(android.content.Intent) parameter #0:
-
+
MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
-
+
MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #1:
-
+
MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #2:
-
+
MissingNullability: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context) parameter #0:
-
+
MissingNullability: android.telephony.NetworkService#onUnbind(android.content.Intent) parameter #0:
-
+
MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringDaily(java.time.ZonedDateTime) parameter #0:
-
+
MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringMonthly(java.time.ZonedDateTime) parameter #0:
-
+
MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringWeekly(java.time.ZonedDateTime) parameter #0:
-
+
MissingNullability: android.telephony.data.DataService#onUnbind(android.content.Intent) parameter #0:
-
+
MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String):
-
+
MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0:
-
+
OnNameExpected: android.service.smartspace.SmartspaceService#notifySmartspaceEvent(android.app.smartspace.SmartspaceSessionId, android.app.smartspace.SmartspaceTargetEvent):
@@ -92,178 +92,192 @@
ProtectedMember: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context):
-
+
ProtectedMember: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]):
-
+
ProtectedMember: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context):
-
+
SamShouldBeLast: android.accounts.AccountManager#addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean):
-
+
SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, String[]):
-
+
SamShouldBeLast: android.accounts.AccountManager#confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#editProperties(String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#getAuthTokenByFeatures(String, String, String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#isCredentialsUpdateSuggested(android.accounts.Account, String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#renameAccount(android.accounts.Account, String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#startAddAccountSession(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#startUpdateCredentialsSession(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.accounts.AccountManager#updateCredentials(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-
+
SamShouldBeLast: android.app.AlarmManager#set(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
-
+
SamShouldBeLast: android.app.AlarmManager#setExact(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
-
+
SamShouldBeLast: android.app.AlarmManager#setWindow(int, long, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
-
+
SamShouldBeLast: android.app.WallpaperInfo#dump(android.util.Printer, String):
-
+
SamShouldBeLast: android.app.WallpaperManager#addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler):
-
+
SamShouldBeLast: android.app.admin.DevicePolicyManager#installSystemUpdate(android.content.ComponentName, android.net.Uri, java.util.concurrent.Executor, android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback):
-
+
SamShouldBeLast: android.content.IntentFilter#dump(android.util.Printer, String):
-
+
SamShouldBeLast: android.content.pm.ApplicationInfo#dump(android.util.Printer, String):
-
+
SamShouldBeLast: android.content.pm.PackageItemInfo#dumpBack(android.util.Printer, String):
-
+
SamShouldBeLast: android.content.pm.PackageItemInfo#dumpFront(android.util.Printer, String):
-
+
SamShouldBeLast: android.content.pm.ResolveInfo#dump(android.util.Printer, String):
-
+
SamShouldBeLast: android.location.Location#dump(android.util.Printer, String):
-
+
SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
-
+
SamShouldBeLast: android.location.LocationManager#registerGnssMeasurementsCallback(java.util.concurrent.Executor, android.location.GnssMeasurementsEvent.Callback):
-
+
SamShouldBeLast: android.location.LocationManager#registerGnssNavigationMessageCallback(java.util.concurrent.Executor, android.location.GnssNavigationMessage.Callback):
-
+
SamShouldBeLast: android.location.LocationManager#registerGnssStatusCallback(java.util.concurrent.Executor, android.location.GnssStatus.Callback):
-
+
SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
-
+
SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, java.util.concurrent.Executor, android.location.LocationListener):
-
+
SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, java.util.concurrent.Executor, android.location.LocationListener):
-
+
SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
-
+
SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, java.util.concurrent.Executor, android.location.LocationListener):
-
+
SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
-
+
SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
-
+
SamShouldBeLast: android.media.AudioFocusRequest.Builder#setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler):
-
+
SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
-
+
SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
-
+
SamShouldBeLast: android.media.AudioRecord#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
-
+
SamShouldBeLast: android.media.AudioRecordingMonitor#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
-
+
SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
-
+
SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
-
+
+SamShouldBeLast: android.media.MediaPlayer#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.MediaPlayer#setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnDrmInfoListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.MediaPlayer#setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnDrmPreparedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.MediaPlayer#setOnMediaTimeDiscontinuityListener(android.media.MediaPlayer.OnMediaTimeDiscontinuityListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnMediaTimeDiscontinuityListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
SAM-compatible parameters (such as parameter 2, "listener", in android.media.MediaPlayer.setOnRtpRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.MediaPlayer#setOnSubtitleDataListener(android.media.MediaPlayer.OnSubtitleDataListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnSubtitleDataListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.MediaRecorder#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
-
+
SamShouldBeLast: android.media.MediaRecorder#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
-
+
SamShouldBeLast: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName):
-
+
SamShouldBeLast: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler):
-
+
SamShouldBeLast: android.media.session.MediaSessionManager#addOnSession2TokensChangedListener(android.media.session.MediaSessionManager.OnSession2TokensChangedListener, android.os.Handler):
-
+
SamShouldBeLast: android.media.session.MediaSessionManager#registerCallback(java.util.concurrent.Executor, android.media.session.MediaSessionManager.Callback):
-
+
SamShouldBeLast: android.nfc.NfcAdapter#enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle):
-
+
SamShouldBeLast: android.nfc.NfcAdapter#ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler):
-
+
SamShouldBeLast: android.nfc.NfcAdapter#setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity):
-
+
SamShouldBeLast: android.nfc.NfcAdapter#setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...):
-
+
SamShouldBeLast: android.nfc.NfcAdapter#setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...):
-
+
SamShouldBeLast: android.os.Binder#attachInterface(android.os.IInterface, String):
-
+
SamShouldBeLast: android.os.Binder#linkToDeath(android.os.IBinder.DeathRecipient, int):
-
+
SamShouldBeLast: android.os.Binder#unlinkToDeath(android.os.IBinder.DeathRecipient, int):
-
+
SamShouldBeLast: android.os.Handler#dump(android.util.Printer, String):
-
+
SamShouldBeLast: android.os.Handler#postAtTime(Runnable, Object, long):
-
+
SamShouldBeLast: android.os.Handler#postAtTime(Runnable, long):
-
+
SamShouldBeLast: android.os.Handler#postDelayed(Runnable, Object, long):
-
+
SamShouldBeLast: android.os.Handler#postDelayed(Runnable, long):
-
+
SamShouldBeLast: android.os.Handler#removeCallbacks(Runnable, Object):
-
+
SamShouldBeLast: android.os.IBinder#linkToDeath(android.os.IBinder.DeathRecipient, int):
-
+
SamShouldBeLast: android.os.IBinder#unlinkToDeath(android.os.IBinder.DeathRecipient, int):
-
+
SamShouldBeLast: android.os.RecoverySystem#verifyPackage(java.io.File, android.os.RecoverySystem.ProgressListener, java.io.File):
-
+
+SamShouldBeLast: android.security.KeyChain#choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, String[], java.security.Principal[], String, int, String):
+ SAM-compatible parameters (such as parameter 2, "response", in android.security.KeyChain.choosePrivateKeyAlias) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.security.KeyChain#choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, String[], java.security.Principal[], android.net.Uri, String):
+ SAM-compatible parameters (such as parameter 2, "response", in android.security.KeyChain.choosePrivateKeyAlias) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.view.View#postDelayed(Runnable, long):
-
+
SamShouldBeLast: android.view.View#postOnAnimationDelayed(Runnable, long):
-
+
SamShouldBeLast: android.view.View#scheduleDrawable(android.graphics.drawable.Drawable, Runnable, long):
-
+
SamShouldBeLast: android.view.Window#addOnFrameMetricsAvailableListener(android.view.Window.OnFrameMetricsAvailableListener, android.os.Handler):
-
+
SamShouldBeLast: android.view.accessibility.AccessibilityManager#addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, android.os.Handler):
-
+
SamShouldBeLast: android.view.accessibility.AccessibilityManager#addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, android.os.Handler):
-
+
SamShouldBeLast: android.webkit.WebChromeClient#onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams):
-
+
UserHandleName: android.app.search.SearchAction.Builder#setUserHandle(android.os.UserHandle):
Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `setUserHandle`
UserHandleName: android.app.search.SearchTarget.Builder#setUserHandle(android.os.UserHandle):
-
+
UserHandleName: android.app.smartspace.SmartspaceAction.Builder#setUserHandle(android.os.UserHandle):
Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `setUserHandle`
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 6203239..5fa75dd 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -77,7 +77,7 @@
}
public abstract class AccessibilityService extends android.app.Service {
- field public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 1000; // 0x3e8
+ field public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 333; // 0x14d
}
public class AccessibilityServiceInfo implements android.os.Parcelable {
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 483defa..e91209c 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -685,7 +685,7 @@
* @hide
*/
@TestApi
- public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 1000;
+ public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 333;
/** @hide */
public static final String KEY_ACCESSIBILITY_SCREENSHOT_STATUS =
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 25fd254..317e51c 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -254,6 +254,9 @@
/** Returns the current user id. */
public abstract int getCurrentUserId();
+ /** Returns the currently started user ids. */
+ public abstract int[] getStartedUserIds();
+
/** Returns true if the user is running. */
public abstract boolean isUserRunning(@UserIdInt int userId, int flags);
@@ -604,6 +607,14 @@
String ownerPkgName, int ownerUid);
/**
+ * Effectively PendingIntent.getActivityForUser(), but the PendingIntent is
+ * owned by the given uid rather than by the caller (i.e. the system).
+ */
+ public abstract PendingIntent getPendingIntentActivityAsApp(
+ int requestCode, @NonNull Intent[] intents, int flags, Bundle options,
+ String ownerPkgName, int ownerUid);
+
+ /**
* @return mBootTimeTempAllowlistDuration of ActivityManagerConstants.
*/
public abstract long getBootTimeTempAllowListDuration();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 306b54d..1ce598b 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -56,6 +56,7 @@
import android.view.ViewGroup;
import android.view.Window;
import android.window.IRemoteTransition;
+import android.window.SplashScreen;
import android.window.WindowContainerToken;
import java.lang.annotation.Retention;
@@ -327,6 +328,10 @@
private static final String KEY_LAUNCHED_FROM_BUBBLE =
"android.activity.launchTypeBubble";
+ /** See {@link #setSplashscreenStyle(int)}. */
+ private static final String KEY_SPLASH_SCREEN_STYLE =
+ "android.activity.splashScreenStyle";
+
/** See {@link #setTransientLaunch()}. */
private static final String KEY_TRANSIENT_LAUNCH = "android.activity.transientLaunch";
@@ -415,6 +420,8 @@
private IRemoteTransition mRemoteTransition;
private boolean mOverrideTaskTransition;
private int mSplashScreenThemeResId;
+ @SplashScreen.SplashScreenStyle
+ private int mSplashScreenStyle;
private boolean mRemoveWithTaskOrganizer;
private boolean mLaunchedFromBubble;
private boolean mTransientLaunch;
@@ -1171,6 +1178,7 @@
mRemoveWithTaskOrganizer = opts.getBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER);
mLaunchedFromBubble = opts.getBoolean(KEY_LAUNCHED_FROM_BUBBLE);
mTransientLaunch = opts.getBoolean(KEY_TRANSIENT_LAUNCH);
+ mSplashScreenStyle = opts.getInt(KEY_SPLASH_SCREEN_STYLE);
}
/**
@@ -1365,6 +1373,23 @@
}
/**
+ * Sets the preferred splash screen style.
+ * @hide
+ */
+ public void setSplashscreenStyle(@SplashScreen.SplashScreenStyle int style) {
+ mSplashScreenStyle = style;
+ }
+
+ /**
+ * Gets the preferred splash screen style from caller
+ * @hide
+ */
+ @SplashScreen.SplashScreenStyle
+ public int getSplashScreenStyle() {
+ return mSplashScreenStyle;
+ }
+
+ /**
* Sets whether the activity is to be launched into LockTask mode.
*
* Use this option to start an activity in LockTask mode. Note that only apps permitted by
@@ -1932,6 +1957,9 @@
if (mTransientLaunch) {
b.putBoolean(KEY_TRANSIENT_LAUNCH, mTransientLaunch);
}
+ if (mSplashScreenStyle != 0) {
+ b.putInt(KEY_SPLASH_SCREEN_STYLE, mSplashScreenStyle);
+ }
return b;
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index eb14c11..96d59b8 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -3105,24 +3105,11 @@
*/
public boolean isRecordAudioRestrictionExcept;
- /**
- * Is attribution tag not null and not contained in the package attributions
- */
- public boolean isAttributionTagNotFound = false;
-
public RestrictionBypass(boolean isPrivileged, boolean isRecordAudioRestrictionExcept) {
this.isPrivileged = isPrivileged;
this.isRecordAudioRestrictionExcept = isRecordAudioRestrictionExcept;
}
- public void setIsAttributionTagNotFound(boolean isAttributionTagNotFound) {
- this.isAttributionTagNotFound = isAttributionTagNotFound;
- }
-
- public boolean getIsAttributionTagNotFound() {
- return this.isAttributionTagNotFound;
- }
-
public static RestrictionBypass UNRESTRICTED = new RestrictionBypass(true, true);
}
diff --git a/core/java/android/app/ConfigurationController.java b/core/java/android/app/ConfigurationController.java
index 6d92201..f79e078 100644
--- a/core/java/android/app/ConfigurationController.java
+++ b/core/java/android/app/ConfigurationController.java
@@ -158,10 +158,9 @@
int configDiff;
boolean equivalent;
- final Resources.Theme systemTheme = mActivityThread.getSystemContext().getTheme();
- final Resources.Theme systemUiTheme = mActivityThread.getSystemUiContext().getTheme();
-
synchronized (mResourcesManager) {
+ final Resources.Theme systemTheme = mActivityThread.getSystemContext().getTheme();
+ final Resources.Theme systemUiTheme = mActivityThread.getSystemUiContext().getTheme();
if (mPendingConfiguration != null) {
if (!mPendingConfiguration.isOtherSeqNewer(config)) {
config = mPendingConfiguration;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 89d90a3..313a340 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -686,6 +686,14 @@
boolean enableAppFreezer(in boolean enable);
/**
+ * Suppress or reenable the rate limit on foreground service notification deferral.
+ * This is for use within CTS and is protected by android.permission.WRITE_DEVICE_CONFIG.
+ *
+ * @param enable false to suppress rate-limit policy; true to reenable it.
+ */
+ boolean enableFgsNotificationRateLimit(in boolean enable);
+
+ /**
* Holds the AM lock for the specified amount of milliseconds.
* This is intended for use by the tests that need to imitate lock contention.
* The token should be obtained by
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 62b5ec8..9ed76c1 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -932,6 +932,21 @@
boolean registerAppInfoToArt = false;
if (mDefaultClassLoader == null) {
+ // Setup the dex reporter to notify package manager
+ // of any relevant dex loads. The idle maintenance job will use the information
+ // reported to optimize the loaded dex files.
+ // Note that we only need one global reporter per app.
+ // Make sure we do this before creating the main app classloader for the first time
+ // so that we can capture the complete application startup.
+ //
+ // We should not do this in a zygote context (where mActivityThread will be null),
+ // thus we'll guard against it.
+ // Also, the system server reporter (SystemServerDexLoadReporter) is already registered
+ // when system server starts, so we don't need to do it here again.
+ if (mActivityThread != null && !ActivityThread.isSystem()) {
+ BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
+ }
+
// Temporarily disable logging of disk reads on the Looper thread
// as this is early and necessary.
StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
@@ -1047,14 +1062,6 @@
}
private void registerAppInfoToArt() {
- // Setup the dex reporter to notify package manager
- // of any relevant dex loads. The idle maintenance job will use the information
- // reported to optimize the loaded dex files.
- // Note that we only need one global reporter per app.
- // Make sure we do this before invoking app code for the first time so that we
- // can capture the complete application startup.
- BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
-
// Only set up profile support if the loaded apk has the same uid as the
// current process.
// Currently, we do not support profiling across different apps.
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 0136a35..e68eb74 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -365,6 +365,7 @@
}
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/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
index edd6047..cd82deb 100644
--- a/core/java/android/app/WallpaperColors.java
+++ b/core/java/android/app/WallpaperColors.java
@@ -30,6 +30,7 @@
import android.util.Size;
import com.android.internal.graphics.ColorUtils;
+import com.android.internal.graphics.cam.Cam;
import com.android.internal.graphics.palette.CelebiQuantizer;
import com.android.internal.graphics.palette.Palette;
import com.android.internal.graphics.palette.VariationalKMeansQuantizer;
@@ -43,7 +44,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
+import java.util.Set;
/**
* Provides information about the colors of a wallpaper.
@@ -176,7 +177,7 @@
shouldRecycle = true;
Size optimalSize = calculateOptimalSize(bitmap.getWidth(), bitmap.getHeight());
bitmap = Bitmap.createScaledBitmap(bitmap, optimalSize.getWidth(),
- optimalSize.getHeight(), true /* filter */);
+ optimalSize.getHeight(), false /* filter */);
}
final Palette palette;
@@ -189,7 +190,7 @@
} else {
palette = Palette
.from(bitmap, new CelebiQuantizer())
- .maximumColorCount(5)
+ .maximumColorCount(128)
.resizeBitmapArea(MAX_WALLPAPER_EXTRACTION_AREA)
.generate();
}
@@ -278,7 +279,7 @@
/**
* Constructs a new object from a set of colors, where hints can be specified.
*
- * @param populationByColor Map with keys of colors, and value representing the number of
+ * @param colorToPopulation Map with keys of colors, and value representing the number of
* occurrences of color in the wallpaper.
* @param colorHints A combination of color hints.
* @hide
@@ -286,20 +287,105 @@
* @see WallpaperColors#fromBitmap(Bitmap)
* @see WallpaperColors#fromDrawable(Drawable)
*/
- public WallpaperColors(@NonNull Map<Integer, Integer> populationByColor,
+ public WallpaperColors(@NonNull Map<Integer, Integer> colorToPopulation,
@ColorsHints int colorHints) {
- mAllColors = populationByColor;
+ mAllColors = colorToPopulation;
- ArrayList<Map.Entry<Integer, Integer>> mapEntries = new ArrayList(
- populationByColor.entrySet());
- mapEntries.sort((a, b) ->
- a.getValue().compareTo(b.getValue())
- );
- mMainColors = mapEntries.stream().map(entry -> Color.valueOf(entry.getKey())).collect(
- Collectors.toList());
+ final Map<Integer, Cam> colorToCam = new HashMap<>();
+ for (int color : colorToPopulation.keySet()) {
+ colorToCam.put(color, Cam.fromInt(color));
+ }
+ final double[] hueProportions = hueProportions(colorToCam, colorToPopulation);
+ final Map<Integer, Double> colorToHueProportion = colorToHueProportion(
+ colorToPopulation.keySet(), colorToCam, hueProportions);
+
+ final Map<Integer, Double> colorToScore = new HashMap<>();
+ for (Map.Entry<Integer, Double> mapEntry : colorToHueProportion.entrySet()) {
+ int color = mapEntry.getKey();
+ double proportion = mapEntry.getValue();
+ double score = score(colorToCam.get(color), proportion);
+ colorToScore.put(color, score);
+ }
+ ArrayList<Map.Entry<Integer, Double>> mapEntries = new ArrayList(colorToScore.entrySet());
+ mapEntries.sort((a, b) -> b.getValue().compareTo(a.getValue()));
+
+ List<Integer> colorsByScoreDescending = new ArrayList<>();
+ for (Map.Entry<Integer, Double> colorToScoreEntry : mapEntries) {
+ colorsByScoreDescending.add(colorToScoreEntry.getKey());
+ }
+
+ List<Integer> mainColorInts = new ArrayList<>();
+ findSeedColorLoop:
+ for (int color : colorsByScoreDescending) {
+ Cam cam = colorToCam.get(color);
+ for (int otherColor : mainColorInts) {
+ Cam otherCam = colorToCam.get(otherColor);
+ if (hueDiff(cam, otherCam) < 15) {
+ continue findSeedColorLoop;
+ }
+ }
+ mainColorInts.add(color);
+ }
+ List<Color> mainColors = new ArrayList<>();
+ for (int colorInt : mainColorInts) {
+ mainColors.add(Color.valueOf(colorInt));
+ }
+ mMainColors = mainColors;
mColorHints = colorHints;
}
+ private static double hueDiff(Cam a, Cam b) {
+ return (180f - Math.abs(Math.abs(a.getHue() - b.getHue()) - 180f));
+ }
+
+ private static double score(Cam cam, double proportion) {
+ return cam.getChroma() + (proportion * 100);
+ }
+
+ private static Map<Integer, Double> colorToHueProportion(Set<Integer> colors,
+ Map<Integer, Cam> colorToCam, double[] hueProportions) {
+ Map<Integer, Double> colorToHueProportion = new HashMap<>();
+ for (int color : colors) {
+ final int hue = wrapDegrees(Math.round(colorToCam.get(color).getHue()));
+ double proportion = 0.0;
+ for (int i = hue - 15; i < hue + 15; i++) {
+ proportion += hueProportions[wrapDegrees(i)];
+ }
+ colorToHueProportion.put(color, proportion);
+ }
+ return colorToHueProportion;
+ }
+
+ private static int wrapDegrees(int degrees) {
+ if (degrees < 0) {
+ return (degrees % 360) + 360;
+ } else if (degrees >= 360) {
+ return degrees % 360;
+ } else {
+ return degrees;
+ }
+ }
+
+ private static double[] hueProportions(@NonNull Map<Integer, Cam> colorToCam,
+ Map<Integer, Integer> colorToPopulation) {
+ final double[] proportions = new double[360];
+
+ double totalPopulation = 0;
+ for (Map.Entry<Integer, Integer> entry : colorToPopulation.entrySet()) {
+ totalPopulation += entry.getValue();
+ }
+
+ for (Map.Entry<Integer, Integer> entry : colorToPopulation.entrySet()) {
+ final int color = (int) entry.getKey();
+ final int population = colorToPopulation.get(color);
+ final Cam cam = colorToCam.get(color);
+ final int hue = wrapDegrees(Math.round(cam.getHue()));
+ proportions[hue] = proportions[hue] + ((double) population / totalPopulation);
+ }
+
+ return proportions;
+ }
+
public static final @android.annotation.NonNull Creator<WallpaperColors> CREATOR = new Creator<WallpaperColors>() {
@Override
public WallpaperColors createFromParcel(Parcel in) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8d74796..52c58e1 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6845,6 +6845,10 @@
* <p> Enabling lockdown via {@code lockdownEnabled} argument carries the risk that any failure
* of the VPN provider could break networking for all apps. This method clears any lockdown
* allowlist set by {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)}.
+ * <p> Starting from {@link android.os.Build.VERSION_CODES#S API 31} calling this method with
+ * {@code vpnPackage} set to {@code null} only removes the existing configuration if it was
+ * previously created by this admin. To remove VPN configuration created by the user use
+ * {@link UserManager#DISALLOW_CONFIG_VPN}.
*
* @param vpnPackage The package name for an installed VPN app on the device, or {@code null} to
* remove an existing always-on VPN configuration.
@@ -13084,6 +13088,10 @@
* @see #getCrossProfileCalendarPackages(ComponentName)
* @hide
*/
+ @RequiresPermission(anyOf = {
+ permission.INTERACT_ACROSS_USERS_FULL,
+ permission.INTERACT_ACROSS_USERS
+ }, conditional = true)
public boolean isPackageAllowedToAccessCalendar(@NonNull String packageName) {
throwIfParentInstance("isPackageAllowedToAccessCalendar");
if (mService != null) {
@@ -13112,6 +13120,10 @@
* @see #getCrossProfileCalendarPackages(ComponentName)
* @hide
*/
+ @RequiresPermission(anyOf = {
+ permission.INTERACT_ACROSS_USERS_FULL,
+ permission.INTERACT_ACROSS_USERS
+ })
public @Nullable Set<String> getCrossProfileCalendarPackages() {
throwIfParentInstance("getCrossProfileCalendarPackages");
if (mService != null) {
@@ -13872,8 +13884,7 @@
}
/**
- * Called by device owner or profile owner of an organization-owned managed profile to return
- * whether USB data signaling is currently enabled by the admin.
+ * Returns whether USB data signaling is currently enabled by the admin. Callable by any app.
*
* @return {@code true} if USB data signaling is enabled, {@code false} otherwise.
*/
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 67f5c36..a9bec98 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -265,5 +265,4 @@
*/
public abstract void notifyUnsafeOperationStateChanged(DevicePolicySafetyChecker checker,
@OperationSafetyReason int reason, boolean isSafe);
-
}
diff --git a/core/java/android/app/compat/CompatChanges.java b/core/java/android/app/compat/CompatChanges.java
index 24ca72c..0e31567 100644
--- a/core/java/android/app/compat/CompatChanges.java
+++ b/core/java/android/app/compat/CompatChanges.java
@@ -119,7 +119,7 @@
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
try {
- platformCompat.setOverridesOnReleaseBuilds(config, packageName);
+ platformCompat.putOverridesOnReleaseBuilds(config, packageName);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/people/ConversationChannel.java b/core/java/android/app/people/ConversationChannel.java
index 332e159..2bf71b0 100644
--- a/core/java/android/app/people/ConversationChannel.java
+++ b/core/java/android/app/people/ConversationChannel.java
@@ -36,8 +36,8 @@
private ShortcutInfo mShortcutInfo;
private int mUid;
- private NotificationChannel mParentNotificationChannel;
- private NotificationChannelGroup mParentNotificationChannelGroup;
+ private NotificationChannel mNotificationChannel;
+ private NotificationChannelGroup mNotificationChannelGroup;
private long mLastEventTimestamp;
private boolean mHasActiveNotifications;
private boolean mHasBirthdayToday;
@@ -61,8 +61,8 @@
boolean hasActiveNotifications) {
mShortcutInfo = shortcutInfo;
mUid = uid;
- mParentNotificationChannel = parentNotificationChannel;
- mParentNotificationChannelGroup = parentNotificationChannelGroup;
+ mNotificationChannel = parentNotificationChannel;
+ mNotificationChannelGroup = parentNotificationChannelGroup;
mLastEventTimestamp = lastEventTimestamp;
mHasActiveNotifications = hasActiveNotifications;
}
@@ -74,8 +74,8 @@
List<ConversationStatus> statuses) {
mShortcutInfo = shortcutInfo;
mUid = uid;
- mParentNotificationChannel = parentNotificationChannel;
- mParentNotificationChannelGroup = parentNotificationChannelGroup;
+ mNotificationChannel = parentNotificationChannel;
+ mNotificationChannelGroup = parentNotificationChannelGroup;
mLastEventTimestamp = lastEventTimestamp;
mHasActiveNotifications = hasActiveNotifications;
mHasBirthdayToday = hasBirthdayToday;
@@ -85,8 +85,8 @@
public ConversationChannel(Parcel in) {
mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
mUid = in.readInt();
- mParentNotificationChannel = in.readParcelable(NotificationChannel.class.getClassLoader());
- mParentNotificationChannelGroup =
+ mNotificationChannel = in.readParcelable(NotificationChannel.class.getClassLoader());
+ mNotificationChannelGroup =
in.readParcelable(NotificationChannelGroup.class.getClassLoader());
mLastEventTimestamp = in.readLong();
mHasActiveNotifications = in.readBoolean();
@@ -104,8 +104,8 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(mShortcutInfo, flags);
dest.writeInt(mUid);
- dest.writeParcelable(mParentNotificationChannel, flags);
- dest.writeParcelable(mParentNotificationChannelGroup, flags);
+ dest.writeParcelable(mNotificationChannel, flags);
+ dest.writeParcelable(mNotificationChannelGroup, flags);
dest.writeLong(mLastEventTimestamp);
dest.writeBoolean(mHasActiveNotifications);
dest.writeBoolean(mHasBirthdayToday);
@@ -120,12 +120,12 @@
return mUid;
}
- public NotificationChannel getParentNotificationChannel() {
- return mParentNotificationChannel;
+ public NotificationChannel getNotificationChannel() {
+ return mNotificationChannel;
}
- public NotificationChannelGroup getParentNotificationChannelGroup() {
- return mParentNotificationChannelGroup;
+ public NotificationChannelGroup getNotificationChannelGroup() {
+ return mNotificationChannelGroup;
}
public long getLastEventTimestamp() {
@@ -149,4 +149,18 @@
public @Nullable List<ConversationStatus> getStatuses() {
return mStatuses;
}
+
+ @Override
+ public String toString() {
+ return "ConversationChannel{" +
+ "mShortcutInfo=" + mShortcutInfo +
+ ", mUid=" + mUid +
+ ", mNotificationChannel=" + mNotificationChannel +
+ ", mNotificationChannelGroup=" + mNotificationChannelGroup +
+ ", mLastEventTimestamp=" + mLastEventTimestamp +
+ ", mHasActiveNotifications=" + mHasActiveNotifications +
+ ", mHasBirthdayToday=" + mHasBirthdayToday +
+ ", mStatuses=" + mStatuses +
+ '}';
+ }
}
diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java
index 2dbbfdf..e11861f 100644
--- a/core/java/android/app/people/PeopleSpaceTile.java
+++ b/core/java/android/app/people/PeopleSpaceTile.java
@@ -307,10 +307,10 @@
mContactUri = getContactUri(info);
mStatuses = channel.getStatuses();
mLastInteractionTimestamp = channel.getLastEventTimestamp();
- mIsImportantConversation = channel.getParentNotificationChannel() != null
- && channel.getParentNotificationChannel().isImportantConversation();
- mCanBypassDnd = channel.getParentNotificationChannel() != null
- && channel.getParentNotificationChannel().canBypassDnd();
+ mIsImportantConversation = channel.getNotificationChannel() != null
+ && channel.getNotificationChannel().isImportantConversation();
+ mCanBypassDnd = channel.getNotificationChannel() != null
+ && channel.getNotificationChannel().canBypassDnd();
mNotificationPolicyState = SHOW_CONVERSATIONS;
}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index fe99f85..8a6c85d 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -48,6 +48,7 @@
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.DataUnit;
import android.util.Log;
@@ -214,6 +215,10 @@
* null} value when querying for the mobile network type to receive usage
* for all mobile networks. For additional details see {@link
* TelephonyManager#getSubscriberId()}.
+ * <p>Starting with API level 31, calling apps can provide a
+ * {@code subscriberId} with wifi network type to receive usage for
+ * wifi networks which is under the given subscription if applicable.
+ * Otherwise, pass {@code null} when querying all wifi networks.
* @param startTime Start of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
@@ -255,6 +260,10 @@
* null} value when querying for the mobile network type to receive usage
* for all mobile networks. For additional details see {@link
* TelephonyManager#getSubscriberId()}.
+ * <p>Starting with API level 31, calling apps can provide a
+ * {@code subscriberId} with wifi network type to receive usage for
+ * wifi networks which is under the given subscription if applicable.
+ * Otherwise, pass {@code null} when querying all wifi networks.
* @param startTime Start of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
@@ -300,6 +309,10 @@
* null} value when querying for the mobile network type to receive usage
* for all mobile networks. For additional details see {@link
* TelephonyManager#getSubscriberId()}.
+ * <p>Starting with API level 31, calling apps can provide a
+ * {@code subscriberId} with wifi network type to receive usage for
+ * wifi networks which is under the given subscription if applicable.
+ * Otherwise, pass {@code null} when querying all wifi networks.
* @param startTime Start of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
@@ -388,6 +401,10 @@
* null} value when querying for the mobile network type to receive usage
* for all mobile networks. For additional details see {@link
* TelephonyManager#getSubscriberId()}.
+ * <p>Starting with API level 31, calling apps can provide a
+ * {@code subscriberId} with wifi network type to receive usage for
+ * wifi networks which is under the given subscription if applicable.
+ * Otherwise, pass {@code null} when querying all wifi networks.
* @param startTime Start of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
@@ -450,6 +467,10 @@
* null} value when querying for the mobile network type to receive usage
* for all mobile networks. For additional details see {@link
* TelephonyManager#getSubscriberId()}.
+ * <p>Starting with API level 31, calling apps can provide a
+ * {@code subscriberId} with wifi network type to receive usage for
+ * wifi networks which is under the given subscription if applicable.
+ * Otherwise, pass {@code null} when querying all wifi networks.
* @param startTime Start of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
@@ -531,6 +552,10 @@
* null} value when registering for the mobile network type to receive
* notifications for all mobile networks. For additional details see {@link
* TelephonyManager#getSubscriberId()}.
+ * <p>Starting with API level 31, calling apps can provide a
+ * {@code subscriberId} with wifi network type to receive usage for
+ * wifi networks which is under the given subscription if applicable.
+ * Otherwise, pass {@code null} when querying all wifi networks.
* @param thresholdBytes Threshold in bytes to be notified on.
* @param callback The {@link UsageCallback} that the system will call when data usage
* has exceeded the specified threshold.
@@ -644,7 +669,7 @@
: NetworkTemplate.buildTemplateMobileAll(subscriberId);
break;
case ConnectivityManager.TYPE_WIFI:
- template = subscriberId == null
+ template = TextUtils.isEmpty(subscriberId)
? NetworkTemplate.buildTemplateWifiWildcard()
: NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL,
subscriberId);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 054b63f..ded5e6e 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -17,6 +17,8 @@
package android.bluetooth;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -62,8 +64,6 @@
import android.util.Log;
import android.util.Pair;
-import com.android.internal.util.Preconditions;
-
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -3314,8 +3314,8 @@
*/
WrappedOobDataCallback(@NonNull OobDataCallback callback,
@NonNull @CallbackExecutor Executor executor) {
- Preconditions.checkNotNull(callback);
- Preconditions.checkNotNull(executor);
+ requireNonNull(callback);
+ requireNonNull(executor);
mCallback = callback;
mExecutor = executor;
}
@@ -3385,7 +3385,7 @@
!= BluetoothDevice.TRANSPORT_LE) {
throw new IllegalArgumentException("Invalid transport '" + transport + "'!");
}
- Preconditions.checkNotNull(callback);
+ requireNonNull(callback);
if (!isEnabled()) {
Log.w(TAG, "generateLocalOobData(): Adapter isn't enabled!");
callback.onError(BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED);
@@ -3522,7 +3522,7 @@
* @hide
*/
public static boolean isAddressRandomStatic(@NonNull String address) {
- Preconditions.checkNotNull(address);
+ requireNonNull(address);
return checkBluetoothAddress(address)
&& (Integer.parseInt(address.split(":")[5], 16) & 0b11) == 0b11;
}
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 2dfa91d..4e5ede7 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -16,6 +16,8 @@
package android.bluetooth;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -23,8 +25,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -214,7 +214,7 @@
@NonNull
@SystemApi
public LeBuilder setDeviceName(@NonNull byte[] deviceName) {
- Preconditions.checkNotNull(deviceName);
+ requireNonNull(deviceName);
this.mDeviceName = deviceName;
return this;
}
@@ -308,8 +308,8 @@
@SystemApi
public LeBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] deviceAddressWithType,
@LeRole int leDeviceRole) {
- Preconditions.checkNotNull(confirmationHash);
- Preconditions.checkNotNull(deviceAddressWithType);
+ requireNonNull(confirmationHash);
+ requireNonNull(deviceAddressWithType);
if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
throw new IllegalArgumentException("confirmationHash must be "
+ OobData.CONFIRMATION_OCTETS + " octets in length.");
@@ -344,7 +344,7 @@
@NonNull
@SystemApi
public LeBuilder setLeTemporaryKey(@NonNull byte[] leTemporaryKey) {
- Preconditions.checkNotNull(leTemporaryKey);
+ requireNonNull(leTemporaryKey);
if (leTemporaryKey.length != LE_TK_OCTETS) {
throw new IllegalArgumentException("leTemporaryKey must be "
+ LE_TK_OCTETS + " octets in length.");
@@ -366,7 +366,7 @@
@NonNull
@SystemApi
public LeBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
- Preconditions.checkNotNull(randomizerHash);
+ requireNonNull(randomizerHash);
if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
throw new IllegalArgumentException("randomizerHash must be "
+ OobData.RANDOMIZER_OCTETS + " octets in length.");
@@ -534,9 +534,9 @@
@SystemApi
public ClassicBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] classicLength,
@NonNull byte[] deviceAddressWithType) {
- Preconditions.checkNotNull(confirmationHash);
- Preconditions.checkNotNull(classicLength);
- Preconditions.checkNotNull(deviceAddressWithType);
+ requireNonNull(confirmationHash);
+ requireNonNull(classicLength);
+ requireNonNull(deviceAddressWithType);
if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
throw new IllegalArgumentException("confirmationHash must be "
+ OobData.CONFIRMATION_OCTETS + " octets in length.");
@@ -567,7 +567,7 @@
@NonNull
@SystemApi
public ClassicBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
- Preconditions.checkNotNull(randomizerHash);
+ requireNonNull(randomizerHash);
if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
throw new IllegalArgumentException("randomizerHash must be "
+ OobData.RANDOMIZER_OCTETS + " octets in length.");
@@ -592,7 +592,7 @@
@NonNull
@SystemApi
public ClassicBuilder setDeviceName(@NonNull byte[] deviceName) {
- Preconditions.checkNotNull(deviceName);
+ requireNonNull(deviceName);
this.mDeviceName = deviceName;
return this;
}
@@ -617,7 +617,7 @@
@NonNull
@SystemApi
public ClassicBuilder setClassOfDevice(@NonNull byte[] classOfDevice) {
- Preconditions.checkNotNull(classOfDevice);
+ requireNonNull(classOfDevice);
if (classOfDevice.length != OobData.CLASS_OF_DEVICE_OCTETS) {
throw new IllegalArgumentException("classOfDevice must be "
+ OobData.CLASS_OF_DEVICE_OCTETS + " octets in length.");
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index dfef47d..cb3bf29 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -16,6 +16,8 @@
package android.bluetooth.le;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -27,7 +29,6 @@
import android.os.Parcelable;
import com.android.internal.util.BitUtils;
-import com.android.internal.util.Preconditions;
import java.util.Arrays;
import java.util.List;
@@ -646,7 +647,7 @@
public Builder setDeviceAddress(@NonNull String deviceAddress,
@AddressType int addressType,
@NonNull byte[] irk) {
- Preconditions.checkNotNull(irk);
+ requireNonNull(irk);
if (irk.length != LEN_IRK_OCTETS) {
throw new IllegalArgumentException("'irk' is invalid length!");
}
@@ -678,7 +679,7 @@
@Nullable byte[] irk) {
// Make sure our deviceAddress is valid!
- Preconditions.checkNotNull(deviceAddress);
+ requireNonNull(deviceAddress);
if (!BluetoothAdapter.checkBluetoothAddress(deviceAddress)) {
throw new IllegalArgumentException("invalid device address " + deviceAddress);
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index dc29c5e..a741f96 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -265,7 +265,7 @@
// Return an empty cursor for all columns.
return new MatrixCursor(cursor.getColumnNames(), 0);
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "query");
+ traceBegin(TRACE_TAG_DATABASE, "query: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -285,7 +285,7 @@
// getCallingPackage() isn't available in getType(), as the javadoc states.
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- Trace.traceBegin(TRACE_TAG_DATABASE, "getType");
+ traceBegin(TRACE_TAG_DATABASE, "getType: ", uri.getAuthority());
try {
return mInterface.getType(uri);
} catch (RemoteException e) {
@@ -323,7 +323,7 @@
setCallingAttributionSource(original);
}
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "insert");
+ traceBegin(TRACE_TAG_DATABASE, "insert: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -345,7 +345,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "bulkInsert");
+ traceBegin(TRACE_TAG_DATABASE, "bulkInsert: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -391,7 +391,7 @@
}
}
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "applyBatch");
+ traceBegin(TRACE_TAG_DATABASE, "applyBatch: ", authority);
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -423,7 +423,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "delete");
+ traceBegin(TRACE_TAG_DATABASE, "delete: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -445,7 +445,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "update");
+ traceBegin(TRACE_TAG_DATABASE, "update: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -465,7 +465,7 @@
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(attributionSource, uri, mode);
- Trace.traceBegin(TRACE_TAG_DATABASE, "openFile");
+ traceBegin(TRACE_TAG_DATABASE, "openFile: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -486,7 +486,7 @@
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(attributionSource, uri, mode);
- Trace.traceBegin(TRACE_TAG_DATABASE, "openAssetFile");
+ traceBegin(TRACE_TAG_DATABASE, "openAssetFile: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -505,7 +505,7 @@
String method, @Nullable String arg, @Nullable Bundle extras) {
validateIncomingAuthority(authority);
Bundle.setDefusable(extras, true);
- Trace.traceBegin(TRACE_TAG_DATABASE, "call");
+ traceBegin(TRACE_TAG_DATABASE, "call: ", authority);
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -523,7 +523,7 @@
// getCallingPackage() isn't available in getType(), as the javadoc states.
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- Trace.traceBegin(TRACE_TAG_DATABASE, "getStreamTypes");
+ traceBegin(TRACE_TAG_DATABASE, "getStreamTypes: ", uri.getAuthority());
try {
return mInterface.getStreamTypes(uri, mimeTypeFilter);
} catch (RemoteException e) {
@@ -541,7 +541,7 @@
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(attributionSource, uri, "r");
- Trace.traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile");
+ traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -569,7 +569,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return null;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "canonicalize");
+ traceBegin(TRACE_TAG_DATABASE, "canonicalize: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -605,7 +605,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return null;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "uncanonicalize");
+ traceBegin(TRACE_TAG_DATABASE, "uncanonicalize: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -641,7 +641,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return false;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "refresh");
+ traceBegin(TRACE_TAG_DATABASE, "refresh: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -658,7 +658,7 @@
int uid, int modeFlags) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- Trace.traceBegin(TRACE_TAG_DATABASE, "checkUriPermission");
+ traceBegin(TRACE_TAG_DATABASE, "checkUriPermission: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -2683,4 +2683,10 @@
}
return uri;
}
+
+ private static void traceBegin(long traceTag, String methodName, String subInfo) {
+ if (Trace.isTagEnabled(traceTag)) {
+ Trace.traceBegin(traceTag, methodName + subInfo);
+ }
+ }
}
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index 5887047..1e650a8 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -19,6 +19,9 @@
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
import static android.content.pm.parsing.ParsingPackageUtils.validateName;
+import static android.content.pm.parsing.ParsingUtils.ANDROID_RES_NAMESPACE;
+import static android.content.pm.parsing.ParsingUtils.DEFAULT_MIN_SDK_VERSION;
+import static android.content.pm.parsing.ParsingUtils.DEFAULT_TARGET_SDK_VERSION;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import android.annotation.NonNull;
@@ -31,12 +34,12 @@
import android.content.res.ApkAssets;
import android.content.res.XmlResourceParser;
import android.os.Trace;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Pair;
import android.util.Slog;
-import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import libcore.io.IoUtils;
@@ -59,10 +62,6 @@
private static final String TAG = ParsingUtils.TAG;
- // TODO(b/135203078): Consolidate constants
- private static final int DEFAULT_MIN_SDK_VERSION = 1;
- private static final int DEFAULT_TARGET_SDK_VERSION = 0;
-
private static final int PARSE_DEFAULT_INSTALL_LOCATION =
PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
@@ -323,8 +322,7 @@
signingDetails = PackageParser.SigningDetails.UNKNOWN;
}
- final AttributeSet attrs = parser;
- return parseApkLite(input, apkPath, parser, attrs, signingDetails);
+ return parseApkLite(input, apkPath, parser, signingDetails);
} catch (XmlPullParserException | IOException | RuntimeException e) {
Slog.w(TAG, "Failed to parse " + apkPath, e);
return input.error(PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
@@ -342,32 +340,39 @@
}
private static ParseResult<ApkLite> parseApkLite(ParseInput input, String codePath,
- XmlPullParser parser, AttributeSet attrs, PackageParser.SigningDetails signingDetails)
+ XmlResourceParser parser, PackageParser.SigningDetails signingDetails)
throws IOException, XmlPullParserException {
- ParseResult<Pair<String, String>> result = parsePackageSplitNames(input, parser, attrs);
+ ParseResult<Pair<String, String>> result = parsePackageSplitNames(input, parser);
if (result.isError()) {
return input.error(result);
}
Pair<String, String> packageSplit = result.getResult();
- int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
- int versionCode = 0;
- int versionCodeMajor = 0;
+ int installLocation = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
+ "installLocation", PARSE_DEFAULT_INSTALL_LOCATION);
+ int versionCode = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE, "versionCode", 0);
+ int versionCodeMajor = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
+ "versionCodeMajor",
+ 0);
+ int revisionCode = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE, "revisionCode", 0);
+ boolean coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
+ boolean isolatedSplits = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
+ "isolatedSplits", false);
+ boolean isFeatureSplit = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
+ "isFeatureSplit", false);
+ boolean isSplitRequired = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
+ "isSplitRequired", false);
+ String configForSplit = parser.getAttributeValue(null, "configForSplit");
+
int targetSdkVersion = DEFAULT_TARGET_SDK_VERSION;
int minSdkVersion = DEFAULT_MIN_SDK_VERSION;
- int revisionCode = 0;
- boolean coreApp = false;
boolean debuggable = false;
boolean profilableByShell = false;
boolean multiArch = false;
boolean use32bitAbi = false;
boolean extractNativeLibs = true;
- boolean isolatedSplits = false;
- boolean isFeatureSplit = false;
- boolean isSplitRequired = false;
boolean useEmbeddedDex = false;
- String configForSplit = null;
String usesSplitName = null;
String targetPackage = null;
boolean overlayIsStatic = false;
@@ -377,40 +382,6 @@
String requiredSystemPropertyName = null;
String requiredSystemPropertyValue = null;
- for (int i = 0; i < attrs.getAttributeCount(); i++) {
- final String attr = attrs.getAttributeName(i);
- switch (attr) {
- case "installLocation":
- installLocation = attrs.getAttributeIntValue(i,
- PARSE_DEFAULT_INSTALL_LOCATION);
- break;
- case "versionCode":
- versionCode = attrs.getAttributeIntValue(i, 0);
- break;
- case "versionCodeMajor":
- versionCodeMajor = attrs.getAttributeIntValue(i, 0);
- break;
- case "revisionCode":
- revisionCode = attrs.getAttributeIntValue(i, 0);
- break;
- case "coreApp":
- coreApp = attrs.getAttributeBooleanValue(i, false);
- break;
- case "isolatedSplits":
- isolatedSplits = attrs.getAttributeBooleanValue(i, false);
- break;
- case "configForSplit":
- configForSplit = attrs.getAttributeValue(i);
- break;
- case "isFeatureSplit":
- isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
- break;
- case "isSplitRequired":
- isSplitRequired = attrs.getAttributeBooleanValue(i, false);
- break;
- }
- }
-
// Only search the tree when the tag is the direct child of <manifest> tag
int type;
final int searchDepth = parser.getDepth() + 1;
@@ -427,34 +398,23 @@
}
if (ParsingPackageUtils.TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
- final VerifierInfo verifier = parseVerifier(attrs);
+ final VerifierInfo verifier = parseVerifier(parser);
if (verifier != null) {
verifiers.add(verifier);
}
} else if (ParsingPackageUtils.TAG_APPLICATION.equals(parser.getName())) {
- for (int i = 0; i < attrs.getAttributeCount(); ++i) {
- final String attr = attrs.getAttributeName(i);
- switch (attr) {
- case "debuggable":
- debuggable = attrs.getAttributeBooleanValue(i, false);
- break;
- case "multiArch":
- multiArch = attrs.getAttributeBooleanValue(i, false);
- break;
- case "use32bitAbi":
- use32bitAbi = attrs.getAttributeBooleanValue(i, false);
- break;
- case "extractNativeLibs":
- extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
- break;
- case "useEmbeddedDex":
- useEmbeddedDex = attrs.getAttributeBooleanValue(i, false);
- break;
- case "rollbackDataPolicy":
- rollbackDataPolicy = attrs.getAttributeIntValue(i, 0);
- break;
- }
- }
+ debuggable = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "debuggable",
+ false);
+ multiArch = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "multiArch",
+ false);
+ use32bitAbi = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "use32bitAbi",
+ false);
+ extractNativeLibs = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
+ "extractNativeLibs", true);
+ useEmbeddedDex = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
+ "useEmbeddedDex", false);
+ rollbackDataPolicy = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
+ "rollbackDataPolicy", 0);
final int innerDepth = parser.getDepth();
int innerType;
@@ -470,52 +430,79 @@
}
if (ParsingPackageUtils.TAG_PROFILEABLE.equals(parser.getName())) {
- for (int i = 0; i < attrs.getAttributeCount(); ++i) {
- final String attr = attrs.getAttributeName(i);
- if ("shell".equals(attr)) {
- profilableByShell = attrs.getAttributeBooleanValue(i,
- profilableByShell);
- }
- }
+ profilableByShell = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
+ "shell", profilableByShell);
}
}
} else if (ParsingPackageUtils.TAG_OVERLAY.equals(parser.getName())) {
- for (int i = 0; i < attrs.getAttributeCount(); ++i) {
- final String attr = attrs.getAttributeName(i);
- if ("requiredSystemPropertyName".equals(attr)) {
- requiredSystemPropertyName = attrs.getAttributeValue(i);
- } else if ("requiredSystemPropertyValue".equals(attr)) {
- requiredSystemPropertyValue = attrs.getAttributeValue(i);
- } else if ("targetPackage".equals(attr)) {
- targetPackage = attrs.getAttributeValue(i);;
- } else if ("isStatic".equals(attr)) {
- overlayIsStatic = attrs.getAttributeBooleanValue(i, false);
- } else if ("priority".equals(attr)) {
- overlayPriority = attrs.getAttributeIntValue(i, 0);
- }
- }
+ requiredSystemPropertyName = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
+ "requiredSystemPropertyName");
+ requiredSystemPropertyValue = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
+ "requiredSystemPropertyValue");
+ targetPackage = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "targetPackage");
+ overlayIsStatic = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "isStatic",
+ false);
+ overlayPriority = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE, "priority", 0);
} else if (ParsingPackageUtils.TAG_USES_SPLIT.equals(parser.getName())) {
if (usesSplitName != null) {
Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
continue;
}
- usesSplitName = attrs.getAttributeValue(PackageParser.ANDROID_RESOURCES, "name");
+ usesSplitName = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "name");
if (usesSplitName == null) {
return input.error(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"<uses-split> tag requires 'android:name' attribute");
}
} else if (ParsingPackageUtils.TAG_USES_SDK.equals(parser.getName())) {
- for (int i = 0; i < attrs.getAttributeCount(); ++i) {
- final String attr = attrs.getAttributeName(i);
- if ("targetSdkVersion".equals(attr)) {
- targetSdkVersion = attrs.getAttributeIntValue(i,
- DEFAULT_TARGET_SDK_VERSION);
- }
- if ("minSdkVersion".equals(attr)) {
- minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION);
+ // Mirrors ParsingPackageUtils#parseUsesSdk until lite and full parsing is combined
+ String minSdkVersionString = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
+ "minSdkVersion");
+ String targetSdkVersionString = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
+ "targetSdkVersion");
+
+ int minVer = DEFAULT_MIN_SDK_VERSION;
+ String minCode = null;
+ int targetVer = DEFAULT_TARGET_SDK_VERSION;
+ String targetCode = null;
+
+ if (!TextUtils.isEmpty(minSdkVersionString)) {
+ try {
+ minVer = Integer.parseInt(minSdkVersionString);
+ } catch (NumberFormatException ignored) {
+ minCode = minSdkVersionString;
}
}
+
+ if (!TextUtils.isEmpty(targetSdkVersionString)) {
+ try {
+ targetVer = Integer.parseInt(targetSdkVersionString);
+ } catch (NumberFormatException ignored) {
+ targetCode = targetSdkVersionString;
+ if (minCode == null) {
+ minCode = targetCode;
+ }
+ }
+ } else {
+ targetVer = minVer;
+ targetCode = minCode;
+ }
+
+ ParseResult<Integer> targetResult = ParsingPackageUtils.computeTargetSdkVersion(
+ targetVer, targetCode, ParsingPackageUtils.SDK_CODENAMES, input);
+ if (targetResult.isError()) {
+ return input.error(targetResult);
+ }
+
+ ParseResult<Integer> minResult = ParsingPackageUtils.computeMinSdkVersion(
+ minVer, minCode, ParsingPackageUtils.SDK_VERSION,
+ ParsingPackageUtils.SDK_CODENAMES, input);
+ if (minResult.isError()) {
+ return input.error(minResult);
+ }
+
+ targetSdkVersion = targetResult.getResult();
+ minSdkVersion = minResult.getResult();
}
}
@@ -541,7 +528,7 @@
}
public static ParseResult<Pair<String, String>> parsePackageSplitNames(ParseInput input,
- XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException {
+ XmlResourceParser parser) throws IOException, XmlPullParserException {
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
@@ -556,7 +543,7 @@
"No <manifest> tag");
}
- final String packageName = attrs.getAttributeValue(null, "package");
+ final String packageName = parser.getAttributeValue(null, "package");
if (!"android".equals(packageName)) {
final ParseResult<?> nameResult = validateName(input, packageName, true, true);
if (nameResult.isError()) {
@@ -565,7 +552,7 @@
}
}
- String splitName = attrs.getAttributeValue(null, "split");
+ String splitName = parser.getAttributeValue(null, "split");
if (splitName != null) {
if (splitName.length() == 0) {
splitName = null;
@@ -583,22 +570,8 @@
}
public static VerifierInfo parseVerifier(AttributeSet attrs) {
- String packageName = null;
- String encodedPublicKey = null;
-
- final int attrCount = attrs.getAttributeCount();
- for (int i = 0; i < attrCount; i++) {
- final int attrResId = attrs.getAttributeNameResource(i);
- switch (attrResId) {
- case R.attr.name:
- packageName = attrs.getAttributeValue(i);
- break;
-
- case R.attr.publicKey:
- encodedPublicKey = attrs.getAttributeValue(i);
- break;
- }
- }
+ String packageName = attrs.getAttributeValue(ANDROID_RES_NAMESPACE, "name");
+ String encodedPublicKey = attrs.getAttributeValue(ANDROID_RES_NAMESPACE, "publicKey");
if (packageName == null || packageName.length() == 0) {
Slog.i(TAG, "verifier package name was null; skipping");
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index f0b7649..4c44ba1 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -356,7 +356,7 @@
private float minAspectRatio;
@Nullable
private SparseIntArray minExtensionVersions;
- private int minSdkVersion;
+ private int minSdkVersion = ParsingUtils.DEFAULT_MIN_SDK_VERSION;
private int networkSecurityConfigRes;
@Nullable
private CharSequence nonLocalizedLabel;
@@ -369,7 +369,7 @@
private int requiresSmallestWidthDp;
private int roundIconRes;
private int targetSandboxVersion;
- private int targetSdkVersion;
+ private int targetSdkVersion = ParsingUtils.DEFAULT_TARGET_SDK_VERSION;
@Nullable
@DataClass.ParcelWith(ForInternedString.class)
private String taskAffinity;
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index b74760a..6fd5333 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -582,12 +582,12 @@
*/
private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, String apkPath,
String codePath, Resources res, XmlResourceParser parser, int flags)
- throws XmlPullParserException, IOException, PackageParserException {
+ throws XmlPullParserException, IOException {
final String splitName;
final String pkgName;
ParseResult<Pair<String, String>> packageSplitResult =
- ApkLiteParseUtils.parsePackageSplitNames(input, parser, parser);
+ ApkLiteParseUtils.parsePackageSplitNames(input, parser);
if (packageSplitResult.isError()) {
return input.error(packageSplitResult);
}
@@ -1460,9 +1460,9 @@
if (SDK_VERSION > 0) {
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk);
try {
- int minVers = 1;
+ int minVers = ParsingUtils.DEFAULT_MIN_SDK_VERSION;
String minCode = null;
- int targetVers = 0;
+ int targetVers = ParsingUtils.DEFAULT_TARGET_SDK_VERSION;
String targetCode = null;
TypedValue val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersion);
diff --git a/core/java/android/content/pm/parsing/ParsingUtils.java b/core/java/android/content/pm/parsing/ParsingUtils.java
index 5da5fbf..07ec6a8 100644
--- a/core/java/android/content/pm/parsing/ParsingUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingUtils.java
@@ -35,6 +35,11 @@
public static final String TAG = "PackageParsing";
+ public static final String ANDROID_RES_NAMESPACE = "http://schemas.android.com/apk/res/android";
+
+ public static final int DEFAULT_MIN_SDK_VERSION = 1;
+ public static final int DEFAULT_TARGET_SDK_VERSION = 0;
+
@Nullable
public static String buildClassName(String pkg, CharSequence clsSeq) {
if (clsSeq == null || clsSeq.length() <= 0) {
diff --git a/core/java/android/content/pm/verify/domain/TEST_MAPPING b/core/java/android/content/pm/verify/domain/TEST_MAPPING
index 5fcf411..ba4a62c 100644
--- a/core/java/android/content/pm/verify/domain/TEST_MAPPING
+++ b/core/java/android/content/pm/verify/domain/TEST_MAPPING
@@ -9,7 +9,10 @@
]
},
{
- "name": "CtsDomainVerificationDeviceTestCases"
+ "name": "CtsDomainVerificationDeviceStandaloneTestCases"
+ },
+ {
+ "name": "CtsDomainVerificationDeviceMultiUserTestCases"
},
{
"name": "CtsDomainVerificationHostTestCases"
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index d50404e..24c6a5a 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -43,6 +43,7 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -1178,11 +1179,14 @@
void releaseTheme(long themePtr) {
synchronized (this) {
- nativeThemeDestroy(themePtr);
decRefsLocked(themePtr);
}
}
+ static long getThemeFreeFunction() {
+ return nativeGetThemeFreeFunction();
+ }
+
void applyStyleToTheme(long themePtr, @StyleRes int resId, boolean force) {
synchronized (this) {
// Need to synchronize on AssetManager because we will be accessing
@@ -1192,6 +1196,31 @@
}
}
+ AssetManager rebaseTheme(long themePtr, @NonNull AssetManager newAssetManager,
+ @StyleRes int[] styleIds, @StyleRes boolean[] force, int count) {
+ // Exchange ownership of the theme with the new asset manager.
+ if (this != newAssetManager) {
+ synchronized (this) {
+ ensureValidLocked();
+ decRefsLocked(themePtr);
+ }
+ synchronized (newAssetManager) {
+ newAssetManager.ensureValidLocked();
+ newAssetManager.incRefsLocked(themePtr);
+ }
+ }
+
+ try {
+ synchronized (newAssetManager) {
+ newAssetManager.ensureValidLocked();
+ nativeThemeRebase(newAssetManager.mObject, themePtr, styleIds, force, count);
+ }
+ } finally {
+ Reference.reachabilityFence(newAssetManager);
+ }
+ return newAssetManager;
+ }
+
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
void setThemeTo(long dstThemePtr, @NonNull AssetManager srcAssetManager, long srcThemePtr) {
synchronized (this) {
@@ -1559,12 +1588,13 @@
// Theme related native methods
private static native long nativeThemeCreate(long ptr);
- private static native void nativeThemeDestroy(long themePtr);
+ private static native long nativeGetThemeFreeFunction();
private static native void nativeThemeApplyStyle(long ptr, long themePtr, @StyleRes int resId,
boolean force);
+ private static native void nativeThemeRebase(long ptr, long themePtr, @NonNull int[] styleIds,
+ @NonNull boolean[] force, int styleSize);
private static native void nativeThemeCopy(long dstAssetManagerPtr, long dstThemePtr,
long srcAssetManagerPtr, long srcThemePtr);
- static native void nativeThemeClear(long themePtr);
private static native int nativeThemeGetAttributeValue(long ptr, long themePtr,
@AttrRes int resId, @NonNull TypedValue outValue, boolean resolve);
private static native void nativeThemeDump(long ptr, long themePtr, int priority, String tag,
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ac4b7b7..12e41e2 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -341,7 +341,7 @@
/**
* Set the underlying implementation (containing all the resources and caches)
- * and updates all Theme references to new implementations as well.
+ * and updates all Theme implementations as well.
* @hide
*/
@UnsupportedAppUsage
@@ -353,14 +353,14 @@
mBaseApkAssetsSize = ArrayUtils.size(impl.getAssets().getApkAssets());
mResourcesImpl = impl;
- // Create new ThemeImpls that are identical to the ones we have.
+ // Rebase the ThemeImpls using the new ResourcesImpl.
synchronized (mThemeRefs) {
final int count = mThemeRefs.size();
for (int i = 0; i < count; i++) {
WeakReference<Theme> weakThemeRef = mThemeRefs.get(i);
Theme theme = weakThemeRef != null ? weakThemeRef.get() : null;
if (theme != null) {
- theme.setNewResourcesImpl(mResourcesImpl);
+ theme.rebase(mResourcesImpl);
}
}
}
@@ -1515,12 +1515,6 @@
}
}
- void setNewResourcesImpl(ResourcesImpl resImpl) {
- synchronized (mLock) {
- mThemeImpl = resImpl.newThemeImpl(mThemeImpl.getKey());
- }
- }
-
/**
* Place new attribute values into the theme. The style resource
* specified by <var>resid</var> will be retrieved from this Theme's
@@ -1847,6 +1841,12 @@
}
}
+ void rebase(ResourcesImpl resImpl) {
+ synchronized (mLock) {
+ mThemeImpl.rebase(resImpl.mAssets);
+ }
+ }
+
/**
* Returns the resource ID for the style specified using {@code style="..."} in the
* {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 553e11b..b9f93b8 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -54,6 +54,8 @@
import com.android.internal.util.GrowingArrayUtils;
+import libcore.util.NativeAllocationRegistry;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -1265,15 +1267,9 @@
return new ThemeImpl();
}
- /**
- * Creates a new ThemeImpl which is already set to the given Resources.ThemeKey.
- */
- ThemeImpl newThemeImpl(Resources.ThemeKey key) {
- ThemeImpl impl = new ThemeImpl();
- impl.mKey.setTo(key);
- impl.rebase();
- return impl;
- }
+ private static final NativeAllocationRegistry sThemeRegistry =
+ NativeAllocationRegistry.createMalloced(ResourcesImpl.class.getClassLoader(),
+ AssetManager.getThemeFreeFunction());
public class ThemeImpl {
/**
@@ -1282,7 +1278,7 @@
private final Resources.ThemeKey mKey = new Resources.ThemeKey();
@SuppressWarnings("hiding")
- private final AssetManager mAssets;
+ private AssetManager mAssets;
private final long mTheme;
/**
@@ -1293,6 +1289,7 @@
/*package*/ ThemeImpl() {
mAssets = ResourcesImpl.this.mAssets;
mTheme = mAssets.createTheme();
+ sThemeRegistry.registerNativeAllocation(this, mTheme);
}
@Override
@@ -1404,14 +1401,18 @@
* {@link #applyStyle(int, boolean)}.
*/
void rebase() {
- AssetManager.nativeThemeClear(mTheme);
+ rebase(mAssets);
+ }
- // Reapply the same styles in the same order.
- for (int i = 0; i < mKey.mCount; i++) {
- final int resId = mKey.mResId[i];
- final boolean force = mKey.mForce[i];
- mAssets.applyStyleToTheme(mTheme, resId, force);
- }
+ /**
+ * Rebases the theme against the {@code newAssets} by re-applying the styles passed to
+ * {@link #applyStyle(int, boolean)}.
+ *
+ * The theme will use {@code newAssets} for all future invocations of
+ * {@link #applyStyle(int, boolean)}.
+ */
+ void rebase(AssetManager newAssets) {
+ mAssets = mAssets.rebaseTheme(mTheme, newAssets, mKey.mResId, mKey.mForce, mKey.mCount);
}
/**
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index bc2dcb3..fe8dc46 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -571,7 +571,9 @@
}
int sensorHandle = (sensor == null) ? -1 : sensor.getHandle();
- if (rate > CAPPED_SAMPLING_RATE_LEVEL
+ if (sensor != null
+ && isSensorInCappedSet(sensor.getType())
+ && rate > CAPPED_SAMPLING_RATE_LEVEL
&& mIsPackageDebuggable
&& !mHasHighSamplingRateSensorsPermission
&& Compatibility.isChangeEnabled(CHANGE_ID_SAMPLING_RATE_SENSORS_PERMISSION)) {
@@ -782,7 +784,8 @@
Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
if (mNativeSensorEventQueue == 0) throw new NullPointerException();
if (sensor == null) throw new NullPointerException();
- if (rateUs < CAPPED_SAMPLING_PERIOD_US
+ if (mManager.isSensorInCappedSet(sensor.getType())
+ && rateUs < CAPPED_SAMPLING_PERIOD_US
&& mManager.mIsPackageDebuggable
&& !mManager.mHasHighSamplingRateSensorsPermission
&& Compatibility.isChangeEnabled(CHANGE_ID_SAMPLING_RATE_SENSORS_PERMISSION)) {
@@ -1015,4 +1018,20 @@
mNativeInstance, handle,
parameter.type, parameter.floatValues, parameter.intValues) == 0;
}
+
+ /**
+ * Checks if a sensor should be capped according to HIGH_SAMPLING_RATE_SENSORS
+ * permission.
+ *
+ * This needs to be kept in sync with the list defined on the native side
+ * in frameworks/native/services/sensorservice/SensorService.cpp
+ */
+ private boolean isSensorInCappedSet(int sensorType) {
+ return (sensorType == Sensor.TYPE_ACCELEROMETER
+ || sensorType == Sensor.TYPE_ACCELEROMETER_UNCALIBRATED
+ || sensorType == Sensor.TYPE_GYROSCOPE
+ || sensorType == Sensor.TYPE_GYROSCOPE_UNCALIBRATED
+ || sensorType == Sensor.TYPE_MAGNETIC_FIELD
+ || sensorType == Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);
+ }
}
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index 8e3de61..4127243 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -693,20 +693,42 @@
throw new IllegalArgumentException("Unsupported extension");
}
+ android.hardware.camera2.extension.Size sz =
+ new android.hardware.camera2.extension.Size();
+ sz.width = captureOutputSize.getWidth();
+ sz.height = captureOutputSize.getHeight();
if (areAdvancedExtensionsSupported()) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId);
- android.hardware.camera2.extension.Size sz =
- new android.hardware.camera2.extension.Size();
- sz.width = captureOutputSize.getWidth();
- sz.height = captureOutputSize.getHeight();
LatencyRange latencyRange = extender.getEstimatedCaptureLatencyRange(mCameraId,
sz, format);
if (latencyRange != null) {
return new Range(latencyRange.min, latencyRange.max);
}
- }
- } catch (RemoteException e) {
+ } else {
+ Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
+ initializeExtension(extension);
+ extenders.second.init(mCameraId, mChars.getNativeMetadata());
+ if ((format == ImageFormat.YUV_420_888) &&
+ (extenders.second.getCaptureProcessor() == null) ){
+ // Extensions that don't implement any capture processor are limited to
+ // JPEG only!
+ return null;
+ }
+ if ((format == ImageFormat.JPEG) &&
+ (extenders.second.getCaptureProcessor() != null)) {
+ // The framework will perform the additional encoding pass on the
+ // processed YUV_420 buffers. Latency in this case is very device
+ // specific and cannot be estimated accurately enough.
+ return null;
+ }
+
+ LatencyRange latencyRange = extenders.second.getEstimatedCaptureLatencyRange(sz);
+ if (latencyRange != null) {
+ return new Range(latencyRange.min, latencyRange.max);
+ }
+ }
+ } catch (RemoteException e) {
Log.e(TAG, "Failed to query the extension capture latency! Extension service does"
+ " not respond!");
} finally {
diff --git a/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl b/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl
index c04e75e..3ebf637 100644
--- a/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl
+++ b/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl
@@ -19,6 +19,8 @@
import android.hardware.camera2.extension.CaptureStageImpl;
import android.hardware.camera2.extension.ICaptureProcessorImpl;
+import android.hardware.camera2.extension.LatencyRange;
+import android.hardware.camera2.extension.Size;
import android.hardware.camera2.extension.SizeList;
/** @hide */
@@ -36,4 +38,5 @@
@nullable List<CaptureStageImpl> getCaptureStages();
int getMaxCaptureStage();
@nullable List<SizeList> getSupportedResolutions();
+ LatencyRange getEstimatedCaptureLatencyRange(in Size outputSize);
}
diff --git a/core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl b/core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl
index f365469..4c85966 100644
--- a/core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl
+++ b/core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl
@@ -21,5 +21,6 @@
/** @hide */
interface IImageProcessorImpl
{
- void onNextImageAvailable(in OutputConfigId outputConfigId, in ParcelImage image);
+ void onNextImageAvailable(in OutputConfigId outputConfigId, in ParcelImage image,
+ in String physicalCameraId);
}
diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
index abc487d..5cf50a2 100644
--- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
@@ -79,8 +79,8 @@
private final HandlerThread mHandlerThread;
private final CameraExtensionSession.StateCallback mCallbacks;
private final IAdvancedExtenderImpl mAdvancedExtender;
- // maps camera outputs to extension output ids
- private final HashMap<Surface, Integer> mSurfaceIdMap = new HashMap<>();
+ // maps registered camera surfaces to extension output configs
+ private final HashMap<Surface, CameraOutputConfig> mCameraConfigMap = new HashMap<>();
// maps camera extension output ids to camera registered image readers
private final HashMap<Integer, ImageReader> mReaderMap = new HashMap<>();
private final RequestProcessor mRequestProcessor = new RequestProcessor();
@@ -226,7 +226,7 @@
reader.getSurface());
break;
case CameraOutputConfig.TYPE_MULTIRES_IMAGEREADER:
- // TBD
+ // Support for multi-resolution outputs to be added in future releases
default:
throw new IllegalArgumentException("Unsupported output config type: " +
output.type);
@@ -251,7 +251,7 @@
}
}
outputList.add(outConfig);
- mSurfaceIdMap.put(outConfig.getSurface(), output.outputId.id);
+ mCameraConfigMap.put(outConfig.getSurface(), output);
}
SessionConfiguration sessionConfiguration = new SessionConfiguration(
@@ -629,7 +629,7 @@
if (request.getTag() instanceof Integer) {
Integer requestId = (Integer) request.getTag();
mCallback.onCaptureBufferLost(requestId, frameNumber,
- mSurfaceIdMap.get(target));
+ mCameraConfigMap.get(target).outputId.id);
} else {
Log.e(TAG, "Invalid capture request tag!");
}
@@ -736,12 +736,14 @@
private static final class ImageReaderHandler implements ImageReader.OnImageAvailableListener {
private final OutputConfigId mOutputConfigId;
private final IImageProcessorImpl mIImageProcessor;
+ private final String mPhysicalCameraId;
private ImageReaderHandler(int outputConfigId,
- IImageProcessorImpl iImageProcessor) {
+ IImageProcessorImpl iImageProcessor, String physicalCameraId) {
mOutputConfigId = new OutputConfigId();
mOutputConfigId.id = outputConfigId;
mIImageProcessor = iImageProcessor;
+ mPhysicalCameraId = physicalCameraId;
}
@Override
@@ -787,7 +789,8 @@
parcelImage.crop = img.getCropRect();
try {
- mIImageProcessor.onNextImageAvailable(mOutputConfigId, parcelImage);
+ mIImageProcessor.onNextImageAvailable(mOutputConfigId, parcelImage,
+ mPhysicalCameraId);
} catch (RemoteException e) {
Log.e(TAG, "Failed to propagate image buffer on output surface id: " +
mOutputConfigId + " extension service does not respond!");
@@ -804,8 +807,17 @@
IImageProcessorImpl imageProcessor) {
synchronized (mInterfaceLock) {
if (mReaderMap.containsKey(outputConfigId.id)) {
- mReaderMap.get(outputConfigId.id).setOnImageAvailableListener(
- new ImageReaderHandler(outputConfigId.id, imageProcessor), mHandler);
+ ImageReader reader = mReaderMap.get(outputConfigId.id);
+ String physicalCameraId = null;
+ if (mCameraConfigMap.containsKey(reader.getSurface())) {
+ physicalCameraId =
+ mCameraConfigMap.get(reader.getSurface()).physicalCameraId;
+ reader.setOnImageAvailableListener(new ImageReaderHandler(outputConfigId.id,
+ imageProcessor, physicalCameraId), mHandler);
+ } else {
+ Log.e(TAG, "Camera output configuration for ImageReader with " +
+ " config Id " + outputConfigId.id + " not found!");
+ }
} else {
Log.e(TAG, "ImageReader with output config id: " + outputConfigId.id +
" not found!");
@@ -828,7 +840,7 @@
ArrayList<CaptureRequest> captureRequests = new ArrayList<>();
for (Request request : requests) {
captureRequests.add(initializeCaptureRequest(mCameraDevice, request,
- mSurfaceIdMap));
+ mCameraConfigMap));
}
mCaptureSession.captureBurstRequests(captureRequests,
new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
@@ -848,7 +860,7 @@
synchronized (mInterfaceLock) {
try {
CaptureRequest repeatingRequest = initializeCaptureRequest(mCameraDevice,
- request, mSurfaceIdMap);
+ request, mCameraConfigMap);
CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback);
mCaptureSession.setSingleRepeatingRequest(repeatingRequest,
new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
@@ -891,12 +903,13 @@
}
private static CaptureRequest initializeCaptureRequest(CameraDevice cameraDevice,
- Request request, HashMap<Surface, Integer> surfaceIdMap) throws CameraAccessException {
+ Request request, HashMap<Surface, CameraOutputConfig> surfaceIdMap)
+ throws CameraAccessException {
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(request.templateId);
for (OutputConfigId configId : request.targetOutputConfigIds) {
boolean found = false;
- for (Map.Entry<Surface, Integer> entry : surfaceIdMap.entrySet()) {
- if (entry.getValue() == configId.id) {
+ for (Map.Entry<Surface, CameraOutputConfig> entry : surfaceIdMap.entrySet()) {
+ if (entry.getValue().outputId.id == configId.id) {
builder.addTarget(entry.getKey());
found = true;
break;
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
index 5339f41..4bcc494 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.graphics.ImageFormat;
-import android.graphics.PixelFormat;
import android.graphics.SurfaceTexture;
import android.hardware.HardwareBuffer;
import android.hardware.camera2.CameraAccessException;
@@ -42,7 +41,6 @@
import android.hardware.camera2.params.ExtensionSessionConfiguration;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.SessionConfiguration;
-import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.SurfaceUtils;
import android.media.Image;
import android.media.ImageReader;
@@ -68,7 +66,6 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
-import java.util.concurrent.RejectedExecutionException;
public final class CameraExtensionSessionImpl extends CameraExtensionSession {
private static final int PREVIEW_QUEUE_SIZE = 3;
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 8dfb787..5bb7201 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -735,8 +735,7 @@
source.readTypedList(surfaces, Surface.CREATOR);
String physicalCameraId = source.readString();
boolean isMultiResolutionOutput = source.readInt() == 1;
- ArrayList<Integer> sensorPixelModesUsed = new ArrayList<Integer>();
- source.readList(sensorPixelModesUsed, Integer.class.getClassLoader());
+ int[] sensorPixelModesUsed = source.createIntArray();
checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
mSurfaceGroupId = surfaceSetId;
@@ -760,7 +759,7 @@
}
mPhysicalCameraId = physicalCameraId;
mIsMultiResolution = isMultiResolutionOutput;
- mSensorPixelModesUsed = sensorPixelModesUsed;
+ mSensorPixelModesUsed = convertIntArrayToIntegerList(sensorPixelModesUsed);
}
/**
@@ -826,13 +825,7 @@
new Parcelable.Creator<OutputConfiguration>() {
@Override
public OutputConfiguration createFromParcel(Parcel source) {
- try {
- OutputConfiguration outputConfiguration = new OutputConfiguration(source);
- return outputConfiguration;
- } catch (Exception e) {
- Log.e(TAG, "Exception creating OutputConfiguration from parcel", e);
- return null;
- }
+ return new OutputConfiguration(source);
}
@Override
@@ -854,6 +847,17 @@
return integerArray;
}
+ private static ArrayList<Integer> convertIntArrayToIntegerList(int[] intArray) {
+ ArrayList<Integer> integerList = new ArrayList<Integer>();
+ if (intArray == null) {
+ return integerList;
+ }
+ for (int i = 0; i < intArray.length; i++) {
+ integerList.add(intArray[i]);
+ }
+ return integerList;
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
if (dest == null) {
@@ -871,7 +875,6 @@
dest.writeInt(mIsMultiResolution ? 1 : 0);
// writeList doesn't seem to work well with Integer list.
dest.writeIntArray(convertIntegerToIntList(mSensorPixelModesUsed));
- //dest.writeArray(mSensorPixelModesUsed.toArray());
}
/**
diff --git a/core/java/android/hardware/camera2/params/SessionConfiguration.java b/core/java/android/hardware/camera2/params/SessionConfiguration.java
index ea6b92d..cfb6efa 100644
--- a/core/java/android/hardware/camera2/params/SessionConfiguration.java
+++ b/core/java/android/hardware/camera2/params/SessionConfiguration.java
@@ -146,13 +146,7 @@
new Parcelable.Creator<SessionConfiguration> () {
@Override
public SessionConfiguration createFromParcel(Parcel source) {
- try {
- SessionConfiguration sessionConfiguration = new SessionConfiguration(source);
- return sessionConfiguration;
- } catch (Exception e) {
- Log.e(TAG, "Exception creating SessionConfiguration from parcel", e);
- return null;
- }
+ return new SessionConfiguration(source);
}
@Override
diff --git a/core/java/android/hardware/camera2/params/VendorTagDescriptor.java b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java
index 4845ec3..c62f6da 100644
--- a/core/java/android/hardware/camera2/params/VendorTagDescriptor.java
+++ b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java
@@ -36,13 +36,7 @@
new Parcelable.Creator<VendorTagDescriptor>() {
@Override
public VendorTagDescriptor createFromParcel(Parcel source) {
- try {
- VendorTagDescriptor vendorDescriptor = new VendorTagDescriptor(source);
- return vendorDescriptor;
- } catch (Exception e) {
- Log.e(TAG, "Exception creating VendorTagDescriptor from parcel", e);
- return null;
- }
+ return new VendorTagDescriptor(source);
}
@Override
diff --git a/core/java/android/hardware/camera2/params/VendorTagDescriptorCache.java b/core/java/android/hardware/camera2/params/VendorTagDescriptorCache.java
index 450b70b..8d7615c 100644
--- a/core/java/android/hardware/camera2/params/VendorTagDescriptorCache.java
+++ b/core/java/android/hardware/camera2/params/VendorTagDescriptorCache.java
@@ -36,13 +36,7 @@
new Parcelable.Creator<VendorTagDescriptorCache>() {
@Override
public VendorTagDescriptorCache createFromParcel(Parcel source) {
- try {
- VendorTagDescriptorCache vendorDescriptorCache = new VendorTagDescriptorCache(source);
- return vendorDescriptorCache;
- } catch (Exception e) {
- Log.e(TAG, "Exception creating VendorTagDescriptorCache from parcel", e);
- return null;
- }
+ return new VendorTagDescriptorCache(source);
}
@Override
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index df51734..a9b95fc 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -94,6 +94,7 @@
// Guarded by mLock
private boolean mDispatchNativeCallbacks = false;
+ private float mNativeCallbackReportedRefreshRate;
private final Object mLock = new Object();
@UnsupportedAppUsage
@@ -404,10 +405,11 @@
// We can likely save a binder hop if we attach the refresh rate onto the
// listener.
DisplayInfo display = getDisplayInfoLocked(displayId);
- if (display != null) {
- float refreshRate = display.getRefreshRate();
+ if (display != null
+ && mNativeCallbackReportedRefreshRate != display.getRefreshRate()) {
+ mNativeCallbackReportedRefreshRate = display.getRefreshRate();
// Signal native callbacks if we ever set a refresh rate.
- nSignalNativeCallbacks(refreshRate);
+ nSignalNativeCallbacks(mNativeCallbackReportedRefreshRate);
}
}
}
@@ -1055,8 +1057,8 @@
if (display != null) {
// We need to tell AChoreographer instances the current refresh rate so that apps
// can get it for free once a callback first registers.
- float refreshRate = display.getRefreshRate();
- nSignalNativeCallbacks(refreshRate);
+ mNativeCallbackReportedRefreshRate = display.getRefreshRate();
+ nSignalNativeCallbacks(mNativeCallbackReportedRefreshRate);
}
}
}
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index dce3fef..c739c6a 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -287,6 +287,12 @@
public abstract void ignoreProximitySensorUntilChanged();
/**
+ * Returns the refresh rate switching type.
+ */
+ @DisplayManager.SwitchingType
+ public abstract int getRefreshRateSwitchingType();
+
+ /**
* Describes the requested power state of the display.
*
* This object is intended to describe the general characteristics of the
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 64f20b8..5a25cfc 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -200,6 +200,9 @@
public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20;
/** @hide */
+ public static final int DAEMON_CLEANUP = BASE + 21;
+
+ /** @hide */
public static final int ENABLE = BASE + 24;
/** @hide */
public static final int DISABLE = BASE + 25;
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index 7eea0b1..86cd23d 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -166,9 +166,6 @@
private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities";
@NonNull private final SortedSet<Integer> mExposedCapabilities;
- private static final String UNDERLYING_CAPABILITIES_KEY = "mUnderlyingCapabilities";
- @NonNull private final SortedSet<Integer> mUnderlyingCapabilities;
-
private static final String MAX_MTU_KEY = "mMaxMtu";
private final int mMaxMtu;
@@ -180,13 +177,11 @@
@NonNull String gatewayConnectionName,
@NonNull IkeTunnelConnectionParams tunnelConnectionParams,
@NonNull Set<Integer> exposedCapabilities,
- @NonNull Set<Integer> underlyingCapabilities,
@NonNull long[] retryIntervalsMs,
@IntRange(from = MIN_MTU_V6) int maxMtu) {
mGatewayConnectionName = gatewayConnectionName;
mTunnelConnectionParams = tunnelConnectionParams;
mExposedCapabilities = new TreeSet(exposedCapabilities);
- mUnderlyingCapabilities = new TreeSet(underlyingCapabilities);
mRetryIntervalsMs = retryIntervalsMs;
mMaxMtu = maxMtu;
@@ -203,16 +198,12 @@
final PersistableBundle exposedCapsBundle =
in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY);
- final PersistableBundle underlyingCapsBundle =
- in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY);
mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY);
mTunnelConnectionParams =
TunnelConnectionParamsUtils.fromPersistableBundle(tunnelConnectionParamsBundle);
mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
- mUnderlyingCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
- underlyingCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
mMaxMtu = in.getInt(MAX_MTU_KEY);
@@ -312,36 +303,6 @@
}
/**
- * Returns all capabilities required of underlying networks.
- *
- * <p>The returned integer-value capabilities will be sorted in ascending numerical order.
- *
- * @see Builder#addRequiredUnderlyingCapability(int)
- * @see Builder#removeRequiredUnderlyingCapability(int)
- * @hide
- */
- // TODO(b/182219992): Remove, and add when per-transport capabilities are supported
- @NonNull
- public int[] getRequiredUnderlyingCapabilities() {
- // Sorted set guarantees ordering
- return ArrayUtils.convertToIntArray(new ArrayList<>(mUnderlyingCapabilities));
- }
-
- /**
- * Returns all capabilities required of underlying networks.
- *
- * <p>Left to prevent the need to make major changes while changes are actively in flight.
- *
- * @deprecated use getRequiredUnderlyingCapabilities() instead
- * @hide
- */
- @Deprecated
- @NonNull
- public Set<Integer> getAllUnderlyingCapabilities() {
- return Collections.unmodifiableSet(mUnderlyingCapabilities);
- }
-
- /**
* Retrieves the configured retry intervals.
*
* @see Builder#setRetryIntervalsMillis(long[])
@@ -377,15 +338,10 @@
PersistableBundleUtils.fromList(
new ArrayList<>(mExposedCapabilities),
PersistableBundleUtils.INTEGER_SERIALIZER);
- final PersistableBundle underlyingCapsBundle =
- PersistableBundleUtils.fromList(
- new ArrayList<>(mUnderlyingCapabilities),
- PersistableBundleUtils.INTEGER_SERIALIZER);
result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle);
result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
- result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle);
result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
result.putInt(MAX_MTU_KEY, mMaxMtu);
@@ -397,7 +353,6 @@
return Objects.hash(
mGatewayConnectionName,
mExposedCapabilities,
- mUnderlyingCapabilities,
Arrays.hashCode(mRetryIntervalsMs),
mMaxMtu);
}
@@ -411,7 +366,6 @@
final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other;
return mGatewayConnectionName.equals(rhs.mGatewayConnectionName)
&& mExposedCapabilities.equals(rhs.mExposedCapabilities)
- && mUnderlyingCapabilities.equals(rhs.mUnderlyingCapabilities)
&& Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
&& mMaxMtu == rhs.mMaxMtu;
}
@@ -423,7 +377,6 @@
@NonNull private final String mGatewayConnectionName;
@NonNull private final IkeTunnelConnectionParams mTunnelConnectionParams;
@NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
- @NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet();
@NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
private int mMaxMtu = DEFAULT_MAX_MTU;
@@ -495,51 +448,6 @@
}
/**
- * Require a capability for Networks underlying this VCN Gateway Connection.
- *
- * @param underlyingCapability the capability that a network MUST have in order to be an
- * underlying network for this VCN Gateway Connection.
- * @return this {@link Builder} instance, for chaining
- * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying
- * networks
- * @hide
- */
- // TODO(b/182219992): Remove, and add when per-transport capabilities are supported
- @NonNull
- public Builder addRequiredUnderlyingCapability(
- @VcnSupportedCapability int underlyingCapability) {
- checkValidCapability(underlyingCapability);
-
- mUnderlyingCapabilities.add(underlyingCapability);
- return this;
- }
-
- /**
- * Remove a requirement of a capability for Networks underlying this VCN Gateway Connection.
- *
- * <p>Calling this method will allow Networks that do NOT have this capability to be
- * selected as an underlying network for this VCN Gateway Connection. However, underlying
- * networks MAY still have the removed capability.
- *
- * @param underlyingCapability the capability that a network DOES NOT need to have in order
- * to be an underlying network for this VCN Gateway Connection.
- * @return this {@link Builder} instance, for chaining
- * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying
- * networks
- * @hide
- */
- // TODO(b/182219992): Remove, and add when per-transport capabilities are supported
- @NonNull
- @SuppressLint("BuilderSetStyle") // For consistency with NetCaps.Builder add/removeCap
- public Builder removeRequiredUnderlyingCapability(
- @VcnSupportedCapability int underlyingCapability) {
- checkValidCapability(underlyingCapability);
-
- mUnderlyingCapabilities.remove(underlyingCapability);
- return this;
- }
-
- /**
* Set the retry interval between VCN establishment attempts upon successive failures.
*
* <p>The last retry interval will be repeated until safe mode is entered, or a connection
@@ -603,7 +511,6 @@
mGatewayConnectionName,
mTunnelConnectionParams,
mExposedCapabilities,
- mUnderlyingCapabilities,
mRetryIntervalsMs,
mMaxMtu);
}
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index f2857ce..6c9f0f67 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -75,6 +75,8 @@
public static final int AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT = 2;
+ private static final int STATSD_PULL_ATOM_MAX_BYTES = 45000;
+
private final int mDischargePercentage;
private final double mBatteryCapacityMah;
private final long mStatsStartTimestampMs;
@@ -369,30 +371,60 @@
/** Returns a proto (as used for atoms.proto) corresponding to this BatteryUsageStats. */
public byte[] getStatsProto() {
+ // ProtoOutputStream.getRawSize() returns the buffer size before compaction.
+ // BatteryUsageStats contains a lot of integers, so compaction of integers to
+ // varint reduces the size of the proto buffer by as much as 50%.
+ int maxRawSize = (int) (STATSD_PULL_ATOM_MAX_BYTES * 1.75);
+ // Limit the number of attempts in order to prevent an infinite loop
+ for (int i = 0; i < 3; i++) {
+ final ProtoOutputStream proto = new ProtoOutputStream();
+ writeStatsProto(proto, maxRawSize);
+
+ final int rawSize = proto.getRawSize();
+ final byte[] protoOutput = proto.getBytes();
+
+ if (protoOutput.length <= STATSD_PULL_ATOM_MAX_BYTES) {
+ return protoOutput;
+ }
+
+ // Adjust maxRawSize proportionately and try again.
+ maxRawSize =
+ (int) ((long) STATSD_PULL_ATOM_MAX_BYTES * rawSize / protoOutput.length - 1024);
+ }
+
+ // Fallback: if we have failed to generate a proto smaller than STATSD_PULL_ATOM_MAX_BYTES,
+ // just generate a proto with the _rawSize_ of STATSD_PULL_ATOM_MAX_BYTES, which is
+ // guaranteed to produce a compacted proto (significantly) smaller than
+ // STATSD_PULL_ATOM_MAX_BYTES.
+ final ProtoOutputStream proto = new ProtoOutputStream();
+ writeStatsProto(proto, STATSD_PULL_ATOM_MAX_BYTES);
+ return proto.getBytes();
+ }
+
+ @NonNull
+ private void writeStatsProto(ProtoOutputStream proto, int maxRawSize) {
final BatteryConsumer deviceBatteryConsumer = getAggregateBatteryConsumer(
AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE);
- final ProtoOutputStream proto = new ProtoOutputStream();
proto.write(BatteryUsageStatsAtomsProto.SESSION_START_MILLIS, getStatsStartTimestamp());
proto.write(BatteryUsageStatsAtomsProto.SESSION_END_MILLIS, getStatsEndTimestamp());
proto.write(BatteryUsageStatsAtomsProto.SESSION_DURATION_MILLIS, getStatsDuration());
- deviceBatteryConsumer.writeStatsProto(proto,
- BatteryUsageStatsAtomsProto.DEVICE_BATTERY_CONSUMER);
- writeUidBatteryConsumersProto(proto);
proto.write(BatteryUsageStatsAtomsProto.SESSION_DISCHARGE_PERCENTAGE,
getDischargePercentage());
- return proto.getBytes();
+ deviceBatteryConsumer.writeStatsProto(proto,
+ BatteryUsageStatsAtomsProto.DEVICE_BATTERY_CONSUMER);
+ writeUidBatteryConsumersProto(proto, maxRawSize);
}
/**
* Writes the UidBatteryConsumers data, held by this BatteryUsageStats, to the proto (as used
* for atoms.proto).
*/
- private void writeUidBatteryConsumersProto(ProtoOutputStream proto) {
+ private void writeUidBatteryConsumersProto(ProtoOutputStream proto, int maxRawSize) {
final List<UidBatteryConsumer> consumers = getUidBatteryConsumers();
+ // Order consumers by descending weight (a combination of consumed power and usage time)
+ consumers.sort(Comparator.comparingDouble(this::getUidBatteryConsumerWeight).reversed());
- // TODO(b/189225426): Sort the list by power consumption. If during the for,
- // proto.getRawSize() > 45kb, truncate the remainder of the list.
final int size = consumers.size();
for (int i = 0; i < size; i++) {
final UidBatteryConsumer consumer = consumers.get(i);
@@ -420,9 +452,35 @@
BatteryUsageStatsAtomsProto.UidBatteryConsumer.TIME_IN_BACKGROUND_MILLIS,
bgMs);
proto.end(token);
+
+ if (proto.getRawSize() >= maxRawSize) {
+ break;
+ }
}
}
+ private static final double WEIGHT_CONSUMED_POWER = 1;
+ // Weight one hour in foreground the same as 100 mAh of power drain
+ private static final double WEIGHT_FOREGROUND_STATE = 100.0 / (1 * 60 * 60 * 1000);
+ // Weight one hour in background the same as 300 mAh of power drain
+ private static final double WEIGHT_BACKGROUND_STATE = 300.0 / (1 * 60 * 60 * 1000);
+
+ /**
+ * Computes the weight associated with a UidBatteryConsumer, which is used for sorting.
+ * We want applications with the largest consumed power as well as applications
+ * with the highest usage time to be included in the statsd atom.
+ */
+ private double getUidBatteryConsumerWeight(UidBatteryConsumer uidBatteryConsumer) {
+ final double consumedPower = uidBatteryConsumer.getConsumedPower();
+ final long timeInForeground =
+ uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND);
+ final long timeInBackground =
+ uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND);
+ return consumedPower * WEIGHT_CONSUMED_POWER
+ + timeInForeground * WEIGHT_FOREGROUND_STATE
+ + timeInBackground * WEIGHT_BACKGROUND_STATE;
+ }
+
/**
* Prints the stats in a human-readable format.
*/
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 224cd84..c22224d 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -575,6 +575,8 @@
* <p>This restriction also prevents VPNs from starting. However, in Android 7.0
* ({@linkplain android.os.Build.VERSION_CODES#N API level 24}) or higher, the system does
* start always-on VPNs created by the device or profile owner.
+ * <p>From Android 12 ({@linkplain android.os.Build.VERSION_CODES#S API level 31}) enforcing
+ * this restriction clears currently active VPN if it was configured by the user.
*
* <p>Key for user restrictions.
* <p>Type: Boolean
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index 6e25968..8ebc081 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -160,7 +160,7 @@
/**
* Starts or re-starts loading of data.
*/
- void startLoading(
+ public void startLoading(
@NonNull DataLoaderParams dataLoaderParams,
@Nullable IDataLoaderStatusListener statusListener,
@Nullable StorageHealthCheckParams healthCheckParams,
diff --git a/core/java/android/os/incremental/IncrementalMetrics.java b/core/java/android/os/incremental/IncrementalMetrics.java
index c44b7d9..534525a 100644
--- a/core/java/android/os/incremental/IncrementalMetrics.java
+++ b/core/java/android/os/incremental/IncrementalMetrics.java
@@ -90,7 +90,7 @@
* @return total duration in milliseconds of delayed reads
*/
public long getTotalDelayedReadsDurationMillis() {
- return mData.getInt(IIncrementalService.METRICS_TOTAL_DELAYED_READS_MILLIS, -1);
+ return mData.getLong(IIncrementalService.METRICS_TOTAL_DELAYED_READS_MILLIS, -1);
}
/**
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index f3cc35b3..c5d0cd4 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -158,6 +158,8 @@
mPermissionManager = IPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
"permissionmgr"));
mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class);
+ //TODO ntmyren: there should be a way to only enable the watcher when requested
+ mUsageHelper = new PermissionUsageHelper(context);
}
/**
@@ -878,10 +880,6 @@
@NonNull
@RequiresPermission(Manifest.permission.GET_APP_OPS_STATS)
public List<PermGroupUsage> getIndicatorAppOpUsageData() {
- // Lazily initialize the usage helper
- if (mUsageHelper == null) {
- mUsageHelper = new PermissionUsageHelper(mContext);
- }
return mUsageHelper.getOpUsageData(new AudioManager().isMicrophoneMute());
}
diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java
index 53ba259..d4e548e 100644
--- a/core/java/android/permission/PermissionUsageHelper.java
+++ b/core/java/android/permission/PermissionUsageHelper.java
@@ -19,6 +19,10 @@
import static android.Manifest.permission_group.CAMERA;
import static android.Manifest.permission_group.LOCATION;
import static android.Manifest.permission_group.MICROPHONE;
+import static android.app.AppOpsManager.ATTRIBUTION_FLAGS_NONE;
+import static android.app.AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
+import static android.app.AppOpsManager.ATTRIBUTION_FLAG_RECEIVER;
+import static android.app.AppOpsManager.AttributionFlags;
import static android.app.AppOpsManager.OPSTR_CAMERA;
import static android.app.AppOpsManager.OPSTR_COARSE_LOCATION;
import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
@@ -30,6 +34,7 @@
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -56,7 +61,7 @@
*
* @hide
*/
-public class PermissionUsageHelper {
+public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedListener {
/** Whether to show the mic and camera icons. */
private static final String PROPERTY_CAMERA_MIC_ICONS_ENABLED = "camera_mic_icons_enabled";
@@ -140,6 +145,7 @@
private ArrayMap<UserHandle, Context> mUserContexts;
private PackageManager mPkgManager;
private AppOpsManager mAppOpsManager;
+ private ArrayMap<Integer, ArrayList<AccessChainLink>> mAttributionChains = new ArrayMap<>();
/**
* Constructor for PermissionUsageHelper
@@ -151,6 +157,10 @@
mAppOpsManager = context.getSystemService(AppOpsManager.class);
mUserContexts = new ArrayMap<>();
mUserContexts.put(Process.myUserHandle(), mContext);
+ // TODO ntmyren: make this listen for flag enable/disable changes
+ String[] ops = { OPSTR_CAMERA, OPSTR_RECORD_AUDIO };
+ mContext.getSystemService(AppOpsManager.class).startWatchingActive(ops,
+ context.getMainExecutor(), this);
}
private Context getUserContext(UserHandle user) {
@@ -160,6 +170,45 @@
return mUserContexts.get(user);
}
+ @Override
+ public void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName,
+ boolean active) {
+ // not part of an attribution chain. Do nothing
+ }
+
+ @Override
+ public void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName,
+ @Nullable String attributionTag, boolean active, @AttributionFlags int attributionFlags,
+ int attributionChainId) {
+ if ((attributionFlags & ATTRIBUTION_FLAGS_NONE) != 0) {
+ return;
+ }
+
+ if (!active) {
+ // if any link in the chain is finished, remove the chain.
+ // TODO ntmyren: be smarter about this
+ mAttributionChains.remove(attributionChainId);
+ return;
+ }
+
+ ArrayList<AccessChainLink> currentChain = mAttributionChains.computeIfAbsent(
+ attributionChainId, k -> new ArrayList<>());
+ AccessChainLink link = new AccessChainLink(op, packageName, attributionTag, uid,
+ attributionFlags);
+
+ int currSize = currentChain.size();
+ if (currSize == 0 || link.isEnd() || !currentChain.get(currSize - 1).isEnd()) {
+ // if the list is empty, this link is the end, or the last link in the current chain
+ // isn't the end, add it to the end
+ currentChain.add(link);
+ } else if (link.isStart()) {
+ currentChain.add(0, link);
+ } else if (currentChain.get(currentChain.size() - 1).isEnd()) {
+ // we already have the end, and this is a mid node, so insert before the end
+ currentChain.add(currSize - 1, link);
+ }
+ }
+
/**
* @see PermissionManager.getIndicatorAppOpUsageData
*/
@@ -331,7 +380,7 @@
private ArrayMap<OpUsage, CharSequence> getUniqueUsagesWithLabels(List<OpUsage> usages) {
ArrayMap<OpUsage, CharSequence> usagesAndLabels = new ArrayMap<>();
- if (usages == null) {
+ if (usages == null || usages.isEmpty()) {
return usagesAndLabels;
}
@@ -430,8 +479,51 @@
}
iterNum++;
}
- usagesAndLabels.put(start,
- proxyLabelList.isEmpty() ? null : formatLabelList(proxyLabelList));
+
+ // TODO ntmyren: remove this proxy logic once camera is converted to AttributionSource
+ // For now: don't add mic proxy usages
+ if (!start.op.equals(OPSTR_RECORD_AUDIO)) {
+ usagesAndLabels.put(start,
+ proxyLabelList.isEmpty() ? null : formatLabelList(proxyLabelList));
+ }
+ }
+
+ for (int i = 0; i < mAttributionChains.size(); i++) {
+ List<AccessChainLink> usageList = mAttributionChains.valueAt(i);
+ int lastVisible = usageList.size() - 1;
+ // TODO ntmyren: remove this mic code once camera is converted to AttributionSource
+ // if the list is empty or incomplete, do not show it.
+ if (usageList.isEmpty() || !usageList.get(lastVisible).isEnd()
+ || !usageList.get(0).isStart()
+ || !usageList.get(lastVisible).usage.op.equals(OPSTR_RECORD_AUDIO)) {
+ continue;
+ }
+
+ //TODO ntmyren: remove once camera etc. etc.
+ for (AccessChainLink link: usageList) {
+ proxyPackages.add(link.usage.getPackageIdHash());
+ }
+
+ AccessChainLink start = usageList.get(0);
+ AccessChainLink lastVisibleLink = usageList.get(lastVisible);
+ while (lastVisible > 0 && !shouldShowPackage(lastVisibleLink.usage.packageName)) {
+ lastVisible--;
+ lastVisibleLink = usageList.get(lastVisible);
+ }
+ String proxyLabel = null;
+ if (!lastVisibleLink.usage.packageName.equals(start.usage.packageName)) {
+ try {
+ PackageManager userPkgManager =
+ getUserContext(lastVisibleLink.usage.getUser()).getPackageManager();
+ ApplicationInfo appInfo = userPkgManager.getApplicationInfo(
+ lastVisibleLink.usage.packageName, 0);
+ proxyLabel = appInfo.loadLabel(userPkgManager).toString();
+ } catch (PackageManager.NameNotFoundException e) {
+ // do nothing
+ }
+
+ }
+ usagesAndLabels.put(start.usage, proxyLabel);
}
for (int packageHash : mostRecentUsages.keySet()) {
@@ -495,4 +587,24 @@
&& lastAccessTime == other.lastAccessTime && isRunning == other.isRunning;
}
}
+
+ private static class AccessChainLink {
+ public final OpUsage usage;
+ public final @AttributionFlags int flags;
+
+ AccessChainLink(String op, String packageName, String attributionTag, int uid,
+ int flags) {
+ this.usage = new OpUsage(packageName, attributionTag, op, uid,
+ System.currentTimeMillis(), true, null);
+ this.flags = flags;
+ }
+
+ public boolean isEnd() {
+ return (flags & ATTRIBUTION_FLAG_ACCESSOR) != 0;
+ }
+
+ public boolean isStart() {
+ return (flags & ATTRIBUTION_FLAG_RECEIVER) != 0;
+ }
+ }
}
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index fed28df..67b97ce 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -354,6 +354,13 @@
null);
}
+ EventPayload(boolean triggerAvailable, boolean captureAvailable,
+ AudioFormat audioFormat, int captureSession, byte[] data,
+ HotwordDetectedResult hotwordDetectedResult) {
+ this(triggerAvailable, captureAvailable, audioFormat, captureSession, data,
+ hotwordDetectedResult, null);
+ }
+
EventPayload(AudioFormat audioFormat, HotwordDetectedResult hotwordDetectedResult) {
this(false, false, audioFormat, -1, null, hotwordDetectedResult, null);
}
@@ -1149,7 +1156,8 @@
}
@Override
- public void onKeyphraseDetected(KeyphraseRecognitionEvent event) {
+ public void onKeyphraseDetected(
+ KeyphraseRecognitionEvent event, HotwordDetectedResult result) {
if (DBG) {
Slog.d(TAG, "onDetected(" + event + ")");
} else {
@@ -1157,7 +1165,7 @@
}
Message.obtain(mHandler, MSG_HOTWORD_DETECTED,
new EventPayload(event.triggerInData, event.captureAvailable,
- event.captureFormat, event.captureSession, event.data))
+ event.captureFormat, event.captureSession, event.data, result))
.sendToTarget();
}
@Override
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index deb6c01..b66d93d 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -31,6 +31,7 @@
import android.content.Intent;
import android.hardware.soundtrigger.SoundTrigger;
import android.media.AudioFormat;
+import android.media.AudioSystem;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
@@ -187,6 +188,11 @@
}
@Override
+ public void updateAudioFlinger(IBinder audioFlinger) {
+ AudioSystem.setAudioFlingerBinder(audioFlinger);
+ }
+
+ @Override
public void updateContentCaptureManager(IContentCaptureManager manager,
ContentCaptureOptions options) {
mContentCaptureManager = new ContentCaptureManager(
diff --git a/core/java/android/service/voice/IHotwordDetectionService.aidl b/core/java/android/service/voice/IHotwordDetectionService.aidl
index 72dd45a..d7ed678 100644
--- a/core/java/android/service/voice/IHotwordDetectionService.aidl
+++ b/core/java/android/service/voice/IHotwordDetectionService.aidl
@@ -19,6 +19,7 @@
import android.content.ContentCaptureOptions;
import android.hardware.soundtrigger.SoundTrigger;
import android.media.AudioFormat;
+import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
@@ -50,6 +51,8 @@
in SharedMemory sharedMemory,
in IRemoteCallback callback);
+ void updateAudioFlinger(in IBinder audioFlinger);
+
void updateContentCaptureManager(
in IContentCaptureManager contentCaptureManager,
in ContentCaptureOptions options);
diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java
index 47f2c64..204e7df 100644
--- a/core/java/android/service/voice/SoftwareHotwordDetector.java
+++ b/core/java/android/service/voice/SoftwareHotwordDetector.java
@@ -147,8 +147,9 @@
}
@Override
- public void onKeyphraseDetected(SoundTrigger.KeyphraseRecognitionEvent recognitionEvent)
- throws RemoteException {
+ public void onKeyphraseDetected(
+ SoundTrigger.KeyphraseRecognitionEvent recognitionEvent,
+ HotwordDetectedResult result) {
}
diff --git a/core/java/android/service/voice/VoiceInteractionManagerInternal.java b/core/java/android/service/voice/VoiceInteractionManagerInternal.java
index f5c9591..c048286 100644
--- a/core/java/android/service/voice/VoiceInteractionManagerInternal.java
+++ b/core/java/android/service/voice/VoiceInteractionManagerInternal.java
@@ -16,9 +16,12 @@
package android.service.voice;
+import android.annotation.Nullable;
import android.os.Bundle;
import android.os.IBinder;
+import com.android.internal.annotations.Immutable;
+
/**
* @hide
@@ -46,4 +49,38 @@
* Returns whether the given package is currently in an active session
*/
public abstract boolean hasActiveSession(String packageName);
+
+ /**
+ * Gets the identity of the currently active HotwordDetectionService.
+ *
+ * @see HotwordDetectionServiceIdentity
+ */
+ @Nullable
+ public abstract HotwordDetectionServiceIdentity getHotwordDetectionServiceIdentity();
+
+ /**
+ * Provides the uids of the currently active
+ * {@link android.service.voice.HotwordDetectionService} and its owning package. The
+ * HotwordDetectionService is an isolated service, so it has a separate uid.
+ */
+ @Immutable
+ public static class HotwordDetectionServiceIdentity {
+ private final int mIsolatedUid;
+ private final int mOwnerUid;
+
+ public HotwordDetectionServiceIdentity(int isolatedUid, int ownerUid) {
+ mIsolatedUid = isolatedUid;
+ mOwnerUid = ownerUid;
+ }
+
+ /** Gets the uid of the currently active isolated process hosting the service. */
+ public int getIsolatedUid() {
+ return mIsolatedUid;
+ }
+
+ /** Gets the uid of the package that provides the HotwordDetectionService. */
+ public int getOwnerUid() {
+ return mOwnerUid;
+ }
+ }
}
\ No newline at end of file
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 085136e..05ed75a 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -157,7 +157,7 @@
private static final int NOTIFY_COLORS_RATE_LIMIT_MS = 1000;
private static final boolean ENABLE_WALLPAPER_DIMMING =
- SystemProperties.getBoolean("persist.debug.enable_wallpaper_dimming", false);
+ SystemProperties.getBoolean("persist.debug.enable_wallpaper_dimming", true);
private final ArrayList<Engine> mActiveEngines
= new ArrayList<Engine>();
@@ -1511,9 +1511,12 @@
void updatePage(EngineWindowPage currentPage, int pageIndx, int numPages,
float xOffsetStep) {
// to save creating a runnable, check twice
- long current = System.nanoTime() / 1_000_000;
+ long current = SystemClock.elapsedRealtime();
long lapsed = current - currentPage.getLastUpdateTime();
- if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) {
+ // Always update the page when the last update time is <= 0
+ // This is important especially when the device first boots
+ if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION
+ && currentPage.getLastUpdateTime() > 0) {
return;
}
Surface surface = mSurfaceHolder.getSurface();
@@ -1764,6 +1767,7 @@
float finalStep = step;
int finalPageIndx = pageIndx;
Bitmap screenShot = page.getBitmap();
+ if (screenShot == null) screenShot = mLastScreenshot;
if (screenShot == null || screenShot.isRecycled()) {
if (DEBUG) {
Log.d(TAG, "invalid bitmap " + screenShot
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index b9ff5e7..055e71f 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -33,10 +33,13 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.util.function.pooled.PooledLambda;
+
import java.lang.ref.WeakReference;
import java.util.Objects;
@@ -226,6 +229,27 @@
protected abstract void onStopListening(Callback listener);
@Override
+ public Context createContext(@NonNull ContextParams contextParams) {
+ if (contextParams.getNextAttributionSource() != null) {
+ if (mHandler.getLooper().equals(Looper.myLooper())) {
+ handleAttributionContextCreation(contextParams.getNextAttributionSource());
+ } else {
+ mHandler.sendMessage(
+ PooledLambda.obtainMessage(this::handleAttributionContextCreation,
+ contextParams.getNextAttributionSource()));
+ }
+ }
+ return super.createContext(contextParams);
+ }
+
+ private void handleAttributionContextCreation(@NonNull AttributionSource attributionSource) {
+ if (mCurrentCallback != null
+ && mCurrentCallback.mCallingAttributionSource.equals(attributionSource)) {
+ mCurrentCallback.mAttributionContextCreated = true;
+ }
+ }
+
+ @Override
public final IBinder onBind(final Intent intent) {
if (DBG) Log.d(TAG, "onBind, intent=" + intent);
return mBinder;
@@ -249,6 +273,7 @@
private final IRecognitionListener mListener;
private final @NonNull AttributionSource mCallingAttributionSource;
private @Nullable Context mAttributionContext;
+ private boolean mAttributionContextCreated;
private Callback(IRecognitionListener listener,
@NonNull AttributionSource attributionSource) {
@@ -421,7 +446,7 @@
}
private boolean checkPermissionAndStartDataDelivery() {
- if (isPerformingDataDelivery()) {
+ if (mCurrentCallback.mAttributionContextCreated) {
return true;
}
if (PermissionChecker.checkPermissionAndStartDataDelivery(
@@ -441,13 +466,4 @@
mCurrentCallback.getAttributionContextForCaller().getAttributionSource());
}
}
-
- @SuppressWarnings("ConstantCondition")
- private boolean isPerformingDataDelivery() {
- final int op = AppOpsManager.permissionToOpCode(Manifest.permission.RECORD_AUDIO);
- final AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
- return appOpsManager.isProxying(op, getAttributionTag(),
- mCurrentCallback.getCallingAttributionSource().getUid(),
- mCurrentCallback.getCallingAttributionSource().getPackageName());
- }
}
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 37a97ca..94da93e 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -309,11 +309,16 @@
* {@link #setRecognitionListener(RecognitionListener)} should be called before dispatching any
* command to the created {@code SpeechRecognizer}, otherwise no notifications will be
* received.
- *
* Use this version of the method to specify a specific service to direct this
- * {@link SpeechRecognizer} to. Normally you would not use this; use
- * {@link #createSpeechRecognizer(Context)} instead to use the system default recognition
- * service.
+ * {@link SpeechRecognizer} to.
+ *
+ * <p><strong>Important</strong>: before calling this method, please check via
+ * {@link android.content.pm.PackageManager#queryIntentServices(Intent, int)} that {@code
+ * serviceComponent} actually exists and provides
+ * {@link RecognitionService#SERVICE_INTERFACE}. Normally you would not use this; call
+ * {@link #createSpeechRecognizer(Context)} to use the system default recognition
+ * service instead or {@link #createOnDeviceSpeechRecognizer(Context)} to use on-device
+ * recognition.</p>
*
* <p>For apps targeting Android 11 (API level 30) interaction with a speech recognition
* service requires <queries> element to be added to the manifest file:
diff --git a/core/java/android/uwb/AdapterStateListener.java b/core/java/android/uwb/AdapterStateListener.java
index 91847f7..7e82cc6 100644
--- a/core/java/android/uwb/AdapterStateListener.java
+++ b/core/java/android/uwb/AdapterStateListener.java
@@ -108,16 +108,13 @@
*/
public void setEnabled(boolean isEnabled) {
synchronized (this) {
- if (!mIsRegistered) {
- return;
- } else {
- try {
- mAdapter.setEnabled(isEnabled);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to set adapter state");
- throw e.rethrowFromSystemServer();
- }
+ try {
+ mAdapter.setEnabled(isEnabled);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set adapter state");
+ throw e.rethrowFromSystemServer();
}
+
}
}
diff --git a/core/java/android/view/CrossWindowBlurListeners.java b/core/java/android/view/CrossWindowBlurListeners.java
index 55fc4f4..e307b96 100644
--- a/core/java/android/view/CrossWindowBlurListeners.java
+++ b/core/java/android/view/CrossWindowBlurListeners.java
@@ -42,7 +42,7 @@
// property for background blur support in surface flinger
private static final String BLUR_PROPERTY = "ro.surface_flinger.supports_background_blur";
public static final boolean CROSS_WINDOW_BLUR_SUPPORTED =
- SystemProperties.get(BLUR_PROPERTY, "default").equals("1");
+ SystemProperties.getBoolean(BLUR_PROPERTY, false);
private static volatile CrossWindowBlurListeners sInstance;
private static final Object sLock = new Object();
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 6a2b723..61f524f 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -154,4 +154,13 @@
* app.
*/
void detachNavigationBarFromApp(boolean moveHomeToTop);
+
+ /**
+ * Used for animating the navigation bar during app launch from recents in live tile mode.
+ *
+ * First fade out the navigation bar at the bottom of the display and then fade in to the app.
+ *
+ * @param duration the duration of the app launch animation
+ */
+ void animateNavigationBarToApp(long duration);
}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 8d59ba0..b8b13b9 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -65,13 +65,20 @@
/**
* Called when the window insets configuration has changed.
+ *
+ * @param willMove The window frame will be moved soon.
+ * @param willResize The window frame will be resized soon.
*/
- void insetsChanged(in InsetsState insetsState);
+ void insetsChanged(in InsetsState insetsState, in boolean willMove, in boolean willResize);
/**
* Called when this window retrieved control over a specified set of insets sources.
+ *
+ * @param willMove The window frame will be moved soon.
+ * @param willResize The window frame will be resized soon.
*/
- void insetsControlChanged(in InsetsState insetsState, in InsetsSourceControl[] activeControls);
+ void insetsControlChanged(in InsetsState insetsState, in InsetsSourceControl[] activeControls,
+ in boolean willMove, in boolean willResize);
/**
* Called when a set of insets source window should be shown by policy.
diff --git a/core/java/android/view/ScrollCaptureTarget.java b/core/java/android/view/ScrollCaptureTarget.java
index 4fd4889..44017ed 100644
--- a/core/java/android/view/ScrollCaptureTarget.java
+++ b/core/java/android/view/ScrollCaptureTarget.java
@@ -16,6 +16,8 @@
package android.view;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UiThread;
@@ -46,11 +48,11 @@
public ScrollCaptureTarget(@NonNull View scrollTarget, @NonNull Rect localVisibleRect,
@NonNull Point positionInWindow, @NonNull ScrollCaptureCallback callback) {
- mContainingView = scrollTarget;
+ mContainingView = requireNonNull(scrollTarget);
mHint = mContainingView.getScrollCaptureHint();
- mCallback = callback;
- mLocalVisibleRect = localVisibleRect;
- mPositionInWindow = positionInWindow;
+ mCallback = requireNonNull(callback);
+ mLocalVisibleRect = requireNonNull(localVisibleRect);
+ mPositionInWindow = requireNonNull(positionInWindow);
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 8138b3d3..a8fe875 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9808,23 +9808,9 @@
*/
private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
AttachInfo ai = mAttachInfo;
- // Skip it while the view is being laided out for the first time
+ // Skip it while the view is being laid out for the first time
if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW,
- "notifyContentCapture(" + appeared + ") for " + getClass().getSimpleName());
- }
- try {
- notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(appeared);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- }
-
- private void notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(boolean appeared) {
- AttachInfo ai = mAttachInfo;
-
// First check if context has client, so it saves a service lookup when it doesn't
if (mContext.getContentCaptureOptions() == null) return;
@@ -30943,6 +30929,16 @@
}
/**
+ * Clears the ViewTranslationResponse stored by the default implementation of {@link
+ * #onViewTranslationResponse}.
+ *
+ * @hide
+ */
+ public void clearViewTranslationResponse() {
+ mViewTranslationResponse = null;
+ }
+
+ /**
* Called when the content from {@link View#onCreateVirtualViewTranslationRequests} had been
* translated by the TranslationService.
*
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 538b888..73294b3 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -953,8 +953,7 @@
private final Callable<OutputStream> mCallback;
private final Executor mExecutor;
private final ReentrantLock mLock = new ReentrantLock(false);
- private final ArrayDeque<byte[]> mQueue = new ArrayDeque<>(3);
- private final ByteArrayOutputStream mByteStream = new ByteArrayOutputStream();
+ private final ArrayDeque<Picture> mQueue = new ArrayDeque<>(3);
private boolean mStopListening;
private Thread mRenderThread;
@@ -990,9 +989,7 @@
mQueue.removeLast();
needsInvoke = false;
}
- picture.writeToStream(mByteStream);
- mQueue.add(mByteStream.toByteArray());
- mByteStream.reset();
+ mQueue.add(picture);
mLock.unlock();
if (needsInvoke) {
@@ -1003,7 +1000,7 @@
@Override
public void run() {
mLock.lock();
- final byte[] picture = mQueue.poll();
+ final Picture picture = mQueue.poll();
final boolean isStopped = mStopListening;
mLock.unlock();
if (Thread.currentThread() == mRenderThread) {
@@ -1024,7 +1021,8 @@
}
if (stream != null) {
try {
- stream.write(picture);
+ picture.writeToStream(stream);
+ stream.flush();
} catch (IOException ex) {
Log.w("ViewDebug", "Aborting rendering commands capture "
+ "due to IOException writing to output stream", ex);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 67cf85c..d42e0c3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -585,6 +585,10 @@
final Rect mWinFrame; // frame given by window manager.
final Rect mPendingBackDropFrame = new Rect();
+
+ private boolean mWillMove;
+ private boolean mWillResize;
+
boolean mPendingAlwaysConsumeSystemBars;
private final InsetsState mTempInsets = new InsetsState();
private final InsetsSourceControl[] mTempControls = new InsetsSourceControl[SIZE];
@@ -1406,8 +1410,6 @@
final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
attrs.getTitle().toString());
- addASurfaceTransactionCallback();
- mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
updateColorModeIfNeeded(attrs.getColorMode());
updateForceDarkMode();
if (mAttachInfo.mThreadedRenderer != null) {
@@ -1416,6 +1418,8 @@
if (mHardwareRendererObserver != null) {
mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
}
+ addASurfaceTransactionCallback();
+ mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
}
}
}
@@ -1708,6 +1712,10 @@
void notifyInsetsChanged() {
mApplyInsetsRequested = true;
+ if (mWillMove || mWillResize) {
+ // The window frame will be changed soon. The following logic will be executed then.
+ return;
+ }
requestLayout();
// See comment for View.sForceLayoutWhenInsetsChanged
@@ -2665,7 +2673,7 @@
}
}
- if (mApplyInsetsRequested) {
+ if (mApplyInsetsRequested && !(mWillMove || mWillResize)) {
dispatchApplyInsets(host);
if (mLayoutRequested) {
// Short-circuit catching a new layout request here, so
@@ -5235,16 +5243,25 @@
break;
case MSG_RESIZED:
case MSG_RESIZED_REPORT: {
+ mWillMove = false;
+ mWillResize = false;
final SomeArgs args = (SomeArgs) msg.obj;
handleResized(msg.what, args);
args.recycle();
break;
}
- case MSG_INSETS_CHANGED:
- mInsetsController.onStateChanged((InsetsState) msg.obj);
+ case MSG_INSETS_CHANGED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mWillMove = args.argi1 == 1;
+ mWillResize = args.argi2 == 1;
+ mInsetsController.onStateChanged((InsetsState) args.arg1);
+ args.recycle();
break;
+ }
case MSG_INSETS_CONTROL_CHANGED: {
SomeArgs args = (SomeArgs) msg.obj;
+ mWillMove = args.argi1 == 1;
+ mWillResize = args.argi2 == 1;
// Deliver state change before control change, such that:
// a) When gaining control, controller can compare with server state to evaluate
@@ -5253,6 +5270,7 @@
// dispatched state as truth.
mInsetsController.onStateChanged((InsetsState) args.arg1);
mInsetsController.onControlsChanged((InsetsSourceControl[]) args.arg2);
+ args.recycle();
break;
}
case MSG_SHOW_INSETS: {
@@ -5270,6 +5288,7 @@
break;
}
case MSG_WINDOW_MOVED:
+ mWillMove = false;
if (mAdded) {
final int w = mWinFrame.width();
final int h = mWinFrame.height();
@@ -7744,6 +7763,8 @@
mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls);
}
setFrame(mTmpFrames.frame);
+ mWillMove = false;
+ mWillResize = false;
mInsetsController.onStateChanged(mTempInsets);
mInsetsController.onControlsChanged(mTempControls);
return relayoutResult;
@@ -8179,7 +8200,8 @@
mHandler.sendMessage(msg);
}
- private void dispatchInsetsChanged(InsetsState insetsState) {
+ private void dispatchInsetsChanged(InsetsState insetsState, boolean willMove,
+ boolean willResize) {
if (Binder.getCallingPid() == android.os.Process.myPid()) {
insetsState = new InsetsState(insetsState, true /* copySource */);
}
@@ -8190,11 +8212,15 @@
ImeTracing.getInstance().triggerClientDump("ViewRootImpl#dispatchInsetsChanged",
getInsetsController().getHost().getInputMethodManager(), null /* icProto */);
}
- mHandler.obtainMessage(MSG_INSETS_CHANGED, insetsState).sendToTarget();
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = insetsState;
+ args.argi1 = willMove ? 1 : 0;
+ args.argi2 = willResize ? 1 : 0;
+ mHandler.obtainMessage(MSG_INSETS_CHANGED, args).sendToTarget();
}
private void dispatchInsetsControlChanged(InsetsState insetsState,
- InsetsSourceControl[] activeControls) {
+ InsetsSourceControl[] activeControls, boolean willMove, boolean willResize) {
if (Binder.getCallingPid() == android.os.Process.myPid()) {
insetsState = new InsetsState(insetsState, true /* copySource */);
if (activeControls != null) {
@@ -8214,6 +8240,8 @@
SomeArgs args = SomeArgs.obtain();
args.arg1 = insetsState;
args.arg2 = activeControls;
+ args.argi1 = willMove ? 1 : 0;
+ args.argi2 = willResize ? 1 : 0;
mHandler.obtainMessage(MSG_INSETS_CONTROL_CHANGED, args).sendToTarget();
}
@@ -9560,19 +9588,20 @@
}
@Override
- public void insetsChanged(InsetsState insetsState) {
+ public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
- viewAncestor.dispatchInsetsChanged(insetsState);
+ viewAncestor.dispatchInsetsChanged(insetsState, willMove, willResize);
}
}
@Override
public void insetsControlChanged(InsetsState insetsState,
- InsetsSourceControl[] activeControls) {
+ InsetsSourceControl[] activeControls, boolean willMove, boolean willResize) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
- viewAncestor.dispatchInsetsControlChanged(insetsState, activeControls);
+ viewAncestor.dispatchInsetsControlChanged(
+ insetsState, activeControls, willMove, willResize);
}
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index ad4ba76..aee540f 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -44,8 +44,9 @@
import android.os.IBinder.DeathRecipient;
import android.os.RemoteException;
import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
import android.text.TextUtils;
-import android.util.ArrayMap;
import android.util.LocalLog;
import android.util.Log;
import android.util.TimeUtils;
@@ -60,7 +61,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -151,12 +151,6 @@
private final LocalLog mFlushHistory;
/**
- * If the event in the buffer is of type {@link TYPE_VIEW_TEXT_CHANGED}, this value
- * indicates whether the event has composing span or not.
- */
- private final Map<AutofillId, Boolean> mLastComposingSpan = new ArrayMap<>();
-
- /**
* Binder object used to update the session state.
*/
@NonNull
@@ -352,40 +346,34 @@
// 2.1 either last or current text is empty: add.
// 2.2 last event doesn't have composing span: add.
// Otherwise, merge.
-
final CharSequence text = event.getText();
final boolean textHasComposingSpan = event.getTextHasComposingSpan();
-
- if (textHasComposingSpan && !mLastComposingSpan.isEmpty()) {
- final Boolean lastEventHasComposingSpan = mLastComposingSpan.get(event.getId());
- if (lastEventHasComposingSpan != null && lastEventHasComposingSpan.booleanValue()) {
- ContentCaptureEvent lastEvent = null;
- for (int index = mEvents.size() - 1; index >= 0; index--) {
- final ContentCaptureEvent tmpEvent = mEvents.get(index);
- if (event.getId().equals(tmpEvent.getId())) {
- lastEvent = tmpEvent;
- break;
- }
+ if (textHasComposingSpan) {
+ ContentCaptureEvent lastEvent = null;
+ for (int index = mEvents.size() - 1; index >= 0; index--) {
+ final ContentCaptureEvent tmpEvent = mEvents.get(index);
+ if (event.getId().equals(tmpEvent.getId())) {
+ lastEvent = tmpEvent;
+ break;
}
- if (lastEvent != null) {
- final CharSequence lastText = lastEvent.getText();
- final boolean bothNonEmpty = !TextUtils.isEmpty(lastText)
- && !TextUtils.isEmpty(text);
- boolean equalContent = TextUtils.equals(lastText, text);
- if (equalContent) {
- addEvent = false;
- } else if (bothNonEmpty && lastEventHasComposingSpan) {
- lastEvent.mergeEvent(event);
- addEvent = false;
- }
- if (!addEvent && sVerbose) {
- Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text="
- + getSanitizedString(text));
- }
+ }
+ if (lastEvent != null && lastEvent.getTextHasComposingSpan()) {
+ final CharSequence lastText = lastEvent.getText();
+ final boolean bothNonEmpty = !TextUtils.isEmpty(lastText)
+ && !TextUtils.isEmpty(text);
+ boolean equalContent = TextUtils.equals(lastText, text);
+ if (equalContent) {
+ addEvent = false;
+ } else if (bothNonEmpty) {
+ lastEvent.mergeEvent(event);
+ addEvent = false;
+ }
+ if (!addEvent && sVerbose) {
+ Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text="
+ + getSanitizedString(text));
}
}
}
- mLastComposingSpan.put(event.getId(), textHasComposingSpan);
}
if (!mEvents.isEmpty() && eventType == TYPE_VIEW_DISAPPEARED) {
@@ -586,7 +574,6 @@
? Collections.EMPTY_LIST
: new ArrayList<>(mEvents);
mEvents.clear();
- mLastComposingSpan.clear();
return new ParceledListSlice<>(events);
}
@@ -717,7 +704,7 @@
// Since the same CharSequence instance may be reused in the TextView, we need to make
// a copy of its content so that its value will not be changed by subsequent updates
// in the TextView.
- final String eventText = text == null ? null : text.toString();
+ final CharSequence eventText = stringOrSpannedStringWithoutNoCopySpans(text);
final boolean textHasComposingSpan =
text instanceof Spannable && BaseInputConnection.getComposingSpanStart(
(Spannable) text) >= 0;
@@ -726,6 +713,16 @@
.setAutofillId(id).setText(eventText, textHasComposingSpan)));
}
+ private CharSequence stringOrSpannedStringWithoutNoCopySpans(CharSequence source) {
+ if (source == null) {
+ return null;
+ } else if (source instanceof Spanned) {
+ return new SpannableString(source, /* ignoreNoCopySpan= */ true);
+ } else {
+ return source.toString();
+ }
+ }
+
/** Public because is also used by ViewRootImpl */
public void notifyViewInsetsChanged(int sessionId, @NonNull Insets viewInsets) {
mHandler.post(() -> sendEvent(new ContentCaptureEvent(sessionId, TYPE_VIEW_INSETS_CHANGED)
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index bf2af51..5ac878d 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -90,6 +90,8 @@
@NonNull
private final Handler mWorkerHandler;
private int mCurrentState;
+ @NonNull
+ private ArraySet<AutofillId> mLastRequestAutofillIds;
public UiTranslationController(Activity activity, Context context) {
mActivity = activity;
@@ -120,6 +122,9 @@
+ (DEBUG ? (", views: " + views + ", spec: " + uiTranslationSpec) : ""));
synchronized (mLock) {
mCurrentState = state;
+ if (views != null) {
+ setLastRequestAutofillIdsLocked(views);
+ }
}
switch (state) {
case STATE_UI_TRANSLATION_STARTED:
@@ -150,6 +155,7 @@
destroyTranslators();
runForEachView((view, callback) -> {
callback.onClearTranslation(view);
+ view.clearViewTranslationResponse();
if (view.hasTranslationTransientState()) {
view.setHasTransientState(false);
view.setHasTranslationTransientState(false);
@@ -175,13 +181,25 @@
}
}
+ private void setLastRequestAutofillIdsLocked(List<AutofillId> views) {
+ if (mLastRequestAutofillIds == null) {
+ mLastRequestAutofillIds = new ArraySet<>();
+ }
+ if (mLastRequestAutofillIds.size() > 0) {
+ mLastRequestAutofillIds.clear();
+ }
+ mLastRequestAutofillIds.addAll(views);
+ }
+
/**
* Called to dump the translation information for Activity.
*/
public void dump(String outerPrefix, PrintWriter pw) {
pw.print(outerPrefix); pw.println("UiTranslationController:");
final String pfx = outerPrefix + " ";
- pw.print(pfx); pw.print("activity: "); pw.println(mActivity);
+ pw.print(pfx); pw.print("activity: "); pw.print(mActivity);
+ pw.print(pfx); pw.print("resumed: "); pw.println(mActivity.isResumed());
+ pw.print(pfx); pw.print("current state: "); pw.println(mCurrentState);
final int translatorSize = mTranslators.size();
pw.print(outerPrefix); pw.print("number translator: "); pw.println(translatorSize);
for (int i = 0; i < translatorSize; i++) {
@@ -244,13 +262,18 @@
pw.print(outerPrefix); pw.print("autofillId: "); pw.print(autofillId);
// TODO: print TranslationTransformation
boolean isContainsView = false;
+ boolean isRequestedView = false;
synchronized (mLock) {
+ if (mLastRequestAutofillIds.contains(autofillId)) {
+ isRequestedView = true;
+ }
final WeakReference<View> viewRef = mViews.get(autofillId);
if (viewRef != null && viewRef.get() != null) {
isContainsView = true;
}
}
- pw.print(outerPrefix); pw.print("isContainsView: "); pw.println(isContainsView);
+ pw.print(outerPrefix); pw.print("isContainsView: "); pw.print(isContainsView);
+ pw.print(outerPrefix); pw.print("isRequestedView: "); pw.println(isRequestedView);
}
/**
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 40cce7c..d596626 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -44,6 +44,7 @@
import java.time.Instant;
import java.time.LocalTime;
import java.time.ZoneId;
+import java.time.ZonedDateTime;
import java.util.Formatter;
import java.util.Locale;
@@ -451,7 +452,9 @@
if (mSecondHandTintInfo.mHasTintList || mSecondHandTintInfo.mHasTintBlendMode) {
mSecondHand = mSecondHandTintInfo.apply(mSecondHand);
}
- mSecondsTick.run();
+ // Re-run the tick runnable immediately as the presence or absence of a seconds hand affects
+ // the next time we need to tick the clock.
+ mTick.run();
mChanged = true;
invalidate();
@@ -583,10 +586,10 @@
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
// OK, this is gross but needed. This class is supported by the
- // remote views machanism and as a part of that the remote views
+ // remote views mechanism and as a part of that the remote views
// can be inflated by a context for another user without the app
// having interact users permission - just for loading resources.
- // For exmaple, when adding widgets from a user profile to the
+ // For example, when adding widgets from a user profile to the
// home screen. Therefore, we register the receiver as the current
// user not the one the context is for.
getContext().registerReceiverAsUser(mIntentReceiver,
@@ -616,14 +619,14 @@
private void onVisible() {
if (!mVisible) {
mVisible = true;
- mSecondsTick.run();
+ mTick.run();
}
}
private void onInvisible() {
if (mVisible) {
- removeCallbacks(mSecondsTick);
+ removeCallbacks(mTick);
mVisible = false;
}
}
@@ -760,6 +763,7 @@
}
}
+ /** Intent receiver for the time or time zone changing. */
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -767,36 +771,56 @@
createClock();
}
- onTimeChanged();
-
- invalidate();
+ mTick.run();
}
};
private boolean mReceiverAttached;
- private final Runnable mSecondsTick = new Runnable() {
+ private final Runnable mTick = new Runnable() {
@Override
public void run() {
removeCallbacks(this);
- if (!mVisible || mSecondHand == null) {
+ if (!mVisible) {
return;
}
Instant now = mClock.instant();
- LocalTime localTime = now.atZone(mClock.getZone()).toLocalTime();
- // How many milliseconds through the second we currently are.
- long millisOfSecond = Duration.ofNanos(localTime.getNano()).toMillis();
- // How many milliseconds there are between tick positions for the seconds hand.
- double millisPerTick = 1000 / (double) mSecondsHandFps;
- // How many milliseconds we are past the last tick position.
- long millisPastLastTick = Math.round(millisOfSecond % millisPerTick);
- // How many milliseconds there are until the next tick position.
- long millisUntilNextTick = Math.round(millisPerTick - millisPastLastTick);
- // If we are exactly at the tick position, this could be 0 milliseconds due to rounding.
- // In this case, advance by the full amount of millis to the next position.
- if (millisUntilNextTick <= 0) {
- millisUntilNextTick = Math.round(millisPerTick);
+ ZonedDateTime zonedDateTime = now.atZone(mClock.getZone());
+ LocalTime localTime = zonedDateTime.toLocalTime();
+
+ long millisUntilNextTick;
+ if (mSecondHand == null) {
+ // If there's no second hand, then tick at the start of the next minute.
+ //
+ // This must be done with ZonedDateTime as opposed to LocalDateTime to ensure proper
+ // handling of DST. Also note that because of leap seconds, it should not be assumed
+ // that one minute == 60 seconds.
+ Instant startOfNextMinute = zonedDateTime.plusMinutes(1).withSecond(0).toInstant();
+ millisUntilNextTick = Duration.between(now, startOfNextMinute).toMillis();
+ if (millisUntilNextTick <= 0) {
+ // This should never occur, but if it does, then just check the tick again in
+ // one minute to ensure we're always moving forward.
+ millisUntilNextTick = Duration.ofMinutes(1).toMillis();
+ }
+ } else {
+ // If there is a seconds hand, then determine the next tick point based on the fps.
+ //
+ // How many milliseconds through the second we currently are.
+ long millisOfSecond = Duration.ofNanos(localTime.getNano()).toMillis();
+ // How many milliseconds there are between tick positions for the seconds hand.
+ double millisPerTick = 1000 / (double) mSecondsHandFps;
+ // How many milliseconds we are past the last tick position.
+ long millisPastLastTick = Math.round(millisOfSecond % millisPerTick);
+ // How many milliseconds there are until the next tick position.
+ millisUntilNextTick = Math.round(millisPerTick - millisPastLastTick);
+ // If we are exactly at the tick position, this could be 0 milliseconds due to
+ // rounding. In this case, advance by the full amount of millis to the next
+ // position.
+ if (millisUntilNextTick <= 0) {
+ millisUntilNextTick = Math.round(millisPerTick);
+ }
}
+
// Schedule a callback for when the next tick should occur.
postDelayed(this, millisUntilNextTick);
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 25c84ba..8a044fd 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -114,6 +114,7 @@
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -812,27 +813,8 @@
AdapterView<?> av = (AdapterView<?>) target;
// The PendingIntent template is stored in the view's tag.
OnItemClickListener listener = (parent, view, position, id) -> {
- // The view should be a frame layout
- if (view instanceof ViewGroup) {
- ViewGroup vg = (ViewGroup) view;
-
- // AdapterViews contain their children in a frame
- // so we need to go one layer deeper here.
- if (parent instanceof AdapterViewAnimator) {
- vg = (ViewGroup) vg.getChildAt(0);
- }
- if (vg == null) return;
-
- RemoteResponse response = null;
- int childCount = vg.getChildCount();
- for (int i = 0; i < childCount; i++) {
- Object tag = vg.getChildAt(i).getTag(R.id.fillInIntent);
- if (tag instanceof RemoteResponse) {
- response = (RemoteResponse) tag;
- break;
- }
- }
- if (response == null) return;
+ RemoteResponse response = findRemoteResponseTag(view);
+ if (response != null) {
response.handleViewInteraction(view, handler);
}
};
@@ -845,6 +827,28 @@
}
}
+ @Nullable
+ private RemoteResponse findRemoteResponseTag(@Nullable View rootView) {
+ if (rootView == null) return null;
+
+ ArrayDeque<View> viewsToCheck = new ArrayDeque<>();
+ viewsToCheck.addLast(rootView);
+
+ while (!viewsToCheck.isEmpty()) {
+ View view = viewsToCheck.removeFirst();
+ Object tag = view.getTag(R.id.fillInIntent);
+ if (tag instanceof RemoteResponse) return (RemoteResponse) tag;
+ if (!(view instanceof ViewGroup)) continue;
+
+ ViewGroup viewGroup = (ViewGroup) view;
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ viewsToCheck.addLast(viewGroup.getChildAt(i));
+ }
+ }
+
+ return null;
+ }
+
@Override
public int getActionTag() {
return SET_PENDING_INTENT_TEMPLATE_TAG;
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index b1485ef..e48afb2 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -34,7 +34,6 @@
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.format.DateFormat;
@@ -45,6 +44,10 @@
import com.android.internal.R;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.TimeZone;
@@ -185,18 +188,29 @@
private final Runnable mTicker = new Runnable() {
public void run() {
- if (mStopTicking) {
+ removeCallbacks(this);
+ if (mStopTicking || !mShouldRunTicker) {
return; // Test disabled the clock ticks
}
onTimeChanged();
- long now = SystemClock.uptimeMillis();
- long next = now + (1000 - now % 1000);
+ Instant now = mTime.toInstant();
+ ZoneId zone = mTime.getTimeZone().toZoneId();
- Handler handler = getHandler();
- if (handler != null) {
- handler.postAtTime(mTicker, next);
+ ZonedDateTime nextTick;
+ if (mHasSeconds) {
+ nextTick = now.atZone(zone).plusSeconds(1).withNano(0);
+ } else {
+ nextTick = now.atZone(zone).plusMinutes(1).withSecond(0).withNano(0);
}
+
+ long millisUntilNextTick = Duration.between(now, nextTick.toInstant()).toMillis();
+ if (millisUntilNextTick <= 0) {
+ // This should never happen, but if it does, then tick again in a second.
+ millisUntilNextTick = 1000;
+ }
+
+ postDelayed(this, millisUntilNextTick);
}
};
@@ -519,8 +533,7 @@
mHasSeconds = DateFormat.hasSeconds(mFormat);
if (mShouldRunTicker && hadSeconds != mHasSeconds) {
- if (hadSeconds) getHandler().removeCallbacks(mTicker);
- else mTicker.run();
+ mTicker.run();
}
}
@@ -557,14 +570,10 @@
if (!mShouldRunTicker && isVisible) {
mShouldRunTicker = true;
- if (mHasSeconds) {
- mTicker.run();
- } else {
- onTimeChanged();
- }
+ mTicker.run();
} else if (mShouldRunTicker && !isVisible) {
mShouldRunTicker = false;
- getHandler().removeCallbacks(mTicker);
+ removeCallbacks(mTicker);
}
}
@@ -592,7 +601,6 @@
private void registerReceiver() {
final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index b35eb06..862829b 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -71,6 +71,9 @@
* Note that
* <a href="{@docRoot}reference/com/google/android/material/snackbar/Snackbar">Snackbars</a> are
* preferred for brief messages while the app is in the foreground.
+ * <p>
+ * Note that toasts being sent from the background are rate limited, so avoid sending such toasts
+ * in quick succession.
*
* <div class="special reference">
* <h3>Developer Guides</h3>
diff --git a/core/java/android/widget/ToastPresenter.java b/core/java/android/widget/ToastPresenter.java
index 0f2a3ca..eccff06 100644
--- a/core/java/android/widget/ToastPresenter.java
+++ b/core/java/android/widget/ToastPresenter.java
@@ -69,7 +69,7 @@
private final Context mContext;
private final Resources mResources;
private final WindowManager mWindowManager;
- private final AccessibilityManager mAccessibilityManager;
+ private final IAccessibilityManager mAccessibilityManager;
private final INotificationManager mNotificationManager;
private final String mPackageName;
private final WindowManager.LayoutParams mParams;
@@ -83,16 +83,7 @@
mWindowManager = context.getSystemService(WindowManager.class);
mNotificationManager = notificationManager;
mPackageName = packageName;
-
- // We obtain AccessibilityManager manually via its constructor instead of using method
- // AccessibilityManager.getInstance() for 2 reasons:
- // 1. We want to be able to inject IAccessibilityManager in tests to verify behavior.
- // 2. getInstance() caches the instance for the process even if we pass a different
- // context to it. This is problematic for multi-user because callers can pass a context
- // created via Context.createContextAsUser().
- mAccessibilityManager = new AccessibilityManager(context, accessibilityManager,
- context.getUserId());
-
+ mAccessibilityManager = accessibilityManager;
mParams = createLayoutParams();
}
@@ -283,7 +274,16 @@
* enabled.
*/
public void trySendAccessibilityEvent(View view, String packageName) {
- if (!mAccessibilityManager.isEnabled()) {
+ // We obtain AccessibilityManager manually via its constructor instead of using method
+ // AccessibilityManager.getInstance() for 2 reasons:
+ // 1. We want to be able to inject IAccessibilityManager in tests to verify behavior.
+ // 2. getInstance() caches the instance for the process even if we pass a different
+ // context to it. This is problematic for multi-user because callers can pass a context
+ // created via Context.createContextAsUser().
+ final AccessibilityManager accessibilityManager =
+ new AccessibilityManager(mContext, mAccessibilityManager, mContext.getUserId());
+ if (!accessibilityManager.isEnabled()) {
+ accessibilityManager.removeClient();
return;
}
AccessibilityEvent event = AccessibilityEvent.obtain(
@@ -291,7 +291,11 @@
event.setClassName(Toast.class.getName());
event.setPackageName(packageName);
view.dispatchPopulateAccessibilityEvent(event);
- mAccessibilityManager.sendAccessibilityEvent(event);
+ accessibilityManager.sendAccessibilityEvent(event);
+ // Every new instance of A11yManager registers an IA11yManagerClient object with the
+ // backing service. This client isn't removed until the calling process is destroyed,
+ // causing a leak here. We explicitly remove the client.
+ accessibilityManager.removeClient();
}
private void addToastView() {
diff --git a/core/java/android/window/SplashScreen.java b/core/java/android/window/SplashScreen.java
index 42a58fb..3e00758 100644
--- a/core/java/android/window/SplashScreen.java
+++ b/core/java/android/window/SplashScreen.java
@@ -16,6 +16,7 @@
package android.window;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.StyleRes;
import android.annotation.SuppressLint;
@@ -42,6 +43,24 @@
*/
public interface SplashScreen {
/**
+ * Force splash screen to be empty.
+ * @hide
+ */
+ int SPLASH_SCREEN_STYLE_EMPTY = 0;
+ /**
+ * Force splash screen to show icon.
+ * @hide
+ */
+ int SPLASH_SCREEN_STYLE_ICON = 1;
+
+ /** @hide */
+ @IntDef(prefix = { "SPLASH_SCREEN_STYLE_" }, value = {
+ SPLASH_SCREEN_STYLE_EMPTY,
+ SPLASH_SCREEN_STYLE_ICON
+ })
+ @interface SplashScreenStyle {}
+
+ /**
* <p>Specifies whether an {@link Activity} wants to handle the splash screen animation on its
* own. Normally the splash screen will show on screen before the content of the activity has
* been drawn, and disappear when the activity is showing on the screen. With this listener set,
diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java
index 000dfb2..6772afe 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -85,7 +85,6 @@
| FLAG_TRANSLUCENT_NAVIGATION | FLAG_TRANSLUCENT_STATUS;
private boolean mNotCopyable;
- private boolean mRevealAnimationSupported = true;
private int mInitBackgroundColor;
private int mInitIconBackgroundColor;
private View mIconView;
@@ -353,25 +352,6 @@
}
/**
- * If set to true, indicates to the system that this view can be dismissed by playing the
- * Reveal animation.
- * <p>
- * If the exit animation is handled by the client, the animation won't be played anyway.
- * @hide
- */
- public void setRevealAnimationSupported(boolean support) {
- mRevealAnimationSupported = support;
- }
-
- /**
- * Whether this view support reveal animation.
- * @hide
- */
- public boolean isRevealAnimationSupported() {
- return mRevealAnimationSupported;
- }
-
- /**
* Called when this {@link SplashScreenView} has been copied to be transferred to the client.
*
* @hide
diff --git a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
index 9bec505..ec99c95 100644
--- a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
+++ b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
@@ -17,6 +17,7 @@
package com.android.internal.app;
import android.hardware.soundtrigger.SoundTrigger;
+import android.service.voice.HotwordDetectedResult;
import android.service.voice.HotwordRejectedResult;
/**
@@ -29,8 +30,11 @@
* @param recognitionEvent Object containing data relating to the
* keyphrase recognition event such as keyphrase
* extras.
+ * @param result Successful detection result payload.
*/
- void onKeyphraseDetected(in SoundTrigger.KeyphraseRecognitionEvent recognitionEvent);
+ void onKeyphraseDetected(
+ in SoundTrigger.KeyphraseRecognitionEvent recognitionEvent,
+ in HotwordDetectedResult result);
/**
* Called when a generic sound trigger event is witnessed.
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index f718d40..418d16e 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -168,7 +168,7 @@
* @param packageName the package name of the app whose changes will be overridden
* @throws SecurityException if overriding changes is not permitted
*/
- void setOverridesOnReleaseBuilds(in CompatibilityOverrideConfig overrides, in String packageName);
+ void putOverridesOnReleaseBuilds(in CompatibilityOverrideConfig overrides, in String packageName);
/**
* Adds overrides to compatibility changes.
diff --git a/core/java/com/android/internal/graphics/palette/CelebiQuantizer.java b/core/java/com/android/internal/graphics/palette/CelebiQuantizer.java
index de6bf20..454fd00 100644
--- a/core/java/com/android/internal/graphics/palette/CelebiQuantizer.java
+++ b/core/java/com/android/internal/graphics/palette/CelebiQuantizer.java
@@ -19,26 +19,32 @@
import java.util.List;
/**
- * An implementation of Celebi's WSM quantizer, or, a Kmeans quantizer that starts with centroids
- * from a Wu quantizer to ensure 100% reproducible and quality results, and has some optimizations
- * to the Kmeans algorithm.
- *
+ * An implementation of Celebi's quantization method.
* See Celebi 2011, “Improving the Performance of K-Means for Color Quantization”
+ *
+ * First, Wu's quantizer runs. The results are used as starting points for a subsequent Kmeans
+ * run. Using Wu's quantizer ensures 100% reproducible quantization results, because the starting
+ * centroids are always the same. It also ensures high quality results, Wu is a box-cutting
+ * quantization algorithm, much like medican color cut. It minimizes variance, much like Kmeans.
+ * Wu is shown to be the highest quality box-cutting quantization algorithm.
+ *
+ * Second, a Kmeans quantizer tweaked for performance is run. Celebi calls this a weighted
+ * square means quantizer, or WSMeans. Optimizations include operating on a map of image pixels
+ * rather than all image pixels, and avoiding excess color distance calculations by using a
+ * matrix and geometrical properties to know when there won't be any cluster closer to a pixel.
*/
public class CelebiQuantizer implements Quantizer {
private List<Palette.Swatch> mSwatches;
- public CelebiQuantizer() { }
+ public CelebiQuantizer() {
+ }
@Override
public void quantize(int[] pixels, int maxColors) {
- WuQuantizer wu = new WuQuantizer(pixels, maxColors);
+ WuQuantizer wu = new WuQuantizer();
wu.quantize(pixels, maxColors);
- List<Palette.Swatch> wuSwatches = wu.getQuantizedColors();
- LABCentroid labCentroidProvider = new LABCentroid();
- WSMeansQuantizer kmeans =
- new WSMeansQuantizer(WSMeansQuantizer.createStartingCentroids(labCentroidProvider,
- wuSwatches), labCentroidProvider, pixels, maxColors);
+ WSMeansQuantizer kmeans = new WSMeansQuantizer(wu.getColors(), new LABPointProvider(),
+ wu.inputPixelToCount());
kmeans.quantize(pixels, maxColors);
mSwatches = kmeans.getQuantizedColors();
}
diff --git a/core/java/com/android/internal/graphics/palette/LABCentroid.java b/core/java/com/android/internal/graphics/palette/LABPointProvider.java
similarity index 92%
rename from core/java/com/android/internal/graphics/palette/LABCentroid.java
rename to core/java/com/android/internal/graphics/palette/LABPointProvider.java
index 408cf1f..21a2212 100644
--- a/core/java/com/android/internal/graphics/palette/LABCentroid.java
+++ b/core/java/com/android/internal/graphics/palette/LABPointProvider.java
@@ -26,11 +26,11 @@
* in L*a*b* space, also known as deltaE, is a universally accepted standard across industries
* and worldwide.
*/
-public class LABCentroid implements CentroidProvider {
+public class LABPointProvider implements PointProvider {
final ColorSpace.Connector mRgbToLab;
final ColorSpace.Connector mLabToRgb;
- public LABCentroid() {
+ public LABPointProvider() {
mRgbToLab = ColorSpace.connect(
ColorSpace.get(ColorSpace.Named.SRGB),
ColorSpace.get(ColorSpace.Named.CIE_LAB));
@@ -39,7 +39,7 @@
}
@Override
- public float[] getCentroid(int color) {
+ public float[] fromInt(int color) {
float r = Color.red(color) / 255.f;
float g = Color.green(color) / 255.f;
float b = Color.blue(color) / 255.f;
@@ -49,7 +49,7 @@
}
@Override
- public int getColor(float[] centroid) {
+ public int toInt(float[] centroid) {
float[] rgb = mLabToRgb.transform(centroid);
int color = Color.rgb(rgb[0], rgb[1], rgb[2]);
return color;
diff --git a/core/java/com/android/internal/graphics/palette/Mean.java b/core/java/com/android/internal/graphics/palette/Mean.java
deleted file mode 100644
index bde0363..0000000
--- a/core/java/com/android/internal/graphics/palette/Mean.java
+++ /dev/null
@@ -1,44 +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.internal.graphics.palette;
-
-import java.util.Random;
-
-/**
- * Represents a centroid in Kmeans algorithms.
- */
-public class Mean {
- public float[] center;
-
- /**
- * Constructor.
- *
- * @param upperBound maximum value of a dimension in the space Kmeans is optimizing in
- * @param random used to generate a random center
- */
- Mean(int upperBound, Random random) {
- center =
- new float[]{
- random.nextInt(upperBound + 1), random.nextInt(upperBound + 1),
- random.nextInt(upperBound + 1)
- };
- }
-
- Mean(float[] center) {
- this.center = center;
- }
-}
diff --git a/core/java/com/android/internal/graphics/palette/MeanBucket.java b/core/java/com/android/internal/graphics/palette/MeanBucket.java
deleted file mode 100644
index ae8858a..0000000
--- a/core/java/com/android/internal/graphics/palette/MeanBucket.java
+++ /dev/null
@@ -1,42 +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.internal.graphics.palette;
-
-import java.util.HashSet;
-import java.util.Set;
-
-class MeanBucket {
- float[] mTotal = {0.f, 0.f, 0.f};
- int mCount = 0;
- Set<Integer> mColors = new HashSet<>();
-
- void add(float[] colorAsDoubles, int color, int colorCount) {
- assert (colorAsDoubles.length == 3);
- mColors.add(color);
- mTotal[0] += (colorAsDoubles[0] * colorCount);
- mTotal[1] += (colorAsDoubles[1] * colorCount);
- mTotal[2] += (colorAsDoubles[2] * colorCount);
- mCount += colorCount;
- }
-
- float[] getCentroid() {
- if (mCount == 0) {
- return null;
- }
- return new float[]{mTotal[0] / mCount, mTotal[1] / mCount, mTotal[2] / mCount};
- }
-}
diff --git a/core/java/com/android/internal/graphics/palette/CentroidProvider.java b/core/java/com/android/internal/graphics/palette/PointProvider.java
similarity index 62%
rename from core/java/com/android/internal/graphics/palette/CentroidProvider.java
rename to core/java/com/android/internal/graphics/palette/PointProvider.java
index 5fcfcba..017adeb 100644
--- a/core/java/com/android/internal/graphics/palette/CentroidProvider.java
+++ b/core/java/com/android/internal/graphics/palette/PointProvider.java
@@ -18,21 +18,18 @@
import android.annotation.ColorInt;
-interface CentroidProvider {
- /**
- * @return 3 dimensions representing the color
- */
- float[] getCentroid(@ColorInt int color);
+/**
+ * Interface that allows quantizers to have a plug-and-play interface for experimenting with
+ * quantization in different color spaces.
+ */
+public interface PointProvider {
+ /** Convert a color to 3 coordinates representing the color in a color space. */
+ float[] fromInt(@ColorInt int argb);
- /**
- * @param centroid 3 dimensions representing the color
- * @return 32-bit ARGB representation
- */
+ /** Convert 3 coordinates in the color space into a color */
@ColorInt
- int getColor(float[] centroid);
+ int toInt(float[] point);
- /**
- * Distance between two centroids.
- */
+ /** Find the distance between two colosrin the color space */
float distance(float[] a, float[] b);
}
diff --git a/core/java/com/android/internal/graphics/palette/QuantizerMap.java b/core/java/com/android/internal/graphics/palette/QuantizerMap.java
new file mode 100644
index 0000000..6b60f61
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/QuantizerMap.java
@@ -0,0 +1,62 @@
+/*
+ * 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.graphics.palette;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Converts a set of pixels/colors into a map with keys of unique colors, and values of the count
+ * of the unique color in the original set of pixels.
+ *
+ * This allows other quantizers to get a significant speed boost by simply running this quantizer,
+ * and then performing operations using the map, rather than for each pixel.
+ */
+public final class QuantizerMap implements Quantizer {
+ private HashMap<Integer, Integer> mColorToCount;
+ private Palette mPalette;
+
+ @Override
+ public void quantize(@NonNull int[] pixels, int colorCount) {
+ final HashMap<Integer, Integer> colorToCount = new HashMap<>();
+ for (int pixel : pixels) {
+ colorToCount.merge(pixel, 1, Integer::sum);
+ }
+ mColorToCount = colorToCount;
+
+ List<Palette.Swatch> swatches = new ArrayList<>();
+ for (Map.Entry<Integer, Integer> entry : colorToCount.entrySet()) {
+ swatches.add(new Palette.Swatch(entry.getKey(), entry.getValue()));
+ }
+ mPalette = Palette.from(swatches);
+ }
+
+ @Override
+ public List<Palette.Swatch> getQuantizedColors() {
+ return mPalette.getSwatches();
+ }
+
+ @Nullable
+ public Map<Integer, Integer> getColorToCount() {
+ return mColorToCount;
+ }
+}
diff --git a/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java b/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java
index 1d865c2..19ed8d0 100644
--- a/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java
+++ b/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java
@@ -16,18 +16,20 @@
package com.android.internal.graphics.palette;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
-
/**
- * A color quantizer based on the Kmeans algorithm.
+ * A color quantizer based on the Kmeans algorithm. Prefer using QuantizerCelebi.
*
* This is an implementation of Kmeans based on Celebi's 2011 paper,
* "Improving the Performance of K-Means for Color Quantization". In the paper, this algorithm is
@@ -36,253 +38,237 @@
* well as indexing colors by their count, thus minimizing the number of points to move around.
*
* Celebi's paper also stabilizes results and guarantees high quality by using starting centroids
- * from Wu's quantization algorithm. See CelebiQuantizer for more info.
+ * from Wu's quantization algorithm. See QuantizerCelebi for more info.
*/
-public class WSMeansQuantizer implements Quantizer {
- Mean[] mMeans;
- private final Map<Integer, Integer> mCountByColor = new HashMap<>();
- private final Map<Integer, Integer> mMeanIndexByColor = new HashMap<>();
- private final Set<Integer> mUniqueColors = new HashSet<>();
- private final List<Palette.Swatch> mSwatches = new ArrayList<>();
- private final CentroidProvider mCentroidProvider;
+public final class WSMeansQuantizer implements Quantizer {
+ private static final String TAG = "QuantizerWsmeans";
+ private static final boolean DEBUG = false;
+ private static final int MAX_ITERATIONS = 10;
+ // Points won't be moved to a closer cluster, if the closer cluster is within
+ // this distance. 3.0 used because L*a*b* delta E < 3 is considered imperceptible.
+ private static final float MIN_MOVEMENT_DISTANCE = 3.0f;
- public WSMeansQuantizer(
- float[][] means, CentroidProvider centroidProvider, int[] pixels, int maxColors) {
- if (pixels == null) {
- pixels = new int[]{};
- }
- mCentroidProvider = centroidProvider;
- mMeans = new Mean[maxColors];
- for (int i = 0; i < means.length; i++) {
- mMeans[i] = new Mean(means[i]);
+ private final PointProvider mPointProvider;
+ private @Nullable Map<Integer, Integer> mInputPixelToCount;
+ private float[][] mClusters;
+ private int[] mClusterPopulations;
+ private float[][] mPoints;
+ private int[] mPixels;
+ private int[] mClusterIndices;
+ private int[][] mIndexMatrix = {};
+ private float[][] mDistanceMatrix = {};
+
+ private Palette mPalette;
+
+ public WSMeansQuantizer(int[] inClusters, PointProvider pointProvider,
+ @Nullable Map<Integer, Integer> inputPixelToCount) {
+ mPointProvider = pointProvider;
+
+ mClusters = new float[inClusters.length][3];
+ int index = 0;
+ for (int cluster : inClusters) {
+ float[] point = pointProvider.fromInt(cluster);
+ mClusters[index++] = point;
}
- if (maxColors > means.length) {
- // Always initialize Random with the same seed. Ensures the results of quantization
- // are consistent, even when random centroids are required.
- Random random = new Random(0x42688);
- int randomMeansToCreate = maxColors - means.length;
- for (int i = 0; i < randomMeansToCreate; i++) {
- mMeans[means.length + i] = new Mean(100, random);
- }
- }
-
- for (int pixel : pixels) {
- // These are pixels from the bitmap that is being quantized.
- // Depending on the bitmap & downscaling, it may have pixels that are less than opaque
- // Ignore those pixels.
- ///
- // Note: they don't _have_ to be ignored, for example, we could instead turn them
- // opaque. Traditionally, including outside Android, quantizers ignore transparent
- // pixels, so that strategy was chosen.
- int alpha = (pixel >> 24) & 0xff;
- if (alpha < 255) {
- continue;
- }
- Integer currentCount = mCountByColor.get(pixel);
- if (currentCount == null) {
- currentCount = 0;
- mUniqueColors.add(pixel);
- }
- mCountByColor.put(pixel, currentCount + 1);
- }
- for (int color : mUniqueColors) {
- int closestMeanIndex = -1;
- double closestMeanDistance = -1;
- float[] centroid = mCentroidProvider.getCentroid(color);
- for (int i = 0; i < mMeans.length; i++) {
- double distance = mCentroidProvider.distance(centroid, mMeans[i].center);
- if (closestMeanIndex == -1 || distance < closestMeanDistance) {
- closestMeanIndex = i;
- closestMeanDistance = distance;
- }
- }
- mMeanIndexByColor.put(color, closestMeanIndex);
- }
-
- if (pixels.length == 0) {
- return;
- }
-
- predict(maxColors, 0);
- }
-
- /** Create starting centroids for K-means from a set of colors. */
- public static float[][] createStartingCentroids(CentroidProvider centroidProvider,
- List<Palette.Swatch> swatches) {
- float[][] startingCentroids = new float[swatches.size()][];
- for (int i = 0; i < swatches.size(); i++) {
- startingCentroids[i] = centroidProvider.getCentroid(swatches.get(i).getInt());
- }
- return startingCentroids;
- }
-
- /** Create random starting centroids for K-means. */
- public static float[][] randomMeans(int maxColors, int upperBound) {
- float[][] means = new float[maxColors][];
-
- // Always initialize Random with the same seed. Ensures the results of quantization
- // are consistent, even when random centroids are required.
- Random random = new Random(0x42688);
- for (int i = 0; i < maxColors; i++) {
- means[i] = new Mean(upperBound, random).center;
- }
- return means;
- }
-
-
- @Override
- public void quantize(int[] pixels, int maxColors) {
-
+ mInputPixelToCount = inputPixelToCount;
}
@Override
public List<Palette.Swatch> getQuantizedColors() {
- return mSwatches;
+ return mPalette.getSwatches();
}
- private void predict(int maxColors, int iterationsCompleted) {
- double[][] centroidDistance = new double[maxColors][maxColors];
- for (int i = 0; i <= maxColors; i++) {
- for (int j = i + 1; j < maxColors; j++) {
- float[] meanI = mMeans[i].center;
- float[] meanJ = mMeans[j].center;
- double distance = mCentroidProvider.distance(meanI, meanJ);
- centroidDistance[i][j] = distance;
- centroidDistance[j][i] = distance;
+ @Override
+ public void quantize(@NonNull int[] pixels, int maxColors) {
+ assert (pixels.length > 0);
+
+ if (mInputPixelToCount == null) {
+ QuantizerMap mapQuantizer = new QuantizerMap();
+ mapQuantizer.quantize(pixels, maxColors);
+ mInputPixelToCount = mapQuantizer.getColorToCount();
+ }
+
+ mPoints = new float[mInputPixelToCount.size()][3];
+ mPixels = new int[mInputPixelToCount.size()];
+ int index = 0;
+ for (int pixel : mInputPixelToCount.keySet()) {
+ mPixels[index] = pixel;
+ mPoints[index] = mPointProvider.fromInt(pixel);
+ index++;
+ }
+ if (mClusters.length > 0) {
+ // This implies that the constructor was provided starting clusters. If that was the
+ // case, we limit the number of clusters to the number of starting clusters and don't
+ // initialize random clusters.
+ maxColors = Math.min(maxColors, mClusters.length);
+ }
+ maxColors = Math.min(maxColors, mPoints.length);
+
+ initializeClusters(maxColors);
+ for (int i = 0; i < MAX_ITERATIONS; i++) {
+ calculateClusterDistances(maxColors);
+ if (!reassignPoints(maxColors)) {
+ break;
}
- }
-
- // Construct a K×K matrix M in which row i is a permutation of
- // 1,2,…,K that represents the clusters in increasing order of
- // distance of their centers from ci;
- int[][] distanceMatrix = new int[maxColors][maxColors];
- for (int i = 0; i < maxColors; i++) {
- double[] distancesFromIToAnotherMean = centroidDistance[i];
- double[] sortedByDistanceAscending = distancesFromIToAnotherMean.clone();
- Arrays.sort(sortedByDistanceAscending);
- int[] outputRow = new int[maxColors];
- for (int j = 0; j < maxColors; j++) {
- outputRow[j] = findIndex(distancesFromIToAnotherMean, sortedByDistanceAscending[j]);
- }
- distanceMatrix[i] = outputRow;
- }
-
- // for (i=1;i≤N′;i=i+ 1) do
- // Let Sp be the cluster that xi was assigned to in the previous
- // iteration;
- // p=m[i];
- // min_dist=prev_dist=jjxi−cpjj2;
- boolean anyColorMoved = false;
- for (int intColor : mUniqueColors) {
- float[] color = mCentroidProvider.getCentroid(intColor);
- int indexOfCurrentMean = mMeanIndexByColor.get(intColor);
- Mean currentMean = mMeans[indexOfCurrentMean];
- double minDistance = mCentroidProvider.distance(color, currentMean.center);
- for (int j = 1; j < maxColors; j++) {
- int indexOfClusterFromCurrentToJ = distanceMatrix[indexOfCurrentMean][j];
- double distanceBetweenJAndCurrent =
- centroidDistance[indexOfCurrentMean][indexOfClusterFromCurrentToJ];
- if (distanceBetweenJAndCurrent >= (4 * minDistance)) {
- break;
- }
- double distanceBetweenJAndColor = mCentroidProvider.distance(mMeans[j].center,
- color);
- if (distanceBetweenJAndColor < minDistance) {
- minDistance = distanceBetweenJAndColor;
- mMeanIndexByColor.remove(intColor);
- mMeanIndexByColor.put(intColor, j);
- anyColorMoved = true;
- }
- }
- }
-
- List<MeanBucket> buckets = new ArrayList<>();
- for (int i = 0; i < maxColors; i++) {
- buckets.add(new MeanBucket());
- }
-
- for (int intColor : mUniqueColors) {
- int meanIndex = mMeanIndexByColor.get(intColor);
- MeanBucket meanBucket = buckets.get(meanIndex);
- meanBucket.add(mCentroidProvider.getCentroid(intColor), intColor,
- mCountByColor.get(intColor));
+ recalculateClusterCenters(maxColors);
}
List<Palette.Swatch> swatches = new ArrayList<>();
- boolean done = !anyColorMoved && iterationsCompleted > 0 || iterationsCompleted >= 100;
- if (done) {
- for (int i = 0; i < buckets.size(); i++) {
- MeanBucket a = buckets.get(i);
- if (a.mCount <= 0) {
- continue;
- }
- List<MeanBucket> bucketsToMerge = new ArrayList<>();
- for (int j = i + 1; j < buckets.size(); j++) {
- MeanBucket b = buckets.get(j);
- if (b.mCount == 0) {
- continue;
- }
- float[] bCentroid = b.getCentroid();
- assert (a.mCount > 0);
- assert (a.getCentroid() != null);
-
- assert (bCentroid != null);
- if (mCentroidProvider.distance(a.getCentroid(), b.getCentroid()) < 5) {
- bucketsToMerge.add(b);
- }
- }
-
- for (MeanBucket bucketToMerge : bucketsToMerge) {
- float[] centroid = bucketToMerge.getCentroid();
- a.add(centroid, mCentroidProvider.getColor(centroid), bucketToMerge.mCount);
- buckets.remove(bucketToMerge);
- }
- }
-
- for (MeanBucket bucket : buckets) {
- float[] centroid = bucket.getCentroid();
- if (centroid == null) {
- continue;
- }
-
- int rgb = mCentroidProvider.getColor(centroid);
- swatches.add(new Palette.Swatch(rgb, bucket.mCount));
- mSwatches.clear();
- mSwatches.addAll(swatches);
- }
- } else {
- List<MeanBucket> emptyBuckets = new ArrayList<>();
- for (int i = 0; i < buckets.size(); i++) {
- MeanBucket bucket = buckets.get(i);
- if ((bucket.getCentroid() == null) || (bucket.mCount == 0)) {
- emptyBuckets.add(bucket);
- for (Integer color : mUniqueColors) {
- int meanIndex = mMeanIndexByColor.get(color);
- if (meanIndex > i) {
- mMeanIndexByColor.put(color, meanIndex--);
- }
- }
- }
- }
-
- Mean[] newMeans = new Mean[buckets.size()];
- for (int i = 0; i < buckets.size(); i++) {
- float[] centroid = buckets.get(i).getCentroid();
- newMeans[i] = new Mean(centroid);
- }
-
- predict(buckets.size(), iterationsCompleted + 1);
+ for (int i = 0; i < maxColors; i++) {
+ float[] cluster = mClusters[i];
+ int colorInt = mPointProvider.toInt(cluster);
+ swatches.add(new Palette.Swatch(colorInt, mClusterPopulations[i]));
}
-
+ mPalette = Palette.from(swatches);
}
- private static int findIndex(double[] list, double element) {
- for (int i = 0; i < list.length; i++) {
- if (list[i] == element) {
- return i;
+
+ private void initializeClusters(int maxColors) {
+ boolean hadInputClusters = mClusters.length > 0;
+ if (!hadInputClusters) {
+ int additionalClustersNeeded = maxColors - mClusters.length;
+ if (DEBUG) {
+ Log.d(TAG, "have " + mClusters.length + " clusters, want " + maxColors
+ + " results, so need " + additionalClustersNeeded + " additional clusters");
+ }
+
+ Random random = new Random(0x42688);
+ List<float[]> additionalClusters = new ArrayList<>(additionalClustersNeeded);
+ Set<Integer> clusterIndicesUsed = new HashSet<>();
+ for (int i = 0; i < additionalClustersNeeded; i++) {
+ int index = random.nextInt(mPoints.length);
+ while (clusterIndicesUsed.contains(index)
+ && clusterIndicesUsed.size() < mPoints.length) {
+ index = random.nextInt(mPoints.length);
+ }
+ clusterIndicesUsed.add(index);
+ additionalClusters.add(mPoints[index]);
+ }
+
+ float[][] newClusters = (float[][]) additionalClusters.toArray();
+ float[][] clusters = Arrays.copyOf(mClusters, maxColors);
+ System.arraycopy(newClusters, 0, clusters, clusters.length, newClusters.length);
+ mClusters = clusters;
+ }
+
+ mClusterIndices = new int[mPixels.length];
+ mClusterPopulations = new int[mPixels.length];
+ Random random = new Random(0x42688);
+ for (int i = 0; i < mPixels.length; i++) {
+ int clusterIndex = random.nextInt(maxColors);
+ mClusterIndices[i] = clusterIndex;
+ mClusterPopulations[i] = mInputPixelToCount.get(mPixels[i]);
+ }
+ }
+
+ void calculateClusterDistances(int maxColors) {
+ if (mDistanceMatrix.length != maxColors) {
+ mDistanceMatrix = new float[maxColors][maxColors];
+ }
+
+ for (int i = 0; i <= maxColors; i++) {
+ for (int j = i + 1; j < maxColors; j++) {
+ float distance = mPointProvider.distance(mClusters[i], mClusters[j]);
+ mDistanceMatrix[j][i] = distance;
+ mDistanceMatrix[i][j] = distance;
}
}
- throw new IllegalArgumentException("Element not in list");
+
+ if (mIndexMatrix.length != maxColors) {
+ mIndexMatrix = new int[maxColors][maxColors];
+ }
+
+ for (int i = 0; i < maxColors; i++) {
+ ArrayList<Distance> distances = new ArrayList<>(maxColors);
+ for (int index = 0; index < maxColors; index++) {
+ distances.add(new Distance(index, mDistanceMatrix[i][index]));
+ }
+ distances.sort(
+ (a, b) -> Float.compare(a.getDistance(), b.getDistance()));
+
+ for (int j = 0; j < maxColors; j++) {
+ mIndexMatrix[i][j] = distances.get(j).getIndex();
+ }
+ }
+ }
+
+ boolean reassignPoints(int maxColors) {
+ boolean colorMoved = false;
+ for (int i = 0; i < mPoints.length; i++) {
+ float[] point = mPoints[i];
+ int previousClusterIndex = mClusterIndices[i];
+ float[] previousCluster = mClusters[previousClusterIndex];
+ float previousDistance = mPointProvider.distance(point, previousCluster);
+
+ float minimumDistance = previousDistance;
+ int newClusterIndex = -1;
+ for (int j = 1; j < maxColors; j++) {
+ int t = mIndexMatrix[previousClusterIndex][j];
+ if (mDistanceMatrix[previousClusterIndex][t] >= 4 * previousDistance) {
+ // Triangle inequality proves there's can be no closer center.
+ break;
+ }
+ float distance = mPointProvider.distance(point, mClusters[t]);
+ if (distance < minimumDistance) {
+ minimumDistance = distance;
+ newClusterIndex = t;
+ }
+ }
+ if (newClusterIndex != -1) {
+ float distanceChange = (float)
+ Math.abs((Math.sqrt(minimumDistance) - Math.sqrt(previousDistance)));
+ if (distanceChange > MIN_MOVEMENT_DISTANCE) {
+ colorMoved = true;
+ mClusterIndices[i] = newClusterIndex;
+ }
+ }
+ }
+ return colorMoved;
+ }
+
+ void recalculateClusterCenters(int maxColors) {
+ mClusterPopulations = new int[maxColors];
+ float[] aSums = new float[maxColors];
+ float[] bSums = new float[maxColors];
+ float[] cSums = new float[maxColors];
+ for (int i = 0; i < mPoints.length; i++) {
+ int clusterIndex = mClusterIndices[i];
+ float[] point = mPoints[i];
+ int pixel = mPixels[i];
+ int count = mInputPixelToCount.get(pixel);
+ mClusterPopulations[clusterIndex] += count;
+ aSums[clusterIndex] += point[0] * count;
+ bSums[clusterIndex] += point[1] * count;
+ cSums[clusterIndex] += point[2] * count;
+
+ }
+ for (int i = 0; i < maxColors; i++) {
+ int count = mClusterPopulations[i];
+ float aSum = aSums[i];
+ float bSum = bSums[i];
+ float cSum = cSums[i];
+ mClusters[i][0] = aSum / count;
+ mClusters[i][1] = bSum / count;
+ mClusters[i][2] = cSum / count;
+ }
+ }
+
+ private static class Distance {
+ private final int mIndex;
+ private final float mDistance;
+
+ int getIndex() {
+ return mIndex;
+ }
+
+ float getDistance() {
+ return mDistance;
+ }
+
+ Distance(int index, float distance) {
+ mIndex = index;
+ mDistance = distance;
+ }
}
}
diff --git a/core/java/com/android/internal/graphics/palette/WuQuantizer.java b/core/java/com/android/internal/graphics/palette/WuQuantizer.java
index a2652ea..1cd0d72 100644
--- a/core/java/com/android/internal/graphics/palette/WuQuantizer.java
+++ b/core/java/com/android/internal/graphics/palette/WuQuantizer.java
@@ -16,431 +16,447 @@
package com.android.internal.graphics.palette;
+import static java.lang.System.arraycopy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Color;
+
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
-// All reference Wu implementations are based on the original C code by Wu.
-// Comments on methods are the same as in the original implementation, and the comment below
-// is the original class header.
/**
- * Wu's Color Quantizer (v. 2) (see Graphics Gems vol. II, pp. 126-133) Author: Xiaolin Wu
+ * Wu's quantization algorithm is a box-cut quantizer that minimizes variance. It takes longer to
+ * run than, say, median color cut, but provides the highest quality results currently known.
*
- * <p>Algorithm: Greedy orthogonal bipartition of RGB space for variance minimization aided by
- * inclusion-exclusion tricks. For speed no nearest neighbor search is done. Slightly better
- * performance can be expected by more sophisticated but more expensive versions.
+ * Prefer `QuantizerCelebi`: coupled with Kmeans, this provides the best-known results for image
+ * quantization.
+ *
+ * Seemingly all Wu implementations are based off of one C code snippet that cites a book from 1992
+ * Graphics Gems vol. II, pp. 126-133. As a result, it is very hard to understand the mechanics of
+ * the algorithm, beyond the commentary provided in the C code. Comments on the methods of this
+ * class are avoided in favor of finding another implementation and reading the commentary there,
+ * avoiding perpetuating the same incomplete and somewhat confusing commentary here.
*/
-public class WuQuantizer implements Quantizer {
- private static final int MAX_COLORS = 256;
- private static final int RED = 2;
- private static final int GREEN = 1;
- private static final int BLUE = 0;
+public final class WuQuantizer implements Quantizer {
+ // A histogram of all the input colors is constructed. It has the shape of a
+ // cube. The cube would be too large if it contained all 16 million colors:
+ // historical best practice is to use 5 bits of the 8 in each channel,
+ // reducing the histogram to a volume of ~32,000.
+ private static final int BITS = 5;
+ private static final int MAX_INDEX = 32;
+ private static final int SIDE_LENGTH = 33;
+ private static final int TOTAL_SIZE = 35937;
- private static final int QUANT_SIZE = 33;
- private final List<Palette.Swatch> mSwatches = new ArrayList<>();
+ private int[] mWeights;
+ private int[] mMomentsR;
+ private int[] mMomentsG;
+ private int[] mMomentsB;
+ private double[] mMoments;
+ private Box[] mCubes;
+ private Palette mPalette;
+ private int[] mColors;
+ private Map<Integer, Integer> mInputPixelToCount;
@Override
public List<Palette.Swatch> getQuantizedColors() {
- return mSwatches;
- }
-
- private static final class Box {
- int mR0; /* min value, exclusive */
- int mR1; /* max value, inclusive */
- int mG0;
- int mG1;
- int mB0;
- int mB1;
- int mVol;
- }
-
- private final int mSize; /* image size, in bytes. */
- private int mMaxColors;
- private int[] mQadd;
- private final int[] mPixels;
-
- private final double[][][] mM2 = new double[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
- private final long[][][] mWt = new long[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
- private final long[][][] mMr = new long[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
- private final long[][][] mMg = new long[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
- private final long[][][] mMb = new long[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
-
- public WuQuantizer(int[] pixels, int maxColorCount) {
- if (pixels == null) {
- pixels = new int[]{};
- }
- this.mPixels = pixels;
- this.mSize = pixels.length;
+ return mPalette.getSwatches();
}
@Override
- public void quantize(int[] colors, int maxColorCount) {
- // All of the sample Wu implementations are reimplementations of a snippet of C code from
- // the early 90s. They all cap the maximum # of colors at 256, and it is impossible to tell
- // if this is a requirement, a consequence of QUANT_SIZE, or arbitrary.
- //
- // Also, the number of maximum colors should be capped at the number of pixels - otherwise,
- // If extraction is run on a set of pixels whose count is less than max colors,
- // then colors.length < max colors, and accesses to colors[index] throw an
- // ArrayOutOfBoundsException.
- this.mMaxColors = Math.min(Math.min(MAX_COLORS, maxColorCount), colors.length);
- Box[] cube = new Box[mMaxColors];
- int red, green, blue;
+ public void quantize(@NonNull int[] pixels, int colorCount) {
+ assert (pixels.length > 0);
- int next, i, k;
- long weight;
- double[] vv = new double[mMaxColors];
- double temp;
-
- compute3DHistogram(mWt, mMr, mMg, mMb, mM2);
- computeMoments(mWt, mMr, mMg, mMb, mM2);
-
- for (i = 0; i < mMaxColors; i++) {
- cube[i] = new Box();
- }
-
- cube[0].mR0 = cube[0].mG0 = cube[0].mB0 = 0;
- cube[0].mR1 = cube[0].mG1 = cube[0].mB1 = QUANT_SIZE - 1;
- next = 0;
-
- for (i = 1; i < mMaxColors; ++i) {
- if (cut(cube[next], cube[i])) {
- vv[next] = (cube[next].mVol > 1) ? getVariance(cube[next]) : 0.0f;
- vv[i] = (cube[i].mVol > 1) ? getVariance(cube[i]) : 0.0f;
- } else {
- vv[next] = 0.0f;
- i--;
+ QuantizerMap quantizerMap = new QuantizerMap();
+ quantizerMap.quantize(pixels, colorCount);
+ mInputPixelToCount = quantizerMap.getColorToCount();
+ // Extraction should not be run on using a color count higher than the number of colors
+ // in the pixels. The algorithm doesn't expect that to be the case, unexpected results and
+ // exceptions may occur.
+ Set<Integer> uniqueColors = mInputPixelToCount.keySet();
+ if (uniqueColors.size() <= colorCount) {
+ mColors = new int[mInputPixelToCount.keySet().size()];
+ int index = 0;
+ for (int color : uniqueColors) {
+ mColors[index++] = color;
}
- next = 0;
- temp = vv[0];
- for (k = 1; k <= i; ++k) {
- if (vv[k] > temp) {
- temp = vv[k];
- next = k;
- }
- }
- if (temp <= 0.0f) {
- break;
- }
- }
-
- for (k = 0; k < mMaxColors; ++k) {
- weight = getVolume(cube[k], mWt);
- if (weight > 0) {
- red = (int) (getVolume(cube[k], mMr) / weight);
- green = (int) (getVolume(cube[k], mMg) / weight);
- blue = (int) (getVolume(cube[k], mMb) / weight);
- colors[k] = (255 << 24) | (red << 16) | (green << 8) | blue;
- } else {
- colors[k] = 0;
- }
- }
-
- int bitsPerPixel = 0;
- while ((1 << bitsPerPixel) < mMaxColors) {
- bitsPerPixel++;
+ } else {
+ constructHistogram(mInputPixelToCount);
+ createMoments();
+ CreateBoxesResult createBoxesResult = createBoxes(colorCount);
+ mColors = createResult(createBoxesResult.mResultCount);
}
List<Palette.Swatch> swatches = new ArrayList<>();
- for (int l = 0; l < k; l++) {
- int pixel = colors[l];
- if (pixel == 0) {
- continue;
- }
- swatches.add(new Palette.Swatch(pixel, 0));
+ for (int color : mColors) {
+ swatches.add(new Palette.Swatch(color, 0));
}
- mSwatches.clear();
- mSwatches.addAll(swatches);
+ mPalette = Palette.from(swatches);
}
- /* Histogram is in elements 1..HISTSIZE along each axis,
- * element 0 is for base or marginal value
- * NB: these must start out 0!
- */
- private void compute3DHistogram(
- long[][][] vwt, long[][][] vmr, long[][][] vmg, long[][][] vmb, double[][][] m2) {
- // build 3-D color histogram of counts, r/g/b, and c^2
- int r, g, b;
- int i;
- int inr;
- int ing;
- int inb;
- int[] table = new int[256];
+ @Nullable
+ public int[] getColors() {
+ return mColors;
+ }
- for (i = 0; i < 256; i++) {
- table[i] = i * i;
- }
+ /** Keys are color ints, values are the number of pixels in the image matching that color int */
+ @Nullable
+ public Map<Integer, Integer> inputPixelToCount() {
+ return mInputPixelToCount;
+ }
- mQadd = new int[mSize];
+ private static int getIndex(int r, int g, int b) {
+ return (r << 10) + (r << 6) + (g << 5) + r + g + b;
+ }
- for (i = 0; i < mSize; ++i) {
- int rgb = mPixels[i];
- // Skip less than opaque pixels. They're not meaningful in the context of palette
- // generation for UI schemes.
- if ((rgb >>> 24) < 0xff) {
- continue;
- }
- r = ((rgb >> 16) & 0xff);
- g = ((rgb >> 8) & 0xff);
- b = (rgb & 0xff);
- inr = (r >> 3) + 1;
- ing = (g >> 3) + 1;
- inb = (b >> 3) + 1;
- mQadd[i] = (inr << 10) + (inr << 6) + inr + (ing << 5) + ing + inb;
- /*[inr][ing][inb]*/
- ++vwt[inr][ing][inb];
- vmr[inr][ing][inb] += r;
- vmg[inr][ing][inb] += g;
- vmb[inr][ing][inb] += b;
- m2[inr][ing][inb] += table[r] + table[g] + table[b];
+ private void constructHistogram(Map<Integer, Integer> pixels) {
+ mWeights = new int[TOTAL_SIZE];
+ mMomentsR = new int[TOTAL_SIZE];
+ mMomentsG = new int[TOTAL_SIZE];
+ mMomentsB = new int[TOTAL_SIZE];
+ mMoments = new double[TOTAL_SIZE];
+
+ for (Map.Entry<Integer, Integer> pair : pixels.entrySet()) {
+ int pixel = pair.getKey();
+ int count = pair.getValue();
+ int red = Color.red(pixel);
+ int green = Color.green(pixel);
+ int blue = Color.blue(pixel);
+ int bitsToRemove = 8 - BITS;
+ int iR = (red >> bitsToRemove) + 1;
+ int iG = (green >> bitsToRemove) + 1;
+ int iB = (blue >> bitsToRemove) + 1;
+ int index = getIndex(iR, iG, iB);
+ mWeights[index] += count;
+ mMomentsR[index] += (red * count);
+ mMomentsG[index] += (green * count);
+ mMomentsB[index] += (blue * count);
+ mMoments[index] += (count * ((red * red) + (green * green) + (blue * blue)));
}
}
- /* At conclusion of the histogram step, we can interpret
- * wt[r][g][b] = sum over voxel of P(c)
- * mr[r][g][b] = sum over voxel of r*P(c) , similarly for mg, mb
- * m2[r][g][b] = sum over voxel of c^2*P(c)
- * Actually each of these should be divided by 'size' to give the usual
- * interpretation of P() as ranging from 0 to 1, but we needn't do that here.
- *
- * We now convert histogram into moments so that we can rapidly calculate
- * the sums of the above quantities over any desired box.
- */
- private void computeMoments(
- long[][][] vwt, long[][][] vmr, long[][][] vmg, long[][][] vmb, double[][][] m2) {
- /* compute cumulative moments. */
- int i, r, g, b;
- int line, line_r, line_g, line_b;
- int[] area = new int[QUANT_SIZE];
- int[] area_r = new int[QUANT_SIZE];
- int[] area_g = new int[QUANT_SIZE];
- int[] area_b = new int[QUANT_SIZE];
- double line2;
- double[] area2 = new double[QUANT_SIZE];
+ private void createMoments() {
+ for (int r = 1; r < SIDE_LENGTH; ++r) {
+ int[] area = new int[SIDE_LENGTH];
+ int[] areaR = new int[SIDE_LENGTH];
+ int[] areaG = new int[SIDE_LENGTH];
+ int[] areaB = new int[SIDE_LENGTH];
+ double[] area2 = new double[SIDE_LENGTH];
- for (r = 1; r < QUANT_SIZE; ++r) {
- for (i = 0; i < QUANT_SIZE; ++i) {
- area2[i] = area[i] = area_r[i] = area_g[i] = area_b[i] = 0;
- }
- for (g = 1; g < QUANT_SIZE; ++g) {
- line2 = line = line_r = line_g = line_b = 0;
- for (b = 1; b < QUANT_SIZE; ++b) {
- line += vwt[r][g][b];
- line_r += vmr[r][g][b];
- line_g += vmg[r][g][b];
- line_b += vmb[r][g][b];
- line2 += m2[r][g][b];
+ for (int g = 1; g < SIDE_LENGTH; ++g) {
+ int line = 0;
+ int lineR = 0;
+ int lineG = 0;
+ int lineB = 0;
+
+ double line2 = 0.0;
+ for (int b = 1; b < SIDE_LENGTH; ++b) {
+ int index = getIndex(r, g, b);
+ line += mWeights[index];
+ lineR += mMomentsR[index];
+ lineG += mMomentsG[index];
+ lineB += mMomentsB[index];
+ line2 += mMoments[index];
area[b] += line;
- area_r[b] += line_r;
- area_g[b] += line_g;
- area_b[b] += line_b;
+ areaR[b] += lineR;
+ areaG[b] += lineG;
+ areaB[b] += lineB;
area2[b] += line2;
- vwt[r][g][b] = vwt[r - 1][g][b] + area[b];
- vmr[r][g][b] = vmr[r - 1][g][b] + area_r[b];
- vmg[r][g][b] = vmg[r - 1][g][b] + area_g[b];
- vmb[r][g][b] = vmb[r - 1][g][b] + area_b[b];
- m2[r][g][b] = m2[r - 1][g][b] + area2[b];
+ int previousIndex = getIndex(r - 1, g, b);
+ mWeights[index] = mWeights[previousIndex] + area[b];
+ mMomentsR[index] = mMomentsR[previousIndex] + areaR[b];
+ mMomentsG[index] = mMomentsG[previousIndex] + areaG[b];
+ mMomentsB[index] = mMomentsB[previousIndex] + areaB[b];
+ mMoments[index] = mMoments[previousIndex] + area2[b];
}
}
}
}
- private long getVolume(Box cube, long[][][] mmt) {
- /* Compute sum over a box of any given statistic */
- return (mmt[cube.mR1][cube.mG1][cube.mB1]
- - mmt[cube.mR1][cube.mG1][cube.mB0]
- - mmt[cube.mR1][cube.mG0][cube.mB1]
- + mmt[cube.mR1][cube.mG0][cube.mB0]
- - mmt[cube.mR0][cube.mG1][cube.mB1]
- + mmt[cube.mR0][cube.mG1][cube.mB0]
- + mmt[cube.mR0][cube.mG0][cube.mB1]
- - mmt[cube.mR0][cube.mG0][cube.mB0]);
- }
-
- /* The next two routines allow a slightly more efficient calculation
- * of Vol() for a proposed subbox of a given box. The sum of Top()
- * and Bottom() is the Vol() of a subbox split in the given direction
- * and with the specified new upper bound.
- */
- private long getBottom(Box cube, int dir, long[][][] mmt) {
- /* Compute part of Vol(cube, mmt) that doesn't depend on r1, g1, or b1 */
- /* (depending on dir) */
- switch (dir) {
- case RED:
- return (-mmt[cube.mR0][cube.mG1][cube.mB1]
- + mmt[cube.mR0][cube.mG1][cube.mB0]
- + mmt[cube.mR0][cube.mG0][cube.mB1]
- - mmt[cube.mR0][cube.mG0][cube.mB0]);
- case GREEN:
- return (-mmt[cube.mR1][cube.mG0][cube.mB1]
- + mmt[cube.mR1][cube.mG0][cube.mB0]
- + mmt[cube.mR0][cube.mG0][cube.mB1]
- - mmt[cube.mR0][cube.mG0][cube.mB0]);
- case BLUE:
- return (-mmt[cube.mR1][cube.mG1][cube.mB0]
- + mmt[cube.mR1][cube.mG0][cube.mB0]
- + mmt[cube.mR0][cube.mG1][cube.mB0]
- - mmt[cube.mR0][cube.mG0][cube.mB0]);
- default:
- return 0;
+ private CreateBoxesResult createBoxes(int maxColorCount) {
+ mCubes = new Box[maxColorCount];
+ for (int i = 0; i < maxColorCount; i++) {
+ mCubes[i] = new Box();
}
- }
+ double[] volumeVariance = new double[maxColorCount];
+ Box firstBox = mCubes[0];
+ firstBox.r1 = MAX_INDEX;
+ firstBox.g1 = MAX_INDEX;
+ firstBox.b1 = MAX_INDEX;
- private long getTop(Box cube, int dir, int pos, long[][][] mmt) {
- /* Compute remainder of Vol(cube, mmt), substituting pos for */
- /* r1, g1, or b1 (depending on dir) */
- switch (dir) {
- case RED:
- return (mmt[pos][cube.mG1][cube.mB1]
- - mmt[pos][cube.mG1][cube.mB0]
- - mmt[pos][cube.mG0][cube.mB1]
- + mmt[pos][cube.mG0][cube.mB0]);
- case GREEN:
- return (mmt[cube.mR1][pos][cube.mB1]
- - mmt[cube.mR1][pos][cube.mB0]
- - mmt[cube.mR0][pos][cube.mB1]
- + mmt[cube.mR0][pos][cube.mB0]);
- case BLUE:
- return (mmt[cube.mR1][cube.mG1][pos]
- - mmt[cube.mR1][cube.mG0][pos]
- - mmt[cube.mR0][cube.mG1][pos]
- + mmt[cube.mR0][cube.mG0][pos]);
- default:
- return 0;
- }
- }
+ int generatedColorCount = 0;
+ int next = 0;
- private double getVariance(Box cube) {
- /* Compute the weighted variance of a box */
- /* NB: as with the raw statistics, this is really the variance * size */
- double dr, dg, db, xx;
- dr = getVolume(cube, mMr);
- dg = getVolume(cube, mMg);
- db = getVolume(cube, mMb);
- xx =
- mM2[cube.mR1][cube.mG1][cube.mB1]
- - mM2[cube.mR1][cube.mG1][cube.mB0]
- - mM2[cube.mR1][cube.mG0][cube.mB1]
- + mM2[cube.mR1][cube.mG0][cube.mB0]
- - mM2[cube.mR0][cube.mG1][cube.mB1]
- + mM2[cube.mR0][cube.mG1][cube.mB0]
- + mM2[cube.mR0][cube.mG0][cube.mB1]
- - mM2[cube.mR0][cube.mG0][cube.mB0];
- return xx - (dr * dr + dg * dg + db * db) / getVolume(cube, mWt);
- }
-
- /* We want to minimize the sum of the variances of two subboxes.
- * The sum(c^2) terms can be ignored since their sum over both subboxes
- * is the same (the sum for the whole box) no matter where we split.
- * The remaining terms have a minus sign in the variance formula,
- * so we drop the minus sign and MAXIMIZE the sum of the two terms.
- */
- private double maximize(
- Box cube,
- int dir,
- int first,
- int last,
- int[] cut,
- long wholeR,
- long wholeG,
- long wholeB,
- long wholeW) {
- long half_r, half_g, half_b, half_w;
- long base_r, base_g, base_b, base_w;
- int i;
- double temp, max;
-
- base_r = getBottom(cube, dir, mMr);
- base_g = getBottom(cube, dir, mMg);
- base_b = getBottom(cube, dir, mMb);
- base_w = getBottom(cube, dir, mWt);
-
- max = 0.0f;
- cut[0] = -1;
-
- for (i = first; i < last; ++i) {
- half_r = base_r + getTop(cube, dir, i, mMr);
- half_g = base_g + getTop(cube, dir, i, mMg);
- half_b = base_b + getTop(cube, dir, i, mMb);
- half_w = base_w + getTop(cube, dir, i, mWt);
- /* now half_x is sum over lower half of box, if split at i */
- if (half_w == 0) /* subbox could be empty of pixels! */ {
- continue; /* never split into an empty box */
+ for (int i = 1; i < maxColorCount; i++) {
+ if (cut(mCubes[next], mCubes[i])) {
+ volumeVariance[next] = (mCubes[next].vol > 1) ? variance(mCubes[next]) : 0.0;
+ volumeVariance[i] = (mCubes[i].vol > 1) ? variance(mCubes[i]) : 0.0;
+ } else {
+ volumeVariance[next] = 0.0;
+ i--;
}
- temp = (half_r * half_r + half_g * half_g + half_b * half_b) / (double) half_w;
- half_r = wholeR - half_r;
- half_g = wholeG - half_g;
- half_b = wholeB - half_b;
- half_w = wholeW - half_w;
- if (half_w == 0) /* subbox could be empty of pixels! */ {
- continue; /* never split into an empty box */
- }
- temp += (half_r * half_r + half_g * half_g + half_b * half_b) / (double) half_w;
- if (temp > max) {
- max = temp;
- cut[0] = i;
+ next = 0;
+
+ double temp = volumeVariance[0];
+ for (int k = 1; k <= i; k++) {
+ if (volumeVariance[k] > temp) {
+ temp = volumeVariance[k];
+ next = k;
+ }
+ }
+ generatedColorCount = i + 1;
+ if (temp <= 0.0) {
+ break;
}
}
- return max;
+ return new CreateBoxesResult(maxColorCount, generatedColorCount);
}
- private boolean cut(Box set1, Box set2) {
- int dir;
- int[] cutr = new int[1];
- int[] cutg = new int[1];
- int[] cutb = new int[1];
- double maxr, maxg, maxb;
- long whole_r, whole_g, whole_b, whole_w;
+ private int[] createResult(int colorCount) {
+ int[] colors = new int[colorCount];
+ int nextAvailableIndex = 0;
+ for (int i = 0; i < colorCount; ++i) {
+ Box cube = mCubes[i];
+ int weight = volume(cube, mWeights);
+ if (weight > 0) {
+ int r = (volume(cube, mMomentsR) / weight);
+ int g = (volume(cube, mMomentsG) / weight);
+ int b = (volume(cube, mMomentsB) / weight);
+ int color = Color.rgb(r, g, b);
+ colors[nextAvailableIndex++] = color;
+ }
+ }
+ int[] resultArray = new int[nextAvailableIndex];
+ arraycopy(colors, 0, resultArray, 0, nextAvailableIndex);
+ return resultArray;
+ }
- whole_r = getVolume(set1, mMr);
- whole_g = getVolume(set1, mMg);
- whole_b = getVolume(set1, mMb);
- whole_w = getVolume(set1, mWt);
+ private double variance(Box cube) {
+ int dr = volume(cube, mMomentsR);
+ int dg = volume(cube, mMomentsG);
+ int db = volume(cube, mMomentsB);
+ double xx =
+ mMoments[getIndex(cube.r1, cube.g1, cube.b1)]
+ - mMoments[getIndex(cube.r1, cube.g1, cube.b0)]
+ - mMoments[getIndex(cube.r1, cube.g0, cube.b1)]
+ + mMoments[getIndex(cube.r1, cube.g0, cube.b0)]
+ - mMoments[getIndex(cube.r0, cube.g1, cube.b1)]
+ + mMoments[getIndex(cube.r0, cube.g1, cube.b0)]
+ + mMoments[getIndex(cube.r0, cube.g0, cube.b1)]
+ - mMoments[getIndex(cube.r0, cube.g0, cube.b0)];
- maxr = maximize(set1, RED, set1.mR0 + 1, set1.mR1, cutr, whole_r, whole_g, whole_b,
- whole_w);
- maxg = maximize(set1, GREEN, set1.mG0 + 1, set1.mG1, cutg, whole_r, whole_g, whole_b,
- whole_w);
- maxb = maximize(set1, BLUE, set1.mB0 + 1, set1.mB1, cutb, whole_r, whole_g, whole_b,
- whole_w);
+ int hypotenuse = (dr * dr + dg * dg + db * db);
+ int volume2 = volume(cube, mWeights);
+ double variance2 = xx - ((double) hypotenuse / (double) volume2);
+ return variance2;
+ }
- if (maxr >= maxg && maxr >= maxb) {
- dir = RED;
- if (cutr[0] < 0) return false; /* can't split the box */
- } else if (maxg >= maxr && maxg >= maxb) {
- dir = GREEN;
+ private boolean cut(Box one, Box two) {
+ int wholeR = volume(one, mMomentsR);
+ int wholeG = volume(one, mMomentsG);
+ int wholeB = volume(one, mMomentsB);
+ int wholeW = volume(one, mWeights);
+
+ MaximizeResult maxRResult =
+ maximize(one, Direction.RED, one.r0 + 1, one.r1, wholeR, wholeG, wholeB, wholeW);
+ MaximizeResult maxGResult =
+ maximize(one, Direction.GREEN, one.g0 + 1, one.g1, wholeR, wholeG, wholeB, wholeW);
+ MaximizeResult maxBResult =
+ maximize(one, Direction.BLUE, one.b0 + 1, one.b1, wholeR, wholeG, wholeB, wholeW);
+ Direction cutDirection;
+ double maxR = maxRResult.mMaximum;
+ double maxG = maxGResult.mMaximum;
+ double maxB = maxBResult.mMaximum;
+ if (maxR >= maxG && maxR >= maxB) {
+ if (maxRResult.mCutLocation < 0) {
+ return false;
+ }
+ cutDirection = Direction.RED;
+ } else if (maxG >= maxR && maxG >= maxB) {
+ cutDirection = Direction.GREEN;
} else {
- dir = BLUE;
+ cutDirection = Direction.BLUE;
}
- set2.mR1 = set1.mR1;
- set2.mG1 = set1.mG1;
- set2.mB1 = set1.mB1;
+ two.r1 = one.r1;
+ two.g1 = one.g1;
+ two.b1 = one.b1;
- switch (dir) {
+ switch (cutDirection) {
case RED:
- set2.mR0 = set1.mR1 = cutr[0];
- set2.mG0 = set1.mG0;
- set2.mB0 = set1.mB0;
+ one.r1 = maxRResult.mCutLocation;
+ two.r0 = one.r1;
+ two.g0 = one.g0;
+ two.b0 = one.b0;
break;
case GREEN:
- set2.mG0 = set1.mG1 = cutg[0];
- set2.mR0 = set1.mR0;
- set2.mB0 = set1.mB0;
+ one.g1 = maxGResult.mCutLocation;
+ two.r0 = one.r0;
+ two.g0 = one.g1;
+ two.b0 = one.b0;
break;
case BLUE:
- set2.mB0 = set1.mB1 = cutb[0];
- set2.mR0 = set1.mR0;
- set2.mG0 = set1.mG0;
+ one.b1 = maxBResult.mCutLocation;
+ two.r0 = one.r0;
+ two.g0 = one.g0;
+ two.b0 = one.b1;
break;
+ default:
+ throw new IllegalArgumentException("unexpected direction " + cutDirection);
}
- set1.mVol = (set1.mR1 - set1.mR0) * (set1.mG1 - set1.mG0) * (set1.mB1 - set1.mB0);
- set2.mVol = (set2.mR1 - set2.mR0) * (set2.mG1 - set2.mG0) * (set2.mB1 - set2.mB0);
+
+ one.vol = (one.r1 - one.r0) * (one.g1 - one.g0) * (one.b1 - one.b0);
+ two.vol = (two.r1 - two.r0) * (two.g1 - two.g0) * (two.b1 - two.b0);
return true;
}
+
+ private MaximizeResult maximize(
+ Box cube,
+ Direction direction,
+ int first,
+ int last,
+ int wholeR,
+ int wholeG,
+ int wholeB,
+ int wholeW) {
+ int baseR = bottom(cube, direction, mMomentsR);
+ int baseG = bottom(cube, direction, mMomentsG);
+ int baseB = bottom(cube, direction, mMomentsB);
+ int baseW = bottom(cube, direction, mWeights);
+
+ double max = 0.0;
+ int cut = -1;
+ for (int i = first; i < last; i++) {
+ int halfR = baseR + top(cube, direction, i, mMomentsR);
+ int halfG = baseG + top(cube, direction, i, mMomentsG);
+ int halfB = baseB + top(cube, direction, i, mMomentsB);
+ int halfW = baseW + top(cube, direction, i, mWeights);
+
+ if (halfW == 0) {
+ continue;
+ }
+ double tempNumerator = halfR * halfR + halfG * halfG + halfB * halfB;
+ double tempDenominator = halfW;
+ double temp = tempNumerator / tempDenominator;
+
+ halfR = wholeR - halfR;
+ halfG = wholeG - halfG;
+ halfB = wholeB - halfB;
+ halfW = wholeW - halfW;
+ if (halfW == 0) {
+ continue;
+ }
+
+ tempNumerator = halfR * halfR + halfG * halfG + halfB * halfB;
+ tempDenominator = halfW;
+ temp += (tempNumerator / tempDenominator);
+ if (temp > max) {
+ max = temp;
+ cut = i;
+ }
+ }
+ return new MaximizeResult(cut, max);
+ }
+
+ private static int volume(Box cube, int[] moment) {
+ return (moment[getIndex(cube.r1, cube.g1, cube.b1)]
+ - moment[getIndex(cube.r1, cube.g1, cube.b0)]
+ - moment[getIndex(cube.r1, cube.g0, cube.b1)]
+ + moment[getIndex(cube.r1, cube.g0, cube.b0)]
+ - moment[getIndex(cube.r0, cube.g1, cube.b1)]
+ + moment[getIndex(cube.r0, cube.g1, cube.b0)]
+ + moment[getIndex(cube.r0, cube.g0, cube.b1)]
+ - moment[getIndex(cube.r0, cube.g0, cube.b0)]);
+ }
+
+ private static int bottom(Box cube, Direction direction, int[] moment) {
+ switch (direction) {
+ case RED:
+ return -moment[getIndex(cube.r0, cube.g1, cube.b1)]
+ + moment[getIndex(cube.r0, cube.g1, cube.b0)]
+ + moment[getIndex(cube.r0, cube.g0, cube.b1)]
+ - moment[getIndex(cube.r0, cube.g0, cube.b0)];
+ case GREEN:
+ return -moment[getIndex(cube.r1, cube.g0, cube.b1)]
+ + moment[getIndex(cube.r1, cube.g0, cube.b0)]
+ + moment[getIndex(cube.r0, cube.g0, cube.b1)]
+ - moment[getIndex(cube.r0, cube.g0, cube.b0)];
+ case BLUE:
+ return -moment[getIndex(cube.r1, cube.g1, cube.b0)]
+ + moment[getIndex(cube.r1, cube.g0, cube.b0)]
+ + moment[getIndex(cube.r0, cube.g1, cube.b0)]
+ - moment[getIndex(cube.r0, cube.g0, cube.b0)];
+ default:
+ throw new IllegalArgumentException("unexpected direction " + direction);
+ }
+ }
+
+ private static int top(Box cube, Direction direction, int position, int[] moment) {
+ switch (direction) {
+ case RED:
+ return (moment[getIndex(position, cube.g1, cube.b1)]
+ - moment[getIndex(position, cube.g1, cube.b0)]
+ - moment[getIndex(position, cube.g0, cube.b1)]
+ + moment[getIndex(position, cube.g0, cube.b0)]);
+ case GREEN:
+ return (moment[getIndex(cube.r1, position, cube.b1)]
+ - moment[getIndex(cube.r1, position, cube.b0)]
+ - moment[getIndex(cube.r0, position, cube.b1)]
+ + moment[getIndex(cube.r0, position, cube.b0)]);
+ case BLUE:
+ return (moment[getIndex(cube.r1, cube.g1, position)]
+ - moment[getIndex(cube.r1, cube.g0, position)]
+ - moment[getIndex(cube.r0, cube.g1, position)]
+ + moment[getIndex(cube.r0, cube.g0, position)]);
+ default:
+ throw new IllegalArgumentException("unexpected direction " + direction);
+ }
+ }
+
+ private enum Direction {
+ RED,
+ GREEN,
+ BLUE
+ }
+
+ private static class MaximizeResult {
+ // < 0 if cut impossible
+ final int mCutLocation;
+ final double mMaximum;
+
+ MaximizeResult(int cut, double max) {
+ mCutLocation = cut;
+ mMaximum = max;
+ }
+ }
+
+ private static class CreateBoxesResult {
+ final int mRequestedCount;
+ final int mResultCount;
+
+ CreateBoxesResult(int requestedCount, int resultCount) {
+ mRequestedCount = requestedCount;
+ mResultCount = resultCount;
+ }
+ }
+
+ private static class Box {
+ public int r0 = 0;
+ public int r1 = 0;
+ public int g0 = 0;
+ public int g1 = 0;
+ public int b0 = 0;
+ public int b1 = 0;
+ public int vol = 0;
+ }
}
+
+
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 28b325b..26d6a0c 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -78,6 +78,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Locale;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -713,7 +714,8 @@
}
public String getPerfettoTrigger() {
- return String.format("com.android.telemetry.interaction-jank-monitor-%d", mCujType);
+ return String.format(Locale.US, "com.android.telemetry.interaction-jank-monitor-%d",
+ mCujType);
}
public String getName() {
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 47341cd..f212fc7 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -66,12 +66,12 @@
}
@Override
- public void insetsChanged(InsetsState insetsState) {
+ public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) {
}
@Override
public void insetsControlChanged(InsetsState insetsState,
- InsetsSourceControl[] activeControls) {
+ InsetsSourceControl[] activeControls, boolean willMove, boolean willResize) {
}
@Override
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 9986834..68388d98 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -232,6 +232,7 @@
"libseccomp_policy",
"libgrallocusage",
"libscrypt_static",
+ "libstatssocket_lazy",
],
shared_libs: [
@@ -295,11 +296,8 @@
"libnativewindow",
"libdl",
"libdl_android",
- "libstatslog",
- "libstatssocket",
"libtimeinstate",
"server_configurable_flags",
- "libstatspull",
],
export_shared_lib_headers: [
// our headers include libnativewindow's public headers
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 8f26d35..3debb3e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -639,6 +639,8 @@
char saveResolvedClassesDelayMsOptsBuf[
sizeof("-Xps-save-resolved-classes-delay-ms:")-1 + PROPERTY_VALUE_MAX];
char profileMinSavePeriodOptsBuf[sizeof("-Xps-min-save-period-ms:")-1 + PROPERTY_VALUE_MAX];
+ char profileMinFirstSaveOptsBuf[
+ sizeof("-Xps-min-first-save-ms:")-1 + PROPERTY_VALUE_MAX];
char madviseRandomOptsBuf[sizeof("-XX:MadviseRandomAccess:")-1 + PROPERTY_VALUE_MAX];
char madviseWillNeedFileSizeVdex[
sizeof("-XMadviseWillNeedVdexFileSize:")-1 + PROPERTY_VALUE_MAX];
@@ -877,6 +879,9 @@
parseRuntimeOption("dalvik.vm.ps-min-save-period-ms", profileMinSavePeriodOptsBuf,
"-Xps-min-save-period-ms:");
+ parseRuntimeOption("dalvik.vm.ps-min-first-save-ms", profileMinFirstSaveOptsBuf,
+ "-Xps-min-first-save-ms:");
+
property_get("ro.config.low_ram", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
addOption("-XX:LowMemoryMode");
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index f2ac87e..666ab95 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -65,6 +65,7 @@
# These are highly common-use files
per-file Android.bp = file:/graphics/java/android/graphics/OWNERS
per-file AndroidRuntime.cpp = file:/graphics/java/android/graphics/OWNERS
+per-file AndroidRuntime.cpp = calin@google.com, ngeoffray@google.com, oth@google.com
# Although marked "view" this is mostly graphics stuff
per-file android_view_* = file:/graphics/java/android/graphics/OWNERS
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 56814c7..6e2b9cf 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -42,6 +42,7 @@
#include "android_media_AudioFormat.h"
#include "android_media_AudioProfile.h"
#include "android_media_MicrophoneInfo.h"
+#include "android_util_Binder.h"
// ----------------------------------------------------------------------------
@@ -850,6 +851,11 @@
return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
}
+static void android_media_AudioSystem_setAudioFlingerBinder(JNIEnv *env, jobject clazz,
+ jobject audioFlinger) {
+ AudioSystem::setAudioFlingerBinder(android::ibinderForJavaObject(env, audioFlinger));
+}
+
static void convertAudioGainConfigToNative(JNIEnv *env,
struct audio_gain_config *nAudioGainConfig,
const jobject jAudioGainConfig,
@@ -2383,7 +2389,7 @@
}
static jint android_media_AudioSystem_getMaxChannelCount(JNIEnv *env, jobject thiz) {
- return FCC_8;
+ return FCC_LIMIT;
}
static jint android_media_AudioSystem_getMaxSampleRate(JNIEnv *env, jobject thiz) {
@@ -2728,6 +2734,8 @@
{"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
{"setLowRamDevice", "(ZJ)I", (void *)android_media_AudioSystem_setLowRamDevice},
{"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
+ {"setAudioFlingerBinder", "(Landroid/os/IBinder;)V",
+ (void *)android_media_AudioSystem_setAudioFlingerBinder},
{"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
(void *)android_media_AudioSystem_listAudioPorts},
{"createAudioPatch",
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index ce847e8..e93b00d 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1244,10 +1244,14 @@
return reinterpret_cast<jlong>(assetmanager->NewTheme().release());
}
-static void NativeThemeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong theme_ptr) {
+static void NativeThemeDestroy(jlong theme_ptr) {
delete reinterpret_cast<Theme*>(theme_ptr);
}
+static jlong NativeGetThemeFreeFunction(JNIEnv* /*env*/, jclass /*clazz*/) {
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(&NativeThemeDestroy));
+}
+
static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
jint resid, jboolean force) {
// AssetManager is accessed via the theme, so grab an explicit lock here.
@@ -1264,6 +1268,46 @@
// jniThrowException(env, "java/lang/IllegalArgumentException", error_msg.c_str());
}
+static void NativeThemeRebase(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
+ jintArray style_ids, jbooleanArray force,
+ jint style_count) {
+ // Lock both the original asset manager of the theme and the new asset manager to be used for the
+ // theme.
+ ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+
+ uint32_t* style_id_args = nullptr;
+ if (style_ids != nullptr) {
+ CHECK(style_count <= env->GetArrayLength(style_ids));
+ style_id_args = reinterpret_cast<uint32_t*>(env->GetPrimitiveArrayCritical(style_ids, nullptr));
+ if (style_id_args == nullptr) {
+ return;
+ }
+ } else {
+ CHECK(style_count == 0) << "style_ids is null while style_count is non-zero";
+ }
+
+ jboolean* force_args = nullptr;
+ if (force != nullptr) {
+ CHECK(style_count <= env->GetArrayLength(force));
+ force_args = reinterpret_cast<jboolean*>(env->GetPrimitiveArrayCritical(force, nullptr));
+ if (force_args == nullptr) {
+ env->ReleasePrimitiveArrayCritical(style_ids, style_id_args, JNI_ABORT);
+ return;
+ }
+ } else {
+ CHECK(style_count == 0) << "force is null while style_count is non-zero";
+ }
+
+ auto theme = reinterpret_cast<Theme*>(theme_ptr);
+ theme->Rebase(&(*assetmanager), style_id_args, force_args, static_cast<size_t>(style_count));
+ if (style_ids != nullptr) {
+ env->ReleasePrimitiveArrayCritical(style_ids, style_id_args, JNI_ABORT);
+ }
+ if (force != nullptr) {
+ env->ReleasePrimitiveArrayCritical(force, force_args, JNI_ABORT);
+ }
+}
+
static void NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_asset_manager_ptr,
jlong dst_theme_ptr, jlong src_asset_manager_ptr, jlong src_theme_ptr) {
Theme* dst_theme = reinterpret_cast<Theme*>(dst_theme_ptr);
@@ -1284,10 +1328,6 @@
}
}
-static void NativeThemeClear(JNIEnv* /*env*/, jclass /*clazz*/, jlong theme_ptr) {
- reinterpret_cast<Theme*>(theme_ptr)->Clear();
-}
-
static jint NativeThemeGetAttributeValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
jint resid, jobject typed_value,
jboolean resolve_references) {
@@ -1446,10 +1486,11 @@
// Theme related methods.
{"nativeThemeCreate", "(J)J", (void*)NativeThemeCreate},
- {"nativeThemeDestroy", "(J)V", (void*)NativeThemeDestroy},
+ {"nativeGetThemeFreeFunction", "()J", (void*)NativeGetThemeFreeFunction},
{"nativeThemeApplyStyle", "(JJIZ)V", (void*)NativeThemeApplyStyle},
+ {"nativeThemeRebase", "(JJ[I[ZI)V", (void*)NativeThemeRebase},
+
{"nativeThemeCopy", "(JJJJ)V", (void*)NativeThemeCopy},
- {"nativeThemeClear", "(J)V", (void*)NativeThemeClear},
{"nativeThemeGetAttributeValue", "(JJILandroid/util/TypedValue;Z)I",
(void*)NativeThemeGetAttributeValue},
{"nativeThemeDump", "(JJILjava/lang/String;Ljava/lang/String;)V", (void*)NativeThemeDump},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6b6cbea..64b8a1a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -693,8 +693,8 @@
<!-- Added in S -->
<protected-broadcast android:name="android.scheduling.action.REBOOT_READY" />
<protected-broadcast android:name="android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED" />
-
<protected-broadcast android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
@@ -1408,13 +1408,13 @@
<!-- @SystemApi Required in addition to android.permission.CAMERA to be able to access
system only camera devices.
- <p>Protection level: system|signature
+ <p>Protection level: system|signature|role
@hide -->
<permission android:name="android.permission.SYSTEM_CAMERA"
android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_systemCamera"
android:description="@string/permdesc_systemCamera"
- android:protectionLevel="system|signature" />
+ android:protectionLevel="system|signature|role" />
<!-- @SystemApi Allows receiving the camera service notifications when a camera is opened
(by a certain application package) or closed.
@@ -4053,8 +4053,13 @@
<permission android:name="android.permission.SCHEDULE_PRIORITIZED_ALARM"
android:protectionLevel="signature|privileged"/>
- <!-- Allows an app to use exact alarm scheduling APIs to perform timing
- sensitive background work.
+ <!-- Allows applications to use exact alarm APIs.
+ <p>Exact alarms should only be used for user-facing features.
+ For more details, see <a
+ href="{@docRoot}about/versions/12/behavior-changes-12#exact-alarm-permission">
+ Exact alarm permission</a>.
+ Applications targeting API level 30 or below do not need this permission to use
+ exact alarm APIs.
-->
<permission android:name="android.permission.SCHEDULE_EXACT_ALARM"
android:protectionLevel="normal|appop"/>
@@ -5658,6 +5663,8 @@
<!-- Allows query of any normal app on the device, regardless of manifest declarations.
<p>Protection level: normal -->
<permission android:name="android.permission.QUERY_ALL_PACKAGES"
+ android:label="@string/permlab_queryAllPackages"
+ android:description="@string/permdesc_queryAllPackages"
android:protectionLevel="normal" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
diff --git a/core/res/res/drawable-car/car_checkbox.xml b/core/res/res/drawable-car/car_checkbox.xml
index 651e678..083a7aa 100644
--- a/core/res/res/drawable-car/car_checkbox.xml
+++ b/core/res/res/drawable-car/car_checkbox.xml
@@ -20,4 +20,8 @@
android:width="@*android:dimen/car_primary_icon_size"
android:height="@*android:dimen/car_primary_icon_size"
android:drawable="@drawable/btn_check_material_anim"/>
+ <item
+ android:width="@*android:dimen/car_primary_icon_size"
+ android:height="@*android:dimen/car_primary_icon_size"
+ android:drawable="@drawable/car_checkbox_background"/>
</layer-list>
diff --git a/core/res/res/drawable-car/car_checkbox_background.xml b/core/res/res/drawable-car/car_checkbox_background.xml
new file mode 100644
index 0000000..69dcdbb
--- /dev/null
+++ b/core/res/res/drawable-car/car_checkbox_background.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:state_pressed="true">
+ <shape android:shape="rectangle">
+ <solid android:color="#8A0041BE" />
+ <stroke android:width="4dp" android:color="#0041BE" />
+ </shape>
+ </item>
+ <item android:state_focused="true">
+ <shape android:shape="rectangle">
+ <solid android:color="#3D0059B3" />
+ <stroke android:width="8dp" android:color="#0059B3" />
+ </shape>
+ </item>
+</selector>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 215ec91..85de02e 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Opgedateer deur jou administrateur"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Uitgevee deur jou administrateur"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Batterybespaarder skakel Donkertema aan en beperk of skakel agtergrondaktiwiteit, sommige visuele effekte, sekere kenmerke en sommige netwerkverbindings af"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Batterybespaarder skakel Donkertema aan en beperk of skakel agtergrondaktiwiteit, sommige visuele effekte, sekere kenmerke en sommige netwerkverbindings af"</string>
<string name="data_saver_description" msgid="4995164271550590517">"Databespaarder verhoed sommige programme om data in die agtergrond te stuur of te aanvaar om datagebruik te help verminder. \'n Program wat jy tans gebruik kan by data ingaan, maar sal dit dalk minder gereeld doen. Dit kan byvoorbeeld beteken dat prente nie wys voordat jy op hulle tik nie."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Skakel Databespaarder aan?"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index dff40b6..18cc4c6 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"በእርስዎ አስተዳዳሪ ተዘምኗል"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"በእርስዎ አስተዳዳሪ ተሰርዟል"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"እሺ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ባትሪ ቆጣቢ ጠቆር ያለ ገጽታን ያበራል እና የጀርባ እንቅስቃሴን፣ አንዳንድ ዕይታዊ ውጤቶችን፣ አንዳንድ ባህሪዎችን፣ እና አንዳንድ የአውታረ መረብ ግንኙነቶችን ይገድባል ወይም ያጠፋል።"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"ባትሪ ቆጣቢ ጠቆር ያለ ገጽታን ያበራል እና የጀርባ እንቅስቃሴን፣ አንዳንድ ዕይታዊ ውጤቶችን፣ አንዳንድ ባህሪዎችን፣ እና አንዳንድ የአውታረ መረብ ግንኙነቶችን ይገድባል ወይም ያጠፋል።"</string>
<string name="data_saver_description" msgid="4995164271550590517">"የውሂብ አጠቃቀም እንዲቀንስ ለማገዝ ውሂብ ቆጣቢ አንዳንድ መተግበሪያዎች ከበስተጀርባ ሆነው ውሂብ እንዳይልኩ ወይም እንዳይቀበሉ ይከለክላቸዋል። በአሁኑ ጊዜ እየተጠቀሙበት ያለ መተግበሪያ ውሂብ ሊደርስ ይችላል፣ ነገር ግን ባነሰ ተደጋጋሚነት ሊሆን ይችላል። ይሄ ማለት ለምሳሌ ምስሎችን መታ እስኪያደርጓቸው ድረስ ላይታዩ ይችላሉ ማለት ነው።"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ውሂብ ቆጣቢ ይጥፋ?"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index c88218d..1d7ce15 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1538,6 +1538,10 @@
<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="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>
@@ -1958,11 +1962,10 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"تم التحديث بواسطة المشرف"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"تم الحذف بواسطة المشرف"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"حسنًا"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"يؤدي استخدام ميزة \"توفير شحن البطارية\" إلى تفعيل وضع \"المظهر الداكن\" وتقييد أو إيقاف الأنشطة في الخلفية وبعض التأثيرات المرئية وميزات معيّنة وبعض اتصالات الشبكات."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"يؤدي استخدام ميزة \"توفير شحن البطارية\" إلى تفعيل وضع \"المظهر الداكن\" وتقييد أو إيقاف الأنشطة في الخلفية وبعض التأثيرات المرئية وميزات معيّنة وبعض اتصالات الشبكات."</string>
<string name="data_saver_description" msgid="4995164271550590517">"للمساعدة في خفض استخدام البيانات، تمنع ميزة \"توفير البيانات\" بعض التطبيقات من إرسال البيانات وتلقّيها في الخلفية. يمكن للتطبيقات المتاحة لديك الآن استخدام البيانات، ولكن لا يمكنها الإكثار من ذلك. وهذا يعني أن الصور مثلاً لا تظهر حتى تنقر عليها."</string>
- <string name="data_saver_enable_title" msgid="7080620065745260137">"هل تريد تفعيل توفير البيانات؟"</string>
+ <string name="data_saver_enable_title" msgid="7080620065745260137">"هل تريد تفعيل ميزة \"توفير البيانات\"؟"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"تفعيل"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
<item quantity="zero">لمدة أقل من دقيقة (%1$d) (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
@@ -2202,8 +2205,8 @@
<string name="harmful_app_warning_title" msgid="8794823880881113856">"تم العثور على تطبيق ضار"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"يريد تطبيق <xliff:g id="APP_0">%1$s</xliff:g> عرض شرائح تطبيق <xliff:g id="APP_2">%2$s</xliff:g>."</string>
<string name="screenshot_edit" msgid="7408934887203689207">"تعديل"</string>
- <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"سيهتز الهاتف عند تلقّي المكالمات والإشعارات"</string>
- <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"سيتم كتم صوت الهاتف عند تلقي المكالمات والإشعارات"</string>
+ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"سيهتز الهاتف عند تلقّي المكالمات والإشعارات."</string>
+ <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"سيتم كتم صوت الهاتف عند تلقي المكالمات والإشعارات."</string>
<string name="notification_channel_system_changes" msgid="2462010596920209678">"تغييرات النظام"</string>
<string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"عدم الإزعاج"</string>
<string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"جديد: يؤدي تفعيل ميزة \"عدم الإزعاج\" إلى إخفاء الإشعارات."</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 20740ab..b1bf980 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"আপোনাৰ প্ৰশাসকে আপেডট কৰিছে"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"আপোনাৰ প্ৰশাসকে মচিছে"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ঠিক আছে"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"বেটাৰী সঞ্চয়কাৰীয়ে গাঢ় ৰঙৰ থীম অন কৰে আৰু নেপথ্যৰ কাৰ্যকলাপ, কিছুমান ভিজুৱেল ইফেক্ট, নিৰ্দিষ্ট কিছুমান সুবিধা আৰু নেটৱৰ্কৰ সংযোগ সীমিত অথবা অফ কৰে।"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"বেটাৰী সঞ্চয়কাৰীয়ে গাঢ় ৰঙৰ থীম অন কৰে আৰু নেপথ্যৰ কাৰ্যকলাপ, কিছুমান ভিজুৱেল ইফেক্ট, নিৰ্দিষ্ট কিছুমান সুবিধা আৰু নেটৱৰ্কৰ সংযোগ অফ কৰে অথবা সীমাবদ্ধ কৰে।"</string>
<string name="data_saver_description" msgid="4995164271550590517">"ডেটা ব্য়ৱহাৰৰ হ্ৰাস কৰিবলৈ ডেটা সঞ্চয়কাৰীয়ে কিছুমান এপক নেপথ্য়ত ডেটা প্ৰেৰণ বা সংগ্ৰহ কৰাত বাধা প্ৰদান কৰে। আপুনি বৰ্তমান ব্য়ৱহাৰ কৰি থকা এটা এপে ডেটা এক্সেছ কৰিব পাৰে, কিন্তু সঘনাই এক্সেছ কৰিব নোৱাৰিব পাৰে। ইয়াৰ অৰ্থ উদাহৰণস্বৰূপে এয়া হ\'ব পাৰে যে, আপুনি নিটিপা পর্যন্ত প্ৰতিচ্ছবিসমূহ দেখুওৱা নহ’ব।"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ডেটা সঞ্চয়কাৰী অন কৰিবনে?"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 8db8251..af66b0b 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1157,7 +1157,7 @@
<string name="redo" msgid="7231448494008532233">"Yenidən edin"</string>
<string name="autofill" msgid="511224882647795296">"Avtodoldurma"</string>
<string name="textSelectionCABTitle" msgid="5151441579532476940">"Mətn seçimi"</string>
- <string name="addToDictionary" msgid="8041821113480950096">"Lüğətə əlavə et"</string>
+ <string name="addToDictionary" msgid="8041821113480950096">"Lüğətə əlavə edin"</string>
<string name="deleteText" msgid="4200807474529938112">"Sil"</string>
<string name="inputMethod" msgid="1784759500516314751">"Daxiletmə metodu"</string>
<string name="editTextMenuTitle" msgid="857666911134482176">"Mətn əməliyyatları"</string>
@@ -1366,8 +1366,8 @@
<string name="usb_power_notification_message" msgid="7284765627437897702">"Qoşulmuş cihaza enerji doldurulur. Əlavə seçimlər üçün klikləyin."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Analoq audio aksesuar aşkarlandı"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Əlavə edilən cihaz bu telefonla uyğun deyil. Ətraflı məlumat üçün klikləyin."</string>
- <string name="adb_active_notification_title" msgid="408390247354560331">"USB sazlama qoşuludur"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"USB sazlamanı deaktiv etmək üçün klikləyin"</string>
+ <string name="adb_active_notification_title" msgid="408390247354560331">"USB vasitəsilə sazlama qoşuludur"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Deaktiv etmək üçün klikləyin"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"USb debaqı deaktivasiya etməyi seçin."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"WiFi sazlaması qoşulub"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"WiFi sazlamasını deaktiv etmək üçün toxunun"</string>
@@ -1387,7 +1387,7 @@
<string name="share_remote_bugreport_action" msgid="7630880678785123682">"PAYLAŞIN"</string>
<string name="decline_remote_bugreport_action" msgid="4040894777519784346">"RƏDD EDİN"</string>
<string name="select_input_method" msgid="3971267998568587025">"Daxiletmə metodunu seçin"</string>
- <string name="show_ime" msgid="6406112007347443383">"Fiziki klaviatura aktiv olduğu halda ekranda saxlayın"</string>
+ <string name="show_ime" msgid="6406112007347443383">"Fiziki klaviatura aktiv olanda görünsün"</string>
<string name="hardware" msgid="1800597768237606953">"Virtual klaviaturanı göstərin"</string>
<string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Fiziki klaviaturanı konfiqurasiya edin"</string>
<string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Dil və tərtibatı seçmək üçün tıklayın"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1564,7 +1568,7 @@
<string name="description_target_unlock_tablet" msgid="7431571180065859551">"Kilidi açmaq üçün vurun."</string>
<string name="action_bar_home_description" msgid="1501655419158631974">"Evə naviqasiya et"</string>
<string name="action_bar_up_description" msgid="6611579697195026932">"Yuxarı gedin"</string>
- <string name="action_menu_overflow_description" msgid="4579536843510088170">"Digər variantlar"</string>
+ <string name="action_menu_overflow_description" msgid="4579536843510088170">"Digər seçimlər"</string>
<string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s, %3$s"</string>
<string name="storage_internal" msgid="8490227947584914460">"Daxili paylaşılan yaddaş"</string>
@@ -1710,12 +1714,12 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Qısayol İstifadə edin"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Rəng İnversiyası"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Rəng korreksiyası"</string>
- <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Bir əlli rejim"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Əlavə qaraltma"</string>
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Birəlli rejim"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Əlavə tündləşmə"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Səs səviyyəsi düymələrinə basıb saxlayın. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktiv edildi."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Səs səviyyəsi düymələrinə basılaraq saxlanıb. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> deaktiv edilib."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> istifadə etmək üçün hər iki səs düyməsini üç saniyə basıb saxlayın"</string>
- <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Əlçatımlılıq düyməsinə toxunduqda istifadə edəcəyiniz funksiyanı seçin:"</string>
+ <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Xüsusi imkanlar düyməsinə toxunanda istədiyiniz funksiyanı seçin:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Əlçatımlılıq jesti (iki barmağınızla ekranın aşağısından yuxarı doğru sürüşdürün) ilə istifadə edəcəyiniz funksiyanı seçin:"</string>
<string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Əlçatımlılıq jesti (üç barmağınızla ekranın aşağısından yuxarı doğru sürüşdürün) ilə istifadə edəcəyiniz funksiyanı seçin:"</string>
<string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Funksiyalar arasında keçid etmək üçün əlçatımlılıq düyməsinə toxunub saxlayın."</string>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Admin tərəfindən yeniləndi"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Admin tərəfindən silindi"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Enerjiyə Qənaət rejimi Tünd temanı aktivləşdirir, habelə arxa fon fəaliyyətini, bəzi vizual effektləri, müəyyən xüsusiyyətləri və bəzi şəbəkə bağlantılarını məhdudlaşdırır, yaxud söndürür."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Enerjiyə Qənaət rejimi Tünd temanı aktivləşdirir, habelə arxa fon fəaliyyətini, bəzi vizual effektləri, müəyyən xüsusiyyətləri və bəzi şəbəkə bağlantılarını məhdudlaşdırır, yaxud söndürür."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Mobil interneti qənaətlə işlətmək məqsədilə Data Qanaəti bəzi tətbiqlərin fonda data göndərməsinin və qəbulunun qarşısını alır. Hazırda işlətdiyiniz tətbiq nisbətən az müntəzəmliklə data istifadə edə bilər. Örnək olaraq bu, o deməkdir ki, şəkil fayllarına toxunmadıqca onlar açılmayacaq."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Trafikə qənaət edilsin?"</string>
@@ -1938,7 +1941,7 @@
<string name="usb_midi_peripheral_name" msgid="490523464968655741">"Android USB Peripheral Port"</string>
<string name="usb_midi_peripheral_manufacturer_name" msgid="7557148557088787741">"Android"</string>
<string name="usb_midi_peripheral_product_name" msgid="2836276258480904434">"USB Peripheral Port"</string>
- <string name="floating_toolbar_open_overflow_description" msgid="2260297653578167367">"Daha çox seçim"</string>
+ <string name="floating_toolbar_open_overflow_description" msgid="2260297653578167367">"Digər seçimlər"</string>
<string name="floating_toolbar_close_overflow_description" msgid="3949818077708138098">"Yüklənməni qapadın"</string>
<string name="maximize_button_text" msgid="4258922519914732645">"Böyüdün"</string>
<string name="close_button_text" msgid="10603510034455258">"Qapadın"</string>
@@ -2006,7 +2009,7 @@
<string name="app_category_productivity" msgid="1844422703029557883">"Məhsuldarlıq"</string>
<string name="app_category_accessibility" msgid="6643521607848547683">"Əlçatımlılıq"</string>
<string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"Cihaz yaddaşı"</string>
- <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB sazlama"</string>
+ <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB ilə sazlama"</string>
<string name="time_picker_hour_label" msgid="4208590187662336864">"saat"</string>
<string name="time_picker_minute_label" msgid="8307452311269824553">"dəqiqə"</string>
<string name="time_picker_header_text" msgid="9073802285051516688">"Vaxtı ayarlayın"</string>
@@ -2278,7 +2281,7 @@
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
<string name="window_magnification_prompt_title" msgid="2876703640772778215">"Yeni böyütmə ayarları"</string>
- <string name="window_magnification_prompt_content" msgid="8159173903032344891">"İndi ekranınızın bir hissəsini böyüdə bilərsiniz"</string>
+ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"İndi ekran hissəsini böyütmək olar"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ayarlarda aktiv edin"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Qapadın"</string>
<string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Cihaz mikrofonunu blokdan çıxarın"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 78a9aa7..4cc46d9 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1478,6 +1478,10 @@
<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="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>
@@ -1889,8 +1893,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao je administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao je administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Potvrdi"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Ušteda baterije uključuje tamnu temu i ograničava ili isključuje aktivnosti u pozadini, neke vizuelne efekte, određene funkcije i neke mrežne veze."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Ušteda baterije uključuje tamnu temu i ograničava ili isključuje aktivnosti u pozadini, neke vizuelne efekte, određene funkcije i neke mrežne veze."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Da bi se smanjila potrošnja podataka, Ušteda podataka sprečava neke aplikacije da šalju ili primaju podatke u pozadini. Aplikacija koju trenutno koristite može da pristupa podacima, ali će to činiti ređe. Na primer, slike se neće prikazivati dok ih ne dodirnete."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Želite da uključite Uštedu podataka?"</string>
@@ -2003,7 +2006,7 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> trenutno nije dostupna. <xliff:g id="APP_NAME_1">%2$s</xliff:g> upravlja dostupnošću."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Saznajte više"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Opozovi pauziranje aplikacije"</string>
- <string name="work_mode_off_title" msgid="961171256005852058">"Uključiti poslovne aplikacije?"</string>
+ <string name="work_mode_off_title" msgid="961171256005852058">"Uključujete poslovne aplikacije?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Pristupajte poslovnim aplikacijama i obaveštenjima"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string>
@@ -2126,7 +2129,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Potvrdi"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Isključi"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Saznajte više"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Poboljšana obaveštenja su zamenila Android prilagodljiva obaveštenja u Android-u 12. Ova funkcija pokazuje predložene radnje i odgovore i organizuje obaveštenja.\n\nPoboljšana obaveštenja mogu da pristupaju sadržaju obaveštenja, uključujući lične podatke poput imena kontakata i poruka. Ova funkcija može i da odbacuje obaveštenja ili da odgovara na njih, na primer, da se javlja na telefonske pozive i kontroliše režim Ne uznemiravaj."</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Poboljšana obaveštenja su zamenila Android prilagodljiva obaveštenja u Android-u 12. Ova funkcija pokazuje predložene radnje i odgovore, i organizuje obaveštenja.\n\nPoboljšana obaveštenja mogu da pristupaju sadržaju obaveštenja, uključujući lične podatke poput imena kontakata i poruka. Ova funkcija može i da odbacuje obaveštenja ili da odgovara na njih, na primer, da se javlja na telefonske pozive i kontroliše režim Ne uznemiravaj."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Obaveštenje o informacijama Rutinskog režima"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Baterija će se možda isprazniti pre uobičajenog punjenja"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Ušteda baterije je aktivirana da bi se produžilo trajanje baterije"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index fe22c56..1423737 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1498,6 +1498,10 @@
<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="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>
@@ -1912,8 +1916,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Абноўлены вашым адміністратарам"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Выдалены вашым адміністратарам"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"У рэжыме эканоміі зараду ўключаецца цёмная тэма і выключаюцца ці абмяжоўваюцца дзеянні ў фонавым рэжыме, некаторыя візуальныя эфекты, пэўныя функцыі і падключэнні да сетак."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"У рэжыме эканоміі зараду ўключаецца цёмная тэма і выключаюцца ці абмяжоўваюцца дзеянні ў фонавым рэжыме, некаторыя візуальныя эфекты, пэўныя функцыі і падключэнні да сетак."</string>
<string name="data_saver_description" msgid="4995164271550590517">"У рэжыме \"Эканомія трафіка\" фонавая перадача для некаторых праграмам адключана. Праграма, якую вы зараз выкарыстоўваеце, можа атрымліваць доступ да даных, але радзей, чым звычайна. Напрыклад, відарысы могуць не загружацца, пакуль вы не націсніце на іх."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Уключыць Эканомію трафіка?"</string>
@@ -2216,8 +2219,8 @@
<string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Размова"</string>
<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_personal_tab" msgid="2051260504014442073">"Асабісты"</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-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 6a2db08..92e1a86 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1355,7 +1355,7 @@
<string name="no_permissions" msgid="5729199278862516390">"Не се изискват разрешения"</string>
<string name="perm_costs_money" msgid="749054595022779685">"това може да ви струва пари"</string>
<string name="dlg_ok" msgid="5103447663504839312">"OK"</string>
- <string name="usb_charging_notification_title" msgid="1674124518282666955">"Това устройство се зарежда през USB"</string>
+ <string name="usb_charging_notification_title" msgid="1674124518282666955">"Устройството се зарежда през USB"</string>
<string name="usb_supplying_notification_title" msgid="5378546632408101811">"Свързаното устройство се зарежда през USB"</string>
<string name="usb_mtp_notification_title" msgid="1065989144124499810">"Прехвърлянето на файлове през USB е включено"</string>
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Режимът PTP през USB е включен"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Актуализирано от администратора ви"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Изтрито от администратора ви"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Режимът за запазване на батерията включва тъмната тема и ограничава или изключва активността на заден план, някои визуални ефекти, определени функции и някои връзки с мрежата."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Режимът за запазване на батерията включва тъмната тема и ограничава или изключва активността на заден план, някои визуални ефекти, определени функции и някои връзки с мрежата."</string>
<string name="data_saver_description" msgid="4995164271550590517">"С цел намаляване на преноса на данни функцията за икономия на данни не позволява на някои приложения да изпращат или получават данни на заден план. Понастоящем използвано от вас приложение може да използва данни, но по-рядко. Това например може да означава, че изображенията не се показват, докато не ги докоснете."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Включване на „Икономия на данни“?"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 73bf6a5..2a9ecf6 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -609,12 +609,10 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"আঙ্গুলের ছাপ আইকন"</string>
- <!-- no translation found for face_recalibrate_notification_name (7311163114750748686) -->
- <skip />
+ <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"\'ফেস আনলক\'"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"আপনার ফেস আবার এনরোল করুন"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"শনাক্তকরণের উন্নতি করতে আপনার ফেস আবার এনরোল করুন"</string>
- <!-- no translation found for face_setup_notification_title (8843461561970741790) -->
- <skip />
+ <string name="face_setup_notification_title" msgid="8843461561970741790">"\'ফেস আনলক\' সেট আপ করুন"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"আপনার ফোনের দিকে তাকিয়ে এটিকে আনলক করুন"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"আনলক করার জন্য বিভিন্ন উপায়ে সেট আপ করুন"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"একটি আঙ্গুলের ছাপ যোগ করতে ট্যাপ করুন"</string>
@@ -641,26 +639,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"ফেস যাচাই করা যায়নি। হার্ডওয়্যার উপলভ্য নেই।"</string>
- <!-- no translation found for face_error_timeout (2598544068593889762) -->
- <skip />
+ <string name="face_error_timeout" msgid="2598544068593889762">"\'ফেস আনলক\' আবার ব্যবহার করার চেষ্টা করুন"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"নতুন ফেস ডেটা স্টোর করা যায়নি। প্রথমে পুরনোটি মুছে ফেলুন।"</string>
<string name="face_error_canceled" msgid="2164434737103802131">"ফেস অপারেশন বাতিল করা হয়েছে৷"</string>
- <!-- no translation found for face_error_user_canceled (5766472033202928373) -->
- <skip />
+ <string name="face_error_user_canceled" msgid="5766472033202928373">"ব্যবহারকারী \'ফেস আনলক\' বাতিল করে দিয়েছেন"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"অনেকবার চেষ্টা করা হয়েছে। পরে আবার চেষ্টা করুন।"</string>
- <!-- no translation found for face_error_lockout_permanent (3277134834042995260) -->
- <skip />
- <!-- no translation found for face_error_lockout_screen_lock (5062609811636860928) -->
- <skip />
+ <string name="face_error_lockout_permanent" msgid="3277134834042995260">"অনেকবার চেষ্টা করেছেন। \'ফেস আনলক\' বন্ধ করা হয়েছে।"</string>
+ <string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"অনেকবার চেষ্টা করেছেন। এর পরিবর্তে স্ক্রিন লক ব্যবহার করুন।"</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"আপনার মুখ যাচাই করা যাচ্ছে না। আবার চেষ্টা করুন।"</string>
- <!-- no translation found for face_error_not_enrolled (1134739108536328412) -->
- <skip />
- <!-- no translation found for face_error_hw_not_present (7940978724978763011) -->
- <skip />
+ <string name="face_error_not_enrolled" msgid="1134739108536328412">"এখনও \'ফেস আনলক\' সেট আপ করেননি"</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"এই ডিভাইসে \'ফেস আনলক\' কাজ করবে না"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"সেন্সর অস্থায়ীভাবে বন্ধ করা আছে।"</string>
<string name="face_name_template" msgid="3877037340223318119">"<xliff:g id="FACEID">%d</xliff:g> ফেস"</string>
- <!-- no translation found for face_app_setting_name (5854024256907828015) -->
- <skip />
+ <string name="face_app_setting_name" msgid="5854024256907828015">"\'ফেস আনলক\' ব্যবহার করুন"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"ফেস অথবা স্ক্রিন লক ব্যবহার করুন"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"চালিয়ে যেতে আপনার মুখ ব্যবহার করুন"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"চালিয়ে যেতে আপনার ফেস বা স্ক্রিন লক ব্যবহার করুন"</string>
@@ -963,8 +954,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"আনলক এলাকা প্রসারিত করুন৷"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"স্লাইড দিয়ে আনলক৷"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"প্যাটার্ন দিয়ে আনলক৷"</string>
- <!-- no translation found for keyguard_accessibility_face_unlock (4533832120787386728) -->
- <skip />
+ <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"\'ফেস আনলক\'।"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"পিন দিয়ে আনলক৷"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"সিম পিন আনলক।"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"সিম পিইউকে আনলক।"</string>
@@ -1468,6 +1458,10 @@
<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="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>
@@ -1876,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"আপনার প্রশাসক আপডেট করেছেন"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"আপনার প্রশাসক মুছে দিয়েছেন"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ঠিক আছে"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ব্যাটারি সেভার ডার্ক থিম চালু করে এবং ব্যাকগ্রাউন্ড অ্যাক্টিভিটি, কিছু ভিজ্যুয়াল এফেক্ট, নির্দিষ্ট ফিচার ও কয়েকটি নেটওয়ার্ক কানেকশনের ব্যবহার সীমিত করে বা বন্ধ করে দেয়।"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"ব্যাটারি সেভার ডার্ক থিম চালু করে এবং ব্যাকগ্রাউন্ড অ্যাক্টিভিটি, কিছু ভিজ্যুয়াল এফেক্ট, নির্দিষ্ট ফিচার ও কয়েকটি নেটওয়ার্ক কানেকশনের ব্যবহার সীমিত করে বা বন্ধ করে দেয়।"</string>
<string name="data_saver_description" msgid="4995164271550590517">"ডেটার ব্যবহার কমাতে সহায়তা করার জন্য, ডেটা সেভার ব্যাকগ্রাউন্ডে কিছু অ্যাপ্লিকেশনকে ডেটা পাঠাতে বা গ্রহণ করতে বাধা দেয়৷ আপনি বর্তমানে এমন একটি অ্যাপ্লিকেশন ব্যবহার করছেন যেটি ডেটা অ্যাক্সেস করতে পারে, তবে সেটি কমই করে৷ এর ফলে যা হতে পারে, উদাহরণস্বরূপ, আপনি ছবির উপর ট্যাপ না করা পর্যন্ত সেগুলি দেখানো হবে না৷"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ডেটা সেভার চালু করবেন?"</string>
@@ -2169,7 +2162,7 @@
<string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"ব্যক্তিগত অ্যাপে এই কন্টেন্ট খোলা যাবে না"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"অফিস প্রোফাইল বন্ধ করা আছে"</string>
<string name="resolver_switch_on_work" msgid="463709043650610420">"চালু করতে ট্যাপ করুন"</string>
- <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"অফিসের অ্যাপ ব্যবহার করা যাবে না"</string>
+ <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"এর জন্য কোনও অফিস অ্যাপ নেই"</string>
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ব্যক্তিগত অ্যাপে দেখা যাবে না"</string>
<string name="miniresolver_open_in_personal" msgid="2937599899213467617">"ব্যক্তিগত প্রোফাইলে <xliff:g id="APP">%s</xliff:g> অ্যাপ খুলতে চান?"</string>
<string name="miniresolver_open_in_work" msgid="152208044699347924">"অফিস প্রোফাইলে <xliff:g id="APP">%s</xliff:g> অ্যাপ খুলতে চান?"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 067d68f..f811ac2 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1478,6 +1478,10 @@
<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="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>
@@ -1889,7 +1893,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao je vaš administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao je vaš administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Uredu"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Štednja baterije uključuje tamnu temu i ograničava ili isključuje aktivnosti u pozadini, neke vizualne efekte, određene značajke i neke mrežne veze."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Ušteda baterije uključuje tamnu temu i ograničava ili isključuje aktivnost u pozadini, određene vizuelne efekte i funkcije te neke mrežne veze."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Ušteda baterije uključuje Tamnu temu i ograničava ili isključuje aktivnost u pozadini, određene vizuelne efekte i funkcije i neke mrežne veze."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Radi smanjenja prijenosa podataka, Ušteda podataka sprečava da neke aplikacije šalju ili primaju podatke u pozadini. Aplikacija koju trenutno koristite može pristupiti podacima, ali će to činiti rjeđe. Naprimjer, to može značiti da se slike ne prikazuju dok ih ne dodirnete."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Uključiti Uštedu podataka?"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index dddc40b..19762bf 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1869,7 +1873,7 @@
<string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Estalvi de bateria activa el tema fosc i limita o desactiva l\'activitat en segon pla, alguns efectes visuals, determinades funcions i algunes connexions a la xarxa."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Estalvi de bateria activa el tema fosc i limita o desactiva l\'activitat en segon pla, alguns efectes visuals, determinades funcions i algunes connexions a la xarxa."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Per reduir l\'ús de dades, la funció Economitzador de dades evita que determinades aplicacions enviïn o rebin dades en segon pla. L\'aplicació que estiguis fent servir podrà accedir a les dades, però menys sovint. Això vol dir, per exemple, que les imatges no es mostraran fins que no les toquis."</string>
- <string name="data_saver_enable_title" msgid="7080620065745260137">"Activar l\'Economitzador de dades?"</string>
+ <string name="data_saver_enable_title" msgid="7080620065745260137">"Vols activar l\'Economitzador de dades?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Activa"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
<item quantity="other">Durant %1$d minuts (fins a les <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
@@ -1971,7 +1975,7 @@
<string name="app_suspended_more_details" msgid="211260942831587014">"Més informació"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Reactiva l\'aplicació"</string>
<string name="work_mode_off_title" msgid="961171256005852058">"Activar aplicacions de treball?"</string>
- <string name="work_mode_off_message" msgid="7319580997683623309">"Accedeix a les teves aplicacions de treball i a les notificacions"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Accedeix a les teves aplicacions i notificacions de treball"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activa"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"L\'aplicació no està disponible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Ara mateix, <xliff:g id="APP_NAME">%1$s</xliff:g> no està disponible."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 6dbf7d4..95b2b55 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1498,6 +1498,10 @@
<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="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>
@@ -2225,7 +2229,7 @@
<string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"Tento obsah nelze sdílet pomocí osobních aplikací"</string>
<string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"Tento obsah nelze otevřít pomocí osobních aplikací"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Pracovní profil je pozastaven"</string>
- <string name="resolver_switch_on_work" msgid="463709043650610420">"Klepnutím zapnete"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"Klepnutím ho zapnete"</string>
<string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Žádné pracovní aplikace"</string>
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Žádné osobní aplikace"</string>
<string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Otevřít v aplikaci <xliff:g id="APP">%s</xliff:g> v osobním profilu?"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 8cebc77..79379f1 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Opdateret af din administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Slettet af din administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Batterisparefunktionen aktiverer Mørkt tema og begrænser eller deaktiverer aktivitet i baggrunden og visse visuelle effekter, funktioner og netværksforbindelser."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Batterisparefunktionen aktiverer Mørkt tema og begrænser eller deaktiverer aktivitet i baggrunden og visse visuelle effekter, funktioner og netværksforbindelser."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Datasparefunktionen forhindrer nogle apps i at sende eller modtage data i baggrunden for at reducere dataforbruget. En app, der er i brug, kan få adgang til data, men gør det måske ikke så ofte. Dette kan f.eks. betyde, at billeder ikke vises, før du trykker på dem."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Vil du aktivere Datasparefunktion?"</string>
@@ -2126,7 +2129,7 @@
<item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fil</item>
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> filer</item>
</plurals>
- <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Der er ingen anbefalede brugere at dele med"</string>
+ <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Der er ingen anbefalede personer at dele med"</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Liste over apps"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Denne app har ikke fået tilladelse til at optage, men optager muligvis lyd via denne USB-enhed."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Hjem"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 4bac1d8..b8727e8 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -350,7 +350,7 @@
<string name="permlab_fullScreenIntent" msgid="4310888199502509104">"Benachrichtigungen auf einem gesperrten Gerät als Vollbildaktivitäten anzeigen"</string>
<string name="permdesc_fullScreenIntent" msgid="1100721419406643997">"Ermöglicht der App, Benachrichtigungen auf einem gesperrten Gerät als Vollbildaktivitäten anzuzeigen"</string>
<string name="permlab_install_shortcut" msgid="7451554307502256221">"Verknüpfungen installieren"</string>
- <string name="permdesc_install_shortcut" msgid="4476328467240212503">"Ermöglicht einer App das Hinzufügen von Verknüpfungen zum Startbildschirm ohne Eingriff des Nutzers"</string>
+ <string name="permdesc_install_shortcut" msgid="4476328467240212503">"ohne Zutun des Nutzers Verknüpfungen zum Startbildschirm hinzufügen."</string>
<string name="permlab_uninstall_shortcut" msgid="295263654781900390">"Verknüpfungen deinstallieren"</string>
<string name="permdesc_uninstall_shortcut" msgid="1924735350988629188">"Ermöglicht einer App das Entfernen von Verknüpfungen vom Startbildschirm ohne Eingriff des Nutzers"</string>
<string name="permlab_processOutgoingCalls" msgid="4075056020714266558">"Ausgehende Anrufe umleiten"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,10 +1870,9 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Von deinem Administrator aktualisiert"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Von deinem Administrator gelöscht"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Der Energiesparmodus aktiviert das dunkle Design und schränkt Hintergrundaktivitäten, einige Funktionen und optische Effekte sowie manche Netzwerkverbindungen ein oder deaktiviert sie."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Der Energiesparmodus aktiviert das dunkle Design und schränkt Hintergrundaktivitäten, einige Funktionen und optische Effekte und manche Netzwerkverbindungen ein oder deaktiviert sie."</string>
- <string name="data_saver_description" msgid="4995164271550590517">"Der Datensparmodus verhindert zum einen, dass manche Apps im Hintergrund Daten senden oder empfangen, sodass weniger Daten verbraucht werden. Zum anderen werden die Datenzugriffe der gerade aktiven App eingeschränkt, was z. B. dazu führen kann, dass Bilder erst angetippt werden müssen, bevor sie sichtbar werden."</string>
+ <string name="data_saver_description" msgid="4995164271550590517">"Der Datensparmodus verhindert, dass manche Apps im Hintergrund Daten senden oder empfangen, sodass weniger Daten verbraucht werden. Auch werden die Datenzugriffe der gerade aktiven App eingeschränkt, was z. B. dazu führen kann, dass Bilder erst angetippt werden müssen, bevor sie sichtbar werden."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Datensparmodus aktivieren?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aktivieren"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
@@ -2070,7 +2073,7 @@
<string name="harmful_app_warning_title" msgid="8794823880881113856">"Schädliche App erkannt"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> möchte Teile von <xliff:g id="APP_2">%2$s</xliff:g> anzeigen"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Bearbeiten"</string>
- <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Anrufe und Benachrichtigungen per Vibrationsalarm"</string>
+ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Gerät vibriert bei Anrufen und Benachrichtigungen"</string>
<string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Anrufe und Benachrichtigungen stummgeschaltet"</string>
<string name="notification_channel_system_changes" msgid="2462010596920209678">"Systemänderungen"</string>
<string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Bitte nicht stören"</string>
@@ -2131,7 +2134,7 @@
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Diese App hat noch keine Berechtigung zum Aufnehmen erhalten, könnte aber Audioaufnahmen über dieses USB-Gerät machen."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Startseite"</string>
<string name="accessibility_system_action_back_label" msgid="4205361367345537608">"Zurück"</string>
- <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"Letzte Apps"</string>
+ <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"Kürzlich geöffnete Apps"</string>
<string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"Benachrichtigungen"</string>
<string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Schnelleinstellungen"</string>
<string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"Kleines Fenster für Akkustand"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index a2624a1..2aa10e5 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1458,6 +1458,10 @@
<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="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 f16e2e4..0817cb5 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1458,6 +1458,10 @@
<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="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 2a67834..6e3b041 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1458,6 +1458,10 @@
<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="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 bb1e6f3..74973c4 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1458,6 +1458,10 @@
<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="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 a06053f..8fe3f42 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1458,6 +1458,10 @@
<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="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 022f060..2d92123 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1458,6 +1458,10 @@
<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="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-rCO/donottranslate-cldr.xml b/core/res/res/values-es-rCO/donottranslate-cldr.xml
new file mode 100755
index 0000000..db438f2
--- /dev/null
+++ b/core/res/res/values-es-rCO/donottranslate-cldr.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%-e %b %Y, %H:%M:%S</string>
+ <string name="date_time">%1$s, %2$s</string>
+</resources>
diff --git a/core/res/res/values-es-rCR/donottranslate-cldr.xml b/core/res/res/values-es-rCR/donottranslate-cldr.xml
new file mode 100755
index 0000000..db438f2
--- /dev/null
+++ b/core/res/res/values-es-rCR/donottranslate-cldr.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%-e %b %Y, %H:%M:%S</string>
+ <string name="date_time">%1$s, %2$s</string>
+</resources>
diff --git a/core/res/res/values-es-rEC/donottranslate-cldr.xml b/core/res/res/values-es-rEC/donottranslate-cldr.xml
new file mode 100755
index 0000000..db438f2
--- /dev/null
+++ b/core/res/res/values-es-rEC/donottranslate-cldr.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%-e %b %Y, %H:%M:%S</string>
+ <string name="date_time">%1$s, %2$s</string>
+</resources>
diff --git a/core/res/res/values-es-rGT/donottranslate-cldr.xml b/core/res/res/values-es-rGT/donottranslate-cldr.xml
new file mode 100755
index 0000000..db438f2
--- /dev/null
+++ b/core/res/res/values-es-rGT/donottranslate-cldr.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%-e %b %Y, %H:%M:%S</string>
+ <string name="date_time">%1$s, %2$s</string>
+</resources>
diff --git a/core/res/res/values-es-rHN/donottranslate-cldr.xml b/core/res/res/values-es-rHN/donottranslate-cldr.xml
new file mode 100755
index 0000000..db438f2
--- /dev/null
+++ b/core/res/res/values-es-rHN/donottranslate-cldr.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%-e %b %Y, %H:%M:%S</string>
+ <string name="date_time">%1$s, %2$s</string>
+</resources>
diff --git a/core/res/res/values-es-rNI/donottranslate-cldr.xml b/core/res/res/values-es-rNI/donottranslate-cldr.xml
new file mode 100755
index 0000000..db438f2
--- /dev/null
+++ b/core/res/res/values-es-rNI/donottranslate-cldr.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%-e %b %Y, %H:%M:%S</string>
+ <string name="date_time">%1$s, %2$s</string>
+</resources>
diff --git a/core/res/res/values-es-rPA/donottranslate-cldr.xml b/core/res/res/values-es-rPA/donottranslate-cldr.xml
new file mode 100755
index 0000000..db438f2
--- /dev/null
+++ b/core/res/res/values-es-rPA/donottranslate-cldr.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%-e %b %Y, %H:%M:%S</string>
+ <string name="date_time">%1$s, %2$s</string>
+</resources>
diff --git a/core/res/res/values-es-rPE/donottranslate-cldr.xml b/core/res/res/values-es-rPE/donottranslate-cldr.xml
new file mode 100755
index 0000000..db438f2
--- /dev/null
+++ b/core/res/res/values-es-rPE/donottranslate-cldr.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%-e %b %Y, %H:%M:%S</string>
+ <string name="date_time">%1$s, %2$s</string>
+</resources>
diff --git a/core/res/res/values-es-rSV/donottranslate-cldr.xml b/core/res/res/values-es-rSV/donottranslate-cldr.xml
new file mode 100755
index 0000000..db438f2
--- /dev/null
+++ b/core/res/res/values-es-rSV/donottranslate-cldr.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%-e %b %Y, %H:%M:%S</string>
+ <string name="date_time">%1$s, %2$s</string>
+</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index a164ffe..9102b89 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1458,6 +1458,10 @@
<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="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 a925eea..07f805b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -148,7 +148,7 @@
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Solo Wi-Fi"</string>
<!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
<skip />
- <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"Llamadas de reserva de <xliff:g id="SPN">%s</xliff:g>"</string>
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"Alternativa para llamadas de <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: No desviada"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> transcurridos <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizado por el administrador"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado por el administrador"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"El modo Ahorro de batería activa el tema oscuro y limita o desactiva la actividad en segundo plano, algunos efectos visuales, ciertas funciones y algunas conexiones de red."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"El modo Ahorro de batería activa el tema oscuro y limita o desactiva la actividad en segundo plano, algunos efectos visuales, ciertas funciones y algunas conexiones de red."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Ahorro de datos evita que algunas aplicaciones envíen o reciban datos en segundo plano, lo que puede reducir el uso de datos. Una aplicación activa puede acceder a los datos, aunque con menos frecuencia. Esto significa que es posible que, por ejemplo, algunas imágenes no se muestren hasta que las toques."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"¿Activar Ahorro de datos?"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index b315dd8..937161b 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administraator on seda värskendanud"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administraator on selle kustutanud"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Akusäästja lülitab sisse tumeda teema ja lülitab välja taustategevused, mõned visuaalsed efektid, teatud funktsioonid ja võrguühendused või piirab neid."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Akusäästja lülitab sisse tumeda teema ja lülitab välja taustategevused, mõned visuaalsed efektid, teatud funktsioonid ja võrguühendused või piirab neid."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Andmekasutuse vähendamiseks keelab andmemahu säästja mõne rakenduse puhul andmete taustal saatmise ja vastuvõtmise. Rakendus, mida praegu kasutate, pääseb andmesidele juurde, kuid võib seda teha väiksema sagedusega. Seetõttu võidakse näiteks pildid kuvada alles siis, kui neid puudutate."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Lülitada andmemahu säästja sisse?"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index d51884d..3160134 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -309,7 +309,7 @@
<string name="permgroupdesc_location" msgid="1995955142118450685">"atzitu gailuaren kokapena"</string>
<string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
<string name="permgroupdesc_calendar" msgid="6762751063361489379">"atzitu egutegia"</string>
- <string name="permgrouplab_sms" msgid="795737735126084874">"SMS mezuak"</string>
+ <string name="permgrouplab_sms" msgid="795737735126084874">"SMSak"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"bidali eta ikusi SMS mezuak"</string>
<string name="permgrouplab_storage" msgid="1938416135375282333">"Fitxategiak eta multimedia-edukia"</string>
<string name="permgroupdesc_storage" msgid="6351503740613026600">"atzitu gailuko argazkiak, multimedia-edukia eta fitxategiak"</string>
@@ -609,10 +609,10 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Hatz-markaren ikonoa"</string>
- <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Aurpegiaren bidez desblokeatzeko eginbidea"</string>
+ <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Aurpegi bidez desblokeatzeko eginbidea"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Erregistratu aurpegia berriro"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Ezagutzea hobetzeko, erregistratu aurpegia berriro"</string>
- <string name="face_setup_notification_title" msgid="8843461561970741790">"Konfiguratu aurpegiaren bidez desblokeatzeko eginbidea"</string>
+ <string name="face_setup_notification_title" msgid="8843461561970741790">"Konfiguratu aurpegi bidez desblokeatzeko eginbidea"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Telefonoa desblokeatzeko, begira iezaiozu"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Konfiguratu telefonoa desblokeatzeko modu gehiago"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Sakatu hau hatz-marka bat gehitzeko"</string>
@@ -642,16 +642,16 @@
<string name="face_error_timeout" msgid="2598544068593889762">"Saiatu berriro aurpegiaren bidez desblokeatzen"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Ezin dira gorde aurpegiaren datu berriak. Ezabatu zaharrak."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Utzi da aurpegiaren bidezko eragiketa."</string>
- <string name="face_error_user_canceled" msgid="5766472033202928373">"Erabiltzaileak aurpegiaren bidez desblokeatzeko aukera utzi du"</string>
+ <string name="face_error_user_canceled" msgid="5766472033202928373">"Erabiltzaileak aurpegi bidez desblokeatzeko aukera utzi du"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string>
- <string name="face_error_lockout_permanent" msgid="3277134834042995260">"Saiakera gehiegi egin dira. Desgaitu egin da aurpegiaren bidez desblokeatzeko eginbidea."</string>
+ <string name="face_error_lockout_permanent" msgid="3277134834042995260">"Saiakera gehiegi egin dira. Desgaitu egin da aurpegi bidez desblokeatzeko eginbidea."</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"Saiakera gehiegi egin dira. Horren ordez, erabili pantailaren blokeoa."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Ezin da egiaztatu aurpegia. Saiatu berriro."</string>
- <string name="face_error_not_enrolled" msgid="1134739108536328412">"Ez duzu konfiguratu aurpegiaren bidez desblokeatzeko eginbidea"</string>
- <string name="face_error_hw_not_present" msgid="7940978724978763011">"Aurpegiaren bidez desblokeatzeko eginbidea ez da bateragarria gailu honekin"</string>
+ <string name="face_error_not_enrolled" msgid="1134739108536328412">"Ez duzu konfiguratu aurpegi bidez desblokeatzeko eginbidea"</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"Aurpegi bidez desblokeatzeko eginbidea ez da bateragarria gailu honekin"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sentsorea aldi baterako desgaitu da."</string>
<string name="face_name_template" msgid="3877037340223318119">"<xliff:g id="FACEID">%d</xliff:g> aurpegia"</string>
- <string name="face_app_setting_name" msgid="5854024256907828015">"Erabili aurpegiaren bidez desblokeatzeko eginbidea"</string>
+ <string name="face_app_setting_name" msgid="5854024256907828015">"Erabili aurpegi bidez desblokeatzeko eginbidea"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Erabili aurpegia edo pantailaren blokeoa"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Aurrera egiteko, erabili aurpegia"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Aurrera egiteko, erabili aurpegia edo pantailaren blokeoa"</string>
@@ -884,7 +884,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Saiatu berriro"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Saiatu berriro"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Desblokeatu eginbide eta datu guztiak erabiltzeko"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Gainditu da aurpegiaren bidez desblokeatzeko saiakera-muga"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Gainditu da aurpegi bidez desblokeatzeko saiakera-muga"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Ez dago SIM txartelik"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Ez dago SIM txartelik tabletan."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Ez dago SIM txartelik Android TV gailuan."</string>
@@ -954,7 +954,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Zabaldu desblokeatzeko eremua."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Hatza lerratuta desblokeatzea."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Ereduaren bidez desblokeatzea."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Aurpegiaren bidez desblokeatzeko eginbidea."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Aurpegi bidez desblokeatzeko eginbidea."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"PIN kodearen bidez desblokeatzea."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIMa desblokeatzeko PINa."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM txartela desblokeatzeko PUK kodea."</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administratzaileak eguneratu du"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administratzaileak ezabatu du"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Ados"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Bateria-aurrezleak gai iluna aktibatzen du, eta murriztu edo desaktibatu egiten ditu atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Bateria-aurrezleak gai iluna aktibatzen du, eta atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk murrizten edo desaktibatzen ditu."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Datuen erabilera murrizteko, atzeko planoan datuak bidaltzea eta jasotzea galarazten die datu-aurrezleak aplikazio batzuei. Une honetan erabiltzen ari zaren aplikazio batek datuak atzitu ahal izango ditu, baina baliteke maiztasun txikiagoarekin atzitzea. Horrela, adibidez, baliteke irudiak ez erakustea haiek sakatu arte."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Datu-aurrezlea aktibatu nahi duzu?"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3f75627..3787d4c 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"توسط سرپرست سیستم بهروزرسانی شد"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"توسط سرپرست سیستم حذف شد"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"تأیید"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"«بهینهسازی باتری» «طرح زمینه تیره» را روشن میکند و فعالیت پسزمینه، برخی از جلوههای بصری، ویژگیهایی خاص، و برخی از اتصالهای شبکه را محدود یا خاموش میکند."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"«بهینهسازی باتری» «طرح زمینه تیره» را روشن میکند و فعالیت پسزمینه، برخی از جلوههای بصری، ویژگیهایی خاص، و برخی از اتصالهای شبکه را محدود یا خاموش میکند."</string>
<string name="data_saver_description" msgid="4995164271550590517">"برای کمک به کاهش مصرف داده، «صرفهجویی داده» از ارسال و دریافت داده در پسزمینه در بعضی برنامهها جلوگیری میکند. برنامهای که درحالحاضر استفاده میکنید میتواند به دادهها دسترسی داشته باشد اما دفعات دسترسی آن محدود است. این میتواند به این معنی باشد که، برای مثال، تصاویر تازمانیکه روی آنها ضربه نزنید نشان داده نمیشوند."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"«صرفهجویی داده» روشن شود؟"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index a9db987..965970c 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1355,7 +1355,7 @@
<string name="no_permissions" msgid="5729199278862516390">"Lupia ei tarvita"</string>
<string name="perm_costs_money" msgid="749054595022779685">"tämä voi maksaa"</string>
<string name="dlg_ok" msgid="5103447663504839312">"OK"</string>
- <string name="usb_charging_notification_title" msgid="1674124518282666955">"Laitetta ladataan USB-yhteyden kautta"</string>
+ <string name="usb_charging_notification_title" msgid="1674124518282666955">"Laite lataa USB-yhteydellä"</string>
<string name="usb_supplying_notification_title" msgid="5378546632408101811">"Ladataan yhdistettyä laitetta USB:n kautta"</string>
<string name="usb_mtp_notification_title" msgid="1065989144124499810">"USB-tiedostonsiirto on käytössä"</string>
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP USB:n kautta on käytössä"</string>
@@ -1367,7 +1367,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Analoginen äänilaite havaittu"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Liitetty laite ei ole yhteensopiva puhelimen kanssa. Napauta, niin näet lisätietoja."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"USB-vianetsintä yhdistetty"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"Laita USB-vianetsintä pois päältä napauttamalla"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Sulje USB-vianetsintä napauttamalla"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Poista USB-vianetsintä käytöstä valitsemalla tämä."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Langaton virheenkorjaus yhdistetty"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Poista langaton virheenkorjaus käytöstä napauttamalla"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Järjestelmänvalvoja päivitti tämän."</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Järjestelmänvalvoja poisti tämän."</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Virransäästö laittaa tumman teeman päälle ja rajoittaa tai laittaa pois päältä taustatoimintoja, tiettyjä ominaisuuksia sekä joitakin visuaalisia tehosteita ja verkkoyhteyksiä."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Virransäästö laittaa tumman teeman päälle ja rajoittaa tai laittaa pois päältä taustatoimintoja, tiettyjä ominaisuuksia sekä joitakin visuaalisia tehosteita ja verkkoyhteyksiä."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Data Saver estää joitakin sovelluksia lähettämästä tai vastaanottamasta tietoja taustalla, jotta datan käyttöä voidaan vähentää. Käytössäsi oleva sovellus voi yhä käyttää dataa, mutta se saattaa tehdä niin tavallista harvemmin. Tämä voi tarkoittaa esimerkiksi sitä, että kuva ladataan vasta, kun kosketat sitä."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Otetaanko Data Saver käyttöön?"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 3412dbc..44754d7 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -280,8 +280,8 @@
<string name="notification_channel_security" msgid="8516754650348238057">"Sécurité"</string>
<string name="notification_channel_car_mode" msgid="2123919247040988436">"Mode Voiture"</string>
<string name="notification_channel_account" msgid="6436294521740148173">"État du compte"</string>
- <string name="notification_channel_developer" msgid="1691059964407549150">"Messages des concepteurs"</string>
- <string name="notification_channel_developer_important" msgid="7197281908918789589">"Messages importants à l\'intention des concepteurs"</string>
+ <string name="notification_channel_developer" msgid="1691059964407549150">"Messages des développeurs"</string>
+ <string name="notification_channel_developer_important" msgid="7197281908918789589">"Messages importants à l\'intention des développeurs"</string>
<string name="notification_channel_updates" msgid="7907863984825495278">"Mises à jour"</string>
<string name="notification_channel_network_status" msgid="2127687368725272809">"État du réseau"</string>
<string name="notification_channel_network_alerts" msgid="6312366315654526528">"Alertes réseau"</string>
@@ -1271,7 +1271,7 @@
<string name="dump_heap_ready_notification" msgid="2302452262927390268">"L\'empreinte de mémoire <xliff:g id="PROC">%1$s</xliff:g> est prête"</string>
<string name="dump_heap_notification_detail" msgid="8431586843001054050">"L\'empreinte de mémoire a été recueillie. Touchez ici pour la partager."</string>
<string name="dump_heap_title" msgid="4367128917229233901">"Partager l\'empreinte de mémoire?"</string>
- <string name="dump_heap_text" msgid="1692649033835719336">"Le processus <xliff:g id="PROC">%1$s</xliff:g> a dépassé sa limite de mémoire de <xliff:g id="SIZE">%2$s</xliff:g>. Vous pouvez partager son empreinte de mémoire avec son concepteur. Attention : Cette empreinte peut contenir certains de vos renseignements personnels auxquels l\'application a accès."</string>
+ <string name="dump_heap_text" msgid="1692649033835719336">"Le processus <xliff:g id="PROC">%1$s</xliff:g> a dépassé sa limite de mémoire de <xliff:g id="SIZE">%2$s</xliff:g>. Vous pouvez partager son empreinte de mémoire avec son développeur. Attention : Cette empreinte peut contenir certains de vos renseignements personnels auxquels l\'application a accès."</string>
<string name="dump_heap_system_text" msgid="6805155514925350849">"Le processus <xliff:g id="PROC">%1$s</xliff:g> a dépassé sa limite de mémoire de <xliff:g id="SIZE">%2$s</xliff:g>. Vous pouvez partager son empreinte de mémoire. Attention : Cette empreinte peut contenir des renseignements personnels auxquels le processus a accès, y compris du texte que vous avez entré."</string>
<string name="dump_heap_ready_text" msgid="5849618132123045516">"Une empreinte de mémoire du processus lié à l\'application <xliff:g id="PROC">%1$s</xliff:g> peut être partagée. Attention : Cette empreinte peut contenir des renseignements personnels auxquels le processus a accès, y compris du texte que vous avez entré."</string>
<string name="sendText" msgid="493003724401350724">"Sélectionner une action pour le texte"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Mise à jour par votre administrateur"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Le mode Économiseur de pile active le thème sombre et limite ou désactive l\'activité en arrière-plan, certains effets visuels, certaines fonctionnalités et certaines connexions réseau."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Le mode Économiseur de pile active le thème sombre et limite ou désactive l\'activité en arrière-plan, certains effets visuels, certaines fonctionnalités et certaines connexions réseau."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Pour aider à diminuer l\'utilisation des données, la fonctionnalité Économiseur de données empêche certaines applications d\'envoyer ou de recevoir des données en arrière-plan. Une application que vous utilisez actuellement peut accéder à des données, mais peut le faire moins souvent. Cela peut signifier, par exemple, que les images ne s\'affichent pas jusqu\'à ce que vous les touchiez."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Activer l\'économiseur de données?"</string>
@@ -1976,7 +1979,7 @@
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activer"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"L\'application n\'est pas accessible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas accessible pour le moment."</string>
- <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Cette application a été conçue pour une ancienne version d\'Android et pourrait ne pas fonctionner correctement. Essayez de vérifier les mises à jour ou communiquez avec son concepteur."</string>
+ <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Cette application a été conçue pour une ancienne version d\'Android et pourrait ne pas fonctionner correctement. Essayez de vérifier les mises à jour ou communiquez avec son développeur."</string>
<string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Vérifier la présence de mises à jour"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"Vous avez de nouveaux messages"</string>
<string name="new_sms_notification_content" msgid="3197949934153460639">"Ouvrez l\'application de messagerie texte pour l\'afficher"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 425e29a..cc22d83 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -209,8 +209,8 @@
<string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, contactez l\'administrateur de votre organisation."</string>
<string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="personal_apps_suspension_title" msgid="7561416677884286600">"Activez votre profil pro"</string>
- <string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vos applications personnelles seront bloquées jusqu\'à ce que vous activiez votre profil professionnel"</string>
- <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Vos applications personnelles seront bloquées le <xliff:g id="DATE">%1$s</xliff:g> à <xliff:g id="TIME">%2$s</xliff:g>. Votre administrateur informatique ne vous autorise pas à désactiver votre profil professionnel pendant plus de <xliff:g id="NUMBER">%3$d</xliff:g> jours."</string>
+ <string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vos applis perso sont bloquées tant que vous n\'avez pas activé votre profil pro"</string>
+ <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Vos applis perso seront bloquées le <xliff:g id="DATE">%1$s</xliff:g> à <xliff:g id="TIME">%2$s</xliff:g>. Votre administrateur ne permet pas que votre profil pro reste désactivé pendant plus de <xliff:g id="NUMBER">%3$d</xliff:g> jours."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activer"</string>
<string name="me" msgid="6207584824693813140">"Moi"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Options de la tablette"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1869,7 +1873,7 @@
<string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"L\'économiseur de batterie active le thème sombre et limite ou désactive les activités en arrière-plan ainsi que certains effets visuels, fonctionnalités et connexions réseau."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"L\'économiseur de batterie active le thème sombre et limite ou désactive les activités en arrière-plan ainsi que certains effets visuels, fonctionnalités et connexions réseau."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Pour réduire la consommation des données, l\'Économiseur de données empêche certaines applis d\'envoyer ou de recevoir des données en arrière-plan. Les applis que vous utiliserez pourront toujours accéder aux données, mais le feront moins fréquemment. Par exemple, les images pourront ne pas s\'afficher tant que vous n\'aurez pas appuyé pas dessus."</string>
- <string name="data_saver_enable_title" msgid="7080620065745260137">"Activer l\'économiseur de données ?"</string>
+ <string name="data_saver_enable_title" msgid="7080620065745260137">"Activer l\'Économiseur de données ?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Activer"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
<item quantity="one">Pendant %1$d minute (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
@@ -1970,7 +1974,7 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"L\'application <xliff:g id="APP_NAME_0">%1$s</xliff:g> n\'est pas disponible pour le moment. Cette suspension est gérée par l\'application <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"En savoir plus"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Débloquer l\'application"</string>
- <string name="work_mode_off_title" msgid="961171256005852058">"Activer les applis pros ?"</string>
+ <string name="work_mode_off_title" msgid="961171256005852058">"Activer les applis pro ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Accéder à vos applis et notifications professionnelles"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activer"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Application non disponible"</string>
@@ -2070,7 +2074,7 @@
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> souhaite afficher des éléments de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Modifier"</string>
<string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Vibreur pour les appels et les notifications"</string>
- <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Sonnerie désactivée pour les appels et les notifications"</string>
+ <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Sons désactivés pour les appels et les notifications"</string>
<string name="notification_channel_system_changes" msgid="2462010596920209678">"Modifications du système"</string>
<string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ne pas déranger"</string>
<string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nouveau : Le mode Ne pas déranger masque les notifications"</string>
@@ -2157,7 +2161,7 @@
<string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"Impossible de partager ce contenu avec des applis personnelles"</string>
<string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"Impossible d\'ouvrir ce contenu avec des applis personnelles"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Profil professionnel en pause"</string>
- <string name="resolver_switch_on_work" msgid="463709043650610420">"Appuyer pour activer"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"Appuyez pour l\'activer"</string>
<string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Aucune appli professionnelle"</string>
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Aucune appli personnelle"</string>
<string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Ouvrir dans <xliff:g id="APP">%s</xliff:g> avec le profil personnel ?"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 54c6a6d..ba41c75 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -712,7 +712,7 @@
<string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Permite ao propietario vincularse á interface de nivel superior dun servizo de mensaxaría. As aplicacións normais non deberían necesitar este permiso."</string>
<string name="permlab_bindCarrierServices" msgid="2395596978626237474">"vincular aos servizos do operador"</string>
<string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Permite ao titular vincularse aos servizos do operador. As aplicacións normais non deberían necesitar este permiso."</string>
- <string name="permlab_access_notification_policy" msgid="5524112842876975537">"acceso ao modo Non molestar"</string>
+ <string name="permlab_access_notification_policy" msgid="5524112842876975537">"acceso a Non molestar"</string>
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite á aplicación ler e escribir a configuración do modo Non molestar."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar uso de permiso de vista"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite ao propietario iniciar o uso de permisos dunha aplicación. As aplicacións normais non deberían precisalo nunca."</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizado polo teu administrador"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado polo teu administrador"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Coa función Aforro de batería, actívase o tema escuro e restrínxense ou desactívanse a actividade en segundo plano, algúns efectos visuais e determinadas funcións e conexións de rede."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Coa función Aforro de batería, actívase o tema escuro e restrínxense ou desactívanse a actividade en segundo plano, algúns efectos visuais e determinadas funcións e conexións de rede."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Para contribuír a reducir o uso de datos, o aforro de datos impide que algunhas aplicacións envíen ou reciban datos en segundo plano. Cando esteas utilizando unha aplicación, esta poderá acceder aos datos, pero é posible que o faga con menos frecuencia. Por exemplo, poida que as imaxes non se mostren ata que as toques."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Queres activar o aforro de datos?"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 6db75a0..4157e1f 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"તમારા વ્યવસ્થાપક દ્વારા અપડેટ કરવામાં આવેલ છે"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"તમારા વ્યવસ્થાપક દ્વારા કાઢી નાખવામાં આવેલ છે"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ઓકે"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"બૅટરી સેવર ઘેરી થીમની સુવિધા ચાલુ કરે છે અને બૅકગ્રાઉન્ડ પ્રવૃત્તિ, અમુક વિઝ્યુઅલ ઇફેક્ટ, અમુક સુવિધાઓ અને કેટલાક નેટવર્ક કનેક્શન મર્યાદિત કે બંધ કરે છે."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"બૅટરી સેવર ઘેરી થીમની સુવિધા ચાલુ કરે છે અને બૅકગ્રાઉન્ડ પ્રવૃત્તિ, અમુક વિઝ્યુઅલ ઇફેક્ટ, અમુક સુવિધાઓ અને કેટલાક નેટવર્ક કનેક્શન મર્યાદિત કે બંધ કરે છે."</string>
<string name="data_saver_description" msgid="4995164271550590517">"ડેટા વપરાશને ઘટાડવામાં સહાય માટે, ડેટા સેવર કેટલીક ઍપને બૅકગ્રાઉન્ડમાં ડેટા મોકલવા અથવા પ્રાપ્ત કરવાથી અટકાવે છે. તમે હાલમાં ઉપયોગ કરી રહ્યાં છો તે ઍપ ડેટાને ઍક્સેસ કરી શકે છે, પરંતુ તે આ ક્યારેક જ કરી શકે છે. આનો અર્થ એ હોઈ શકે છે, ઉદાહરણ તરીકે, છબીઓ ત્યાં સુધી પ્રદર્શિત થશે નહીં જ્યાં સુધી તમે તેમને ટૅપ નહીં કરો."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ડેટા સેવર ચાલુ કરીએ?"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index b30fd30..6e8bd94 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -990,7 +990,7 @@
<string name="autofill_province" msgid="3676846437741893159">"प्रांत"</string>
<string name="autofill_postal_code" msgid="7034789388968295591">"डाक कोड"</string>
<string name="autofill_state" msgid="3341725337190434069">"राज्य"</string>
- <string name="autofill_zip_code" msgid="1315503730274962450">"ज़िप कोड"</string>
+ <string name="autofill_zip_code" msgid="1315503730274962450">"पिन कोड"</string>
<string name="autofill_county" msgid="7781382735643492173">"काउंटी"</string>
<string name="autofill_island" msgid="5367139008536593734">"द्वीप"</string>
<string name="autofill_district" msgid="6428712062213557327">"जिला"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"आपके व्यवस्थापक ने अपडेट किया है"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"आपके व्यवस्थापक ने हटा दिया है"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ठीक है"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"बैटरी सेवर, गहरे रंग वाली थीम को चालू करता है. साथ ही, यह बैकग्राउंड की गतिविधि, कुछ विज़ुअल इफ़ेक्ट, कुछ खास सुविधाओं, और कुछ खास तरह के इंटरनेट कनेक्शन इस्तेमाल करने से डिवाइस को रोकता है या इन्हें बंद कर देता है."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"बैटरी सेवर, गहरे रंग वाली थीम को चालू करता है. साथ ही, यह बैकग्राउंड की गतिविधि, कुछ विज़ुअल इफ़ेक्ट, कुछ खास सुविधाओं, और कुछ खास तरह के इंटरनेट कनेक्शन इस्तेमाल करने से डिवाइस को रोकता है या इन्हें बंद कर देता है."</string>
<string name="data_saver_description" msgid="4995164271550590517">"डेटा खर्च को कम करने के लिए, डेटा बचाने की सेटिंग कुछ ऐप्लिकेशन को बैकग्राउंड में डेटा भेजने या डेटा पाने से रोकती है. फ़िलहाल, आप जिस ऐप्लिकेशन का इस्तेमाल कर रहे हैं वह डेटा ऐक्सेस कर सकता है, लेकिन ऐसा कभी-कभी ही हो पाएगा. उदाहरण के लिए, इमेज तब तक दिखाई नहीं देंगी, जब तक आप उन पर टैप नहीं करते."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"डेटा बचाने की सेटिंग चालू करें?"</string>
@@ -2093,7 +2096,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"चालू करें"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"बंद करें"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ज़्यादा जानें"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12 में, ज़रूरत के हिसाब से सूचनाएं पाने की सुविधा की जगह अब \'बेहतर सूचनाएं\' सुविधा काम करेगी. यह सुविधा आपको कार्रवाइयों और जवाबों के सुझाव दिखाती है. साथ ही, आपके डिवाइस पर मिलने वाली सूचनाओं को व्यवस्थित करती है.\n\n\'बेहतर सूचनाएं\' सुविधा, डिवाइस पर मिलने वाली सभी सूचनाओं का कॉन्टेंट ऐक्सेस कर सकती है. इसमें आपकी निजी जानकारी, जैसे कि संपर्कों के नाम और मैसेज शामिल हैं. यह सुविधा, सूचनाओं को रद्द कर सकती है या उनका जवाब भी दे सकती है, जैसे कि फ़ोन कॉल का जवाब देना और \'परेशान न करें\' को कंट्रोल करना."</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12 में, ज़रूरत के हिसाब से सूचनाएं पाने की सुविधा की जगह अब \'बेहतर सूचनाएं\' सुविधा काम करेगी. यह सुविधा आपको कार्रवाइयों और जवाबों के सुझाव दिखाती है. साथ ही, आपके डिवाइस पर मिलने वाली सूचनाओं को व्यवस्थित करती है.\n\n\'बेहतर सूचनाएं\' सुविधा, डिवाइस पर मिलने वाली सभी सूचनाओं का कॉन्टेंट ऐक्सेस कर सकती है. इसमें आपकी निजी जानकारी, जैसे कि संपर्कों के नाम और मैसेज शामिल हैं. यह सुविधा, सूचनाओं को खारिज कर सकती है या उनका जवाब भी दे सकती है, जैसे कि फ़ोन कॉल का जवाब देना और \'परेशान न करें\' को कंट्रोल करना."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"रूटीन मोड जानकारी की सूचना"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"बैटरी आम तौर पर जितने समय चलती है, उससे पहले खत्म हो सकती है"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"बैटरी लाइफ़ बढ़ाने के लिए \'बैटरी सेवर\' चालू हो गया है"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index c430c4a..98acb89 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1478,6 +1478,10 @@
<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="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>
@@ -2190,7 +2194,7 @@
<string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"Taj se sadržaj ne može otvoriti pomoću poslovnih aplikacija"</string>
<string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"Taj se sadržaj ne može dijeliti pomoću osobnih aplikacija"</string>
<string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"Taj se sadržaj ne može otvoriti pomoću osobnih aplikacija"</string>
- <string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Poslovni je profil pauziran"</string>
+ <string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Poslovni profil je pauziran"</string>
<string name="resolver_switch_on_work" msgid="463709043650610420">"Dodirnite da biste uključili"</string>
<string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Poslovne aplikacije nisu dostupne"</string>
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Osobne aplikacije nisu dostupne"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 108ce33..58c3875 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"A rendszergazda által frissítve"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"A rendszergazda által törölve"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Az Akkumulátorkímélő mód bekapcsolja a Sötét témát, és korlátozza vagy kikapcsolja a háttérbeli tevékenységeket, valamint bizonyos vizuális effekteket, funkciókat és hálózati kapcsolatokat."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Az Akkumulátorkímélő mód bekapcsolja a Sötét témát, és korlátozza vagy kikapcsolja a háttérbeli tevékenységeket, valamint bizonyos vizuális effekteket, funkciókat és hálózati kapcsolatokat."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Az adatforgalom csökkentése érdekében az Adatforgalom-csökkentő megakadályozza, hogy egyes alkalmazások adatokat küldjenek vagy fogadjanak a háttérben. Az Ön által jelenleg használt alkalmazások hozzáférhetnek az adatokhoz, de csak ritkábban. Ez például azt jelentheti, hogy a képek csak rákoppintás után jelennek meg."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Bekapcsolja az Adatforgalom-csökkentőt?"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 863948f..860dcf9 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Թարմացվել է ձեր ադմինիստրատորի կողմից"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Ջնջվել է ձեր ադմինիստրատորի կողմից"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Եղավ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"«Մարտկոցի տնտեսում» գործառույթը միացնում է մուգ թեման և անջատում կամ սահմանափակում է աշխատանքը ֆոնային ռեժիմում, որոշ վիզուալ էֆեկտներ, ցանցային միացումներ և այլ գործառույթներ։"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"«Մարտկոցի տնտեսում» գործառույթը միացնում է մուգ թեման և անջատում կամ սահմանափակում է աշխատանքը ֆոնային ռեժիմում, որոշ վիզուալ էֆեկտներ, ցանցային միացումներ և այլ գործառույթներ։"</string>
<string name="data_saver_description" msgid="4995164271550590517">"Թրաֆիկի տնտեսման ռեժիմում որոշ հավելվածների համար տվյալների ֆոնային փոխանցումն անջատված է։ Հավելվածը, որն օգտագործում եք, կարող է տվյալներ փոխանցել և ստանալ, սակայն ոչ այնքան հաճախ: Օրինակ՝ պատկերները կցուցադրվեն միայն դրանց վրա սեղմելուց հետո։"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Միացնե՞լ թրաֆիկի տնտեսումը"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 489d3cc..b8649c1 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Diupdate oleh admin Anda"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Dihapus oleh admin Anda"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Oke"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Penghemat Baterai akan mengaktifkan Tema gelap dan membatasi atau menonaktifkan aktivitas latar belakang, beberapa efek visual, fitur tertentu, dan beberapa koneksi jaringan."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Penghemat Baterai akan mengaktifkan Tema gelap dan membatasi atau menonaktifkan aktivitas latar belakang, beberapa efek visual, fitur tertentu, dan beberapa koneksi jaringan."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Untuk membantu mengurangi penggunaan data, Penghemat Data mencegah beberapa aplikasi mengirim atau menerima data di latar belakang. Aplikasi yang sedang digunakan dapat mengakses data, tetapi frekuensinya agak lebih jarang. Misalnya saja, gambar hanya akan ditampilkan setelah diketuk."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Aktifkan Penghemat Data?"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index abc9138..0cf1eff 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -815,7 +815,7 @@
<string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string>
<string name="eventTypeCustom" msgid="3257367158986466481">"Sérsniðið"</string>
<string name="eventTypeBirthday" msgid="7770026752793912283">"Afmæli"</string>
- <string name="eventTypeAnniversary" msgid="4684702412407916888">"Brúðkaupsafmæli"</string>
+ <string name="eventTypeAnniversary" msgid="4684702412407916888">"Afmæli"</string>
<string name="eventTypeOther" msgid="530671238533887997">"Annað"</string>
<string name="emailTypeCustom" msgid="1809435350482181786">"Sérsniðið"</string>
<string name="emailTypeHome" msgid="1597116303154775999">"Heima"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Kerfisstjóri uppfærði"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Kerfisstjóri eyddi"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Í lagi"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Rafhlöðusparnaður kveikir á dökku þema og takmarkar eða slekkur á bakgrunnsvirkni, sumum myndáhrifum, tilteknum eiginleikum og sumum nettengingum."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Rafhlöðusparnaður kveikir á dökku þema og takmarkar eða slekkur á bakgrunnsvirkni, sumum áhrifum, tilteknum eiginleikum og sumum nettengingum."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Gagnasparnaður getur hjálpað til við að draga úr gagnanotkun með því að hindra forrit í að senda eða sækja gögn í bakgrunni. Forrit sem er í notkun getur náð í gögn, en gerir það kannski sjaldnar. Niðurstaðan getur verið að myndir eru ekki birtar fyrr en þú ýtir á þær, svo dæmi sé tekið."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Kveikja á gagnasparnaði?"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 12ee90e..29dbd76 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<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>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <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="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>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 0a3ef05..dc43bde 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -865,7 +865,7 @@
<string name="relationTypeSister" msgid="3721676005094140671">"אחות"</string>
<string name="relationTypeSpouse" msgid="6916682664436031703">"בן/בת זוג"</string>
<string name="sipAddressTypeCustom" msgid="6283889809842649336">"בהתאמה אישית"</string>
- <string name="sipAddressTypeHome" msgid="5918441930656878367">"דף הבית"</string>
+ <string name="sipAddressTypeHome" msgid="5918441930656878367">"בית"</string>
<string name="sipAddressTypeWork" msgid="7873967986701216770">"עבודה"</string>
<string name="sipAddressTypeOther" msgid="6317012577345187275">"אחר"</string>
<string name="quick_contacts_not_available" msgid="1262709196045052223">"לא נמצאה אפליקציה להצגת התוכן הזה."</string>
@@ -1498,6 +1498,10 @@
<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="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>
@@ -1912,8 +1916,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"עודכנה על ידי מנהל המערכת"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"נמחקה על ידי מנהל המערכת"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"אישור"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"התכונה \'חיסכון בסוללה\' מפעילה עיצוב כהה ומגבילה או מכבה פעילות ברקע, חלק מהאפקטים החזותיים, תכונות מסוימות וחלק מהחיבורים לרשתות."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"התכונה \'חיסכון בסוללה\' מפעילה עיצוב כהה ומגבילה או מכבה פעילות ברקע, חלק מהאפקטים החזותיים, תכונות מסוימות וחלק מהחיבורים לרשתות."</string>
<string name="data_saver_description" msgid="4995164271550590517">"כדי לסייע בהפחתת השימוש בנתונים, חוסך הנתונים (Data Saver) מונע מאפליקציות מסוימות לשלוח או לקבל נתונים ברקע. אפליקציות שבהן נעשה שימוש כרגע יכולות לגשת לנתונים, אבל בתדירות נמוכה יותר. המשמעות היא, למשל, שתמונות יוצגו רק לאחר שמקישים עליהן."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"להפעיל את חוסך הנתונים?"</string>
@@ -2036,7 +2039,7 @@
<string name="app_suspended_more_details" msgid="211260942831587014">"מידע נוסף"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ביטול ההשהיה של האפליקציה"</string>
<string name="work_mode_off_title" msgid="961171256005852058">"להפעיל את האפליקציות לעבודה?"</string>
- <string name="work_mode_off_message" msgid="7319580997683623309">"קבלת גישה להתראות ולאפליקציות לעבודה"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"קבלת גישה להתראות ולאפליקציות בפרופיל העבודה"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"הפעלה"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"האפליקציה לא זמינה"</string>
<string name="app_blocked_message" msgid="542972921087873023">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לא זמינה בשלב זה."</string>
@@ -2226,7 +2229,7 @@
<string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"אי אפשר לשתף את התוכן הזה עם אפליקציות לשימוש אישי"</string>
<string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"אי אפשר לפתוח את התוכן הזה באמצעות אפליקציות לשימוש אישי"</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"פרופיל העבודה מושהה"</string>
- <string name="resolver_switch_on_work" msgid="463709043650610420">"יש להקיש כדי להפעיל"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"יש להקיש כדי להפעיל את פרופיל העבודה"</string>
<string name="resolver_no_work_apps_available" msgid="3298291360133337270">"אין אפליקציות לעבודה"</string>
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"אין אפליקציות לשימוש אישי"</string>
<string name="miniresolver_open_in_personal" msgid="2937599899213467617">"לפתוח באפליקציה <xliff:g id="APP">%s</xliff:g> בפרופיל האישי?"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 9f44655..b282b44 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"管理者により更新されています"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"管理者により削除されています"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"バッテリー セーバーを有効にすると、ダークテーマが ON になり、バックグラウンド アクティビティ、一部の視覚効果、特定の機能、一部のネットワーク接続が制限されるか OFF になります。"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"バッテリー セーバーを有効にすると、ダークテーマが ON になり、バックグラウンド アクティビティ、一部の視覚効果、特定の機能、一部のネットワーク接続が制限されるか OFF になります。"</string>
<string name="data_saver_description" msgid="4995164271550590517">"データセーバーは、一部のアプリによるバックグラウンドでのデータ送受信を停止することでデータ使用量を抑制します。使用中のアプリからデータを送受信することはできますが、その頻度は低くなる場合があります。この影響として、たとえば画像はタップしないと表示されないようになります。"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"データセーバーを ON にしますか?"</string>
@@ -1972,7 +1975,7 @@
<string name="app_suspended_more_details" msgid="211260942831587014">"詳細"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"アプリの一時停止を解除"</string>
<string name="work_mode_off_title" msgid="961171256005852058">"仕事用アプリを ON にしますか?"</string>
- <string name="work_mode_off_message" msgid="7319580997683623309">"仕事用のアプリや通知を利用する"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"仕事用のアプリを利用し、通知を受け取れるようになります"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ON にする"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"アプリの利用不可"</string>
<string name="app_blocked_message" msgid="542972921087873023">"現在 <xliff:g id="APP_NAME">%1$s</xliff:g> はご利用になれません。"</string>
@@ -2071,7 +2074,7 @@
<string name="slices_permission_request" msgid="3677129866636153406">"「<xliff:g id="APP_0">%1$s</xliff:g>」が「<xliff:g id="APP_2">%2$s</xliff:g>」のスライスの表示をリクエストしています"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"編集"</string>
<string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"着信や通知をバイブレーションで知らせます"</string>
- <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"着信音と通知音をミュートします"</string>
+ <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"着信音と通知音が鳴りません"</string>
<string name="notification_channel_system_changes" msgid="2462010596920209678">"システムの変更"</string>
<string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"サイレント モード"</string>
<string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"新機能: サイレント モードでは通知が非表示になります"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index af21c11..dbc92da 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"განახლებულია თქვენი ადმინისტრატორის მიერ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"წაიშალა თქვენი ადმინისტრატორის მიერ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"კარგი"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ბატარეის დამზოგი ჩართავს მუქ თემას და შეზღუდავს ან გამორთავს ფონურ აქტივობას, ზოგიერთ ვიზუალურ ეფექტს, გარკვეულ ფუნქციებსა და ზოგიერთ ქსელთან კავშირს."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"ბატარეის დამზოგი ჩართავს მუქ თემას და შეზღუდავს ან გამორთავს ფონურ აქტივობას, ზოგიერთ ვიზუალურ ეფექტს, გარკვეულ ფუნქციებსა და ზოგიერთ ქსელთან კავშირს."</string>
<string name="data_saver_description" msgid="4995164271550590517">"მობილური ინტერნეტის მოხმარების შემცირების მიზნით, მონაცემთა დამზოგველი ზოგიერთ აპს ფონურ რეჟიმში მონაცემთა გაგზავნასა და მიღებას შეუზღუდავს. თქვენ მიერ ამჟამად გამოყენებული აპი მაინც შეძლებს მობილურ ინტერნეტზე წვდომას, თუმცა ამას ნაკლები სიხშირით განახორციელებს. ეს ნიშნავს, რომ, მაგალითად, სურათები არ გამოჩნდება მანამ, სანამ მათ საგანგებოდ არ შეეხებით."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ჩაირთოს მონაცემთა დამზოგველი?"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 6d24f8f..6d3429e 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -246,7 +246,7 @@
<string name="global_action_lock" msgid="6949357274257655383">"Экранды құлыптау"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Өшіру"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"Қуат"</string>
- <string name="global_action_restart" msgid="4678451019561687074">"Қайта қосу"</string>
+ <string name="global_action_restart" msgid="4678451019561687074">"Өшіріп қосу"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Төтенше жағдай"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Вирус туралы хабарлау"</string>
<string name="global_action_logout" msgid="6093581310002476511">"Сеансты аяқтау"</string>
@@ -442,7 +442,7 @@
<string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"болжалды орналасқан жер туралы ақпаратқа тек ашық экранда кіру"</string>
<string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Бұл қолданба пайдаланылып жатқанда, ол Локация қызметтерінен болжалды геодерегіңізді ала алады. Геодеректі алу үшін құрылғыңызға арналған Локация қызметтері қосулы тұруы керек."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"геодеректерді фондық режимде пайдалану"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Бұл қолданба пайдаланылмайтын кезде де, ол геодеректі кез келген уақытта пайдалана алады."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Бұл қолданба кез келген уақытта (пайдаланылмайтын кезде де) локацияны пайдалана алады."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"аудио параметрлерін өзгерту"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Қолданбаға дыбыс қаттылығы және аудио шығыс үндеткішін таңдау сияқты жаһандық аудио параметрлерін өзгерту мүмкіндігін береді."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"аудио жазу"</string>
@@ -971,7 +971,7 @@
<string name="factorytest_failed" msgid="3190979160945298006">"Зауыт тесті орындалмады."</string>
<string name="factorytest_not_system" msgid="5658160199925519869">"ЗАУЫТ_TEСТІ әрекетінің қолдауы жүйеде/қолданбада орнатылған жинақтар үшін ғана ұсынылған."</string>
<string name="factorytest_no_action" msgid="339252838115675515">"ЗАУЫТ_TEСТІ әрекетін жабдықтайтын жинақ табылмады."</string>
- <string name="factorytest_reboot" msgid="2050147445567257365">"Қайта қосу"</string>
+ <string name="factorytest_reboot" msgid="2050147445567257365">"Өшіріп қосу"</string>
<string name="js_dialog_title" msgid="7464775045615023241">"\"<xliff:g id="TITLE">%s</xliff:g>\" парағында былай делінген:"</string>
<string name="js_dialog_title_default" msgid="3769524569903332476">"JavaScript"</string>
<string name="js_dialog_before_unload_title" msgid="7012587995876771246">"Жылжуды растау"</string>
@@ -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 OЖ-бен үйлеспейді және дұрыс жұмыс істемеуі ықтимал. Қолданбаның жаңартылған нұсқасы қолжетімді болуы мүмкін."</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> процесі) өзі қолданған StrictMode саясатын бұзды."</string>
<string name="smv_process" msgid="1398801497130695446">"<xliff:g id="PROCESS">%1$s</xliff:g> үрдісі өздігінен күшіне енген ҚатаңРежим ережесін бұзды."</string>
<string name="android_upgrading_title" product="default" msgid="7279077384220829683">"Телефон жаңартылуда…"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1473,7 +1477,7 @@
<string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"Бұл өтініштің орындалуын қалайсыз ба?"</string>
<string name="grant_permissions_header_text" msgid="3420736827804657201">"Кіру өтініші"</string>
<string name="allow" msgid="6195617008611933762">"Рұқсат беру"</string>
- <string name="deny" msgid="6632259981847676572">"Бас тарту"</string>
+ <string name="deny" msgid="6632259981847676572">"Тыйым салу"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"Рұқсат өтінілді"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Рұқсат \nесептік жазба үшін <xliff:g id="ACCOUNT">%s</xliff:g> өтінілді."</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"Осы қолданбаны жұмыс профиліңізден тыс пайдаланып жатырсыз"</string>
@@ -1830,7 +1834,7 @@
<string name="reason_unknown" msgid="5599739807581133337">"белгісіз"</string>
<string name="reason_service_unavailable" msgid="5288405248063804713">"Принтер қызметі қосылмаған"</string>
<string name="print_service_installed_title" msgid="6134880817336942482">"<xliff:g id="NAME">%s</xliff:g> қызметі орнатылды"</string>
- <string name="print_service_installed_message" msgid="7005672469916968131">"Қосу үшін түрту"</string>
+ <string name="print_service_installed_message" msgid="7005672469916968131">"Қосу үшін түртіңіз"</string>
<string name="restr_pin_enter_admin_pin" msgid="1199419462726962697">"Әкімшінің PIN кодын енгізіңіз"</string>
<string name="restr_pin_enter_pin" msgid="373139384161304555">"PIN енгізу"</string>
<string name="restr_pin_incorrect" msgid="3861383632940852496">"Дұрыс емес"</string>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Әкімші жаңартқан"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Әкімші жойған"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Жарайды"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Батареяны үнемдеу режимі қараңғы тақырыпты іске қосады және фондық әрекеттерге, кейбір визуалдық әсерлерге, белгілі бір функциялар мен кейбір желі байланыстарына шектеу қояды немесе оларды өшіреді."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Батареяны үнемдеу режимі қараңғы тақырыпты іске қосады және фондық әрекеттерге, кейбір визуалдық әсерлерге, белгілі бір функциялар мен кейбір желі байланыстарына шектеу қояды немесе оларды өшіреді."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Дерек шығынын азайту үшін Трафикті үнемдеу режимінде кейбір қолданбаларға деректі фондық режимде жіберуге және алуға тыйым салынады. Ашық тұрған қолданба деректі шектеулі шамада пайдаланады (мысалы, кескіндер оларды түрткенге дейін көрсетілмейді)."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Трафикті үнемдеу режимі қосылсын ба?"</string>
@@ -1972,12 +1975,12 @@
<string name="app_suspended_more_details" msgid="211260942831587014">"Толығырақ"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Қолданбаны қайта қосу"</string>
<string name="work_mode_off_title" msgid="961171256005852058">"Жұмыс қолданбаларын қосасыз ба?"</string>
- <string name="work_mode_off_message" msgid="7319580997683623309">"Жұмыс қолданбалары мен хабарландыруларына рұқсат алу"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Жұмыс қолданбалары мен хабарландыруларына қол жеткізесіз."</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Қосу"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Қолданба қолжетімді емес"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> қазір қолжетімді емес."</string>
<string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Қолданба Android жүйесінің ескі нұсқасына арналған және дұрыс жұмыс істемеуі мүмкін. Жаңартылған нұсқаны тексеріңіз немесе әзірлеушіге хабарласыңыз."</string>
- <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Жаңа нұсқасының бар-жоғын тексеру"</string>
+ <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Жаңарту бар-жоғын тексеру"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"Сізде жаңа хабарлар бар"</string>
<string name="new_sms_notification_content" msgid="3197949934153460639">"Көру үшін SMS қолданбасын ашыңыз"</string>
<string name="profile_encrypted_title" msgid="9001208667521266472">"Кейбір функциялар істемеуі мүмкін."</string>
@@ -2158,7 +2161,7 @@
<string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"Бұл мазмұнды жеке қолданбалармен бөлісу мүмкін емес."</string>
<string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"Бұл мазмұнды жеке қолданбалармен ашу мүмкін емес."</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Жұмыс профилі кідіртілді."</string>
- <string name="resolver_switch_on_work" msgid="463709043650610420">"Қосу үшін түрту"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"Қосу үшін түртіңіз"</string>
<string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Жұмыс қолданбалары жоқ."</string>
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Жеке қолданбалар жоқ."</string>
<string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Жеке профильдегі <xliff:g id="APP">%s</xliff:g> қолданбасында ашу керек пе?"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 3a4117d..19aa889 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ធ្វើបច្ចុប្បន្នភាពដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"លុបដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"យល់ព្រម"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"មុខងារសន្សំថ្មបើករចនាប័ទ្មងងឹត និងដាក់កំហិត ឬបិទសកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពលរូបភាពមួយចំនួន មុខងារជាក់លាក់ និងការតភ្ជាប់បណ្ដាញមួយចំនួន។"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"មុខងារសន្សំថ្មបើករចនាប័ទ្មងងឹត និងដាក់កំហិត ឬបិទសកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពលរូបភាពមួយចំនួន មុខងារជាក់លាក់ និងការតភ្ជាប់បណ្ដាញមួយចំនួន។"</string>
<string name="data_saver_description" msgid="4995164271550590517">"ដើម្បីជួយកាត់បន្ថយការប្រើប្រាស់ទិន្នន័យ កម្មវិធីសន្សំសំចៃទិន្នន័យរារាំងកម្មវិធីមួយចំនួនមិនឲ្យបញ្ជូន ឬទទួលទិន្នន័យនៅផ្ទៃខាងក្រោយទេ។ កម្មវិធីដែលអ្នកកំពុងប្រើនាពេលបច្ចុប្បន្នអាចចូលប្រើប្រាស់ទិន្នន័យបាន ប៉ុន្តែអាចនឹងមិនញឹកញាប់ដូចមុនទេ។ ឧទាហរណ៍ រូបភាពមិនបង្ហាញទេ លុះត្រាតែអ្នកប៉ះរូបភាពទាំងនោះ។"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"បើកកម្មវិធីសន្សំសំចៃទិន្នន័យ?"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 9a39c29..a3e0ca5 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,9 +1870,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಅಪ್ಡೇಟ್ ಮಾಡಲ್ಪಟ್ಟಿದೆ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಅಳಿಸಿದ್ದಾರೆ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ಸರಿ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
- <string name="battery_saver_description" msgid="8518809702138617167">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಡಾರ್ಕ್ ಥೀಮ್ ಅನ್ನು ಆನ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ಹಿನ್ನೆಲೆ ಚಟುವಟಿಕೆ, ಕೆಲವು ವಿಷುವಲ್ ಎಫೆಕ್ಟ್ಗಳು, ಕೆಲವು ವೈಶಿಷ್ಟ್ಯಗಳು ಮತ್ತು ಇತರ ನೆಟ್ವರ್ಕ್ ಸಂಪರ್ಕಗಳನ್ನು ಮಿತಿಗೊಳಿಸುತ್ತದೆ ಅಥವಾ ಆಫ್ ಮಾಡುತ್ತದೆ."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ಬ್ಯಾಟರಿ ಸೇವರ್, ಡಾರ್ಕ್ ಥೀಮ್ ಅನ್ನು ಆನ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ಹಿನ್ನೆಲೆ ಚಟುವಟಿಕೆ, ಕೆಲವು ವಿಷುವಲ್ ಎಫೆಕ್ಟ್ಗಳು, ಕೆಲವು ಫೀಚರ್ಗಳು ಮತ್ತು ಇತರ ನೆಟ್ವರ್ಕ್ ಸಂಪರ್ಕಗಳನ್ನು ಮಿತಿಗೊಳಿಸುತ್ತದೆ ಅಥವಾ ಆಫ್ ಮಾಡುತ್ತದೆ."</string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಡಾರ್ಕ್ ಥೀಮ್ ಅನ್ನು ಆನ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ಹಿನ್ನೆಲೆ ಚಟುವಟಿಕೆ, ಕೆಲವು ವಿಷುವಲ್ ಎಫೆಕ್ಟ್ಗಳು, ಕೆಲವು ಫೀಚರ್ಗಳು ಮತ್ತು ಇತರ ನೆಟ್ವರ್ಕ್ ಸಂಪರ್ಕಗಳನ್ನು ಮಿತಿಗೊಳಿಸುತ್ತದೆ ಅಥವಾ ಆಫ್ ಮಾಡುತ್ತದೆ."</string>
<string name="data_saver_description" msgid="4995164271550590517">"ಡೇಟಾ ಬಳಕೆ ಕಡಿಮೆ ಮಾಡುವ ನಿಟ್ಟಿನಲ್ಲಿ, ಡೇಟಾ ಸೇವರ್ ಕೆಲವು ಅಪ್ಲಿಕೇಶನ್ಗಳು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಡೇಟಾ ಕಳುಹಿಸುವುದನ್ನು ಅಥವಾ ಸ್ವೀಕರಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ. ನೀವು ಪ್ರಸ್ತುತ ಬಳಸುತ್ತಿರುವ ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು ಆದರೆ ಪದೇ ಪದೇ ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ. ಇದರರ್ಥ, ಉದಾಹರಣೆಗೆ, ನೀವು ಅವುಗಳನ್ನು ಟ್ಯಾಪ್ ಮಾಡುವವರೆಗೆ ಆ ಚಿತ್ರಗಳು ಕಾಣಿಸಿಕೊಳ್ಳುವುದಿಲ್ಲ."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ಡೇಟಾ ಸೇವರ್ ಆನ್ ಮಾಡಬೇಕೇ?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"ಆನ್ ಮಾಡಿ"</string>
@@ -1989,7 +1992,7 @@
<string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> ಗೆ ಪಿನ್ ಮಾಡಿ"</string>
<string name="unpin_target" msgid="3963318576590204447">"ಅನ್ಪಿನ್"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> ಅನ್ನು ಅನ್ಪಿನ್ ಮಾಡಿ"</string>
- <string name="app_info" msgid="6113278084877079851">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
+ <string name="app_info" msgid="6113278084877079851">"ಆ್ಯಪ್ ಮಾಹಿತಿ"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ಡೆಮೋ ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ..."</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"ಸಾಧನ ಮರುಹೊಂದಿಸಲಾಗುತ್ತಿದೆ..."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 86d49cd..4c1691b 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"관리자에 의해 업데이트되었습니다."</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"관리자에 의해 삭제되었습니다."</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"확인"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"절전 기능은 어두운 테마를 사용 설정하고 백그라운드 활동, 일부 시각 효과, 특정 기능 및 일부 네트워크 연결을 제한하거나 사용 중지합니다."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"절전 기능은 어두운 테마를 사용 설정하고 백그라운드 활동, 일부 시각 효과, 특정 기능 및 일부 네트워크 연결을 제한하거나 사용 중지합니다."</string>
<string name="data_saver_description" msgid="4995164271550590517">"데이터 사용량을 줄이기 위해 데이터 절약 모드는 일부 앱이 백그라운드에서 데이터를 전송하거나 수신하지 못하도록 합니다. 현재 사용 중인 앱에서 데이터에 액세스할 수 있지만 빈도가 줄어듭니다. 예를 들면, 이미지를 탭하기 전에는 이미지가 표시되지 않습니다."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"데이터 절약 모드를 사용 설정하시겠습니까?"</string>
@@ -2158,7 +2161,7 @@
<string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"이 콘텐츠는 개인 앱을 통해 공유할 수 없습니다."</string>
<string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"이 콘텐츠는 개인 앱으로 열 수 없습니다."</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"직장 프로필이 일시중지됨"</string>
- <string name="resolver_switch_on_work" msgid="463709043650610420">"탭하여 사용"</string>
+ <string name="resolver_switch_on_work" msgid="463709043650610420">"탭하여 사용 설정"</string>
<string name="resolver_no_work_apps_available" msgid="3298291360133337270">"직장 앱 없음"</string>
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"개인 앱 없음"</string>
<string name="miniresolver_open_in_personal" msgid="2937599899213467617">"개인 프로필의 <xliff:g id="APP">%s</xliff:g>에서 여시겠습니까?"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 67c8bb7..66ec9aa 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1259,7 +1259,7 @@
<string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Экран өчүрүлсүнбү?"</string>
<string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Манжаңыздын изин жөндөп жатканда күйгүзүү/өчүрүү баскычын басып алдыңыз.\n\nБул адатта экранды өчүрөт."</string>
<string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Өчүрүү"</string>
- <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Жокко чыгаруу"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Жок"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> иштеп жатат"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Оюнга кайтуу үчүн таптаңыз"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Оюн тандоо"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1683,10 +1687,10 @@
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ыкчам иштетесизби?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Атайын мүмкүнчүлүктөр функциясын пайдалануу үчүн ал күйгүзүлгөндө, үндү катуулатып/акырындаткан эки баскычты тең 3 секунддай коё бербей басып туруңуз."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Атайын мүмкүнчүлүктөрдүн ыкчам баскычын иштетесизби?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Атайын мүмкүнчүлүктөр функциясын иштетүү үчүн, үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nУчурдагы функциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТандалган функцияларды өзгөртүү үчүн Жөндөөлөр > Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Атайын мүмкүнчүлүктөр функциясын иштетүү үчүн үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nУчурдагы функциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТандалган функцияларды өзгөртүү үчүн Жөндөөлөр > Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> ыкчам баскычын иштетесизби?"</string>
- <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"<xliff:g id="SERVICE">%1$s</xliff:g> кызматын иштетүү үчүн, үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nБаскычтардын ушул айкалышын башка функцияга дайындоо үчүн, Жөндөөлөр > Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
+ <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"<xliff:g id="SERVICE">%1$s</xliff:g> кызматын иштетүү үчүн үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nБаскычтардын ушул айкалышын башка функцияга дайындоо үчүн, Жөндөөлөр > Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ооба"</string>
<string name="accessibility_shortcut_off" msgid="3651336255403648739">"Жок"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"КҮЙҮК"</string>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Администраторуңуз жаңыртып койгон"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Администраторуңуз жок кылып салган"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ЖАРАЙТ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Батареяны үнөмдөгүч режиминде Караңгы тема күйгүзүлүп, фондогу аракеттер, айрым визуалдык эффекттер, белгилүү бир функциялар жана айрым тармакка туташуулар чектелип же өчүрүлөт."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Батареяны үнөмдөгүч режиминде Караңгы тема күйгүзүлүп, фондогу аракеттер, айрым визуалдык эффекттер, белгилүү бир функциялар жана айрым тармакка туташуулар чектелип же өчүрүлөт."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Трафикти үнөмдөө режиминде айрым колдонмолор маалыматтарды фондо өткөрө алышпайт. Учурда сиз пайдаланып жаткан колдонмо маалыматтарды жөнөтүп/ала алат, бирок адаттагыдан азыраак өткөргөндүктөн, анын айрым функциялары талаптагыдай иштебей коюшу мүмкүн. Мисалы, сүрөттөр басылмайынча жүктөлбөйт."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Трафикти үнөмдөө режимин иштетесизби?"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 1ff849c..fd83eda 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ຖືກອັບໂຫລດໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ຖືກລຶບອອກໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ຕົກລົງ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ຕົວປະຢັດແບັດເຕີຣີຈະເປີດໃຊ້ຮູບແບບສີສັນມືດ ແລະ ຈຳກັດ ຫຼື ປິດການເຄື່ອນໄຫວໃນພື້ນຫຼັງ, ເອັບເຟັກທາງພາບຈຳນວນໜຶ່ງ, ຄຸນສົມບັດບາງຢ່າງ ແລະ ການເຊື່ອມຕໍ່ເຄືອຂ່າຍບາງອັນ."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"ຕົວປະຢັດແບັດເຕີຣີຈະເປີດໃຊ້ຮູບແບບສີສັນມືດ ແລະ ຈຳກັດ ຫຼື ປິດການເຄື່ອນໄຫວໃນພື້ນຫຼັງ, ເອັບເຟັກທາງພາບຈຳນວນໜຶ່ງ, ຄຸນສົມບັດບາງຢ່າງ ແລະ ການເຊື່ອມຕໍ່ເຄືອຂ່າຍບາງອັນ."</string>
<string name="data_saver_description" msgid="4995164271550590517">"ເພື່ອຊ່ວຍຫຼຸດຜ່ອນການນຳໃຊ້ຂໍ້ມູນ, ຕົວປະຢັດອິນເຕີເນັດຈະປ້ອງກັນບໍ່ໃຫ້ບາງແອັບສົ່ງ ຫຼື ຮັບຂໍ້ມູນໃນພື້ນຫຼັງ. ແອັບໃດໜຶ່ງທີ່ທ່ານກຳລັງໃຊ້ຢູ່ຈະສາມາດເຂົ້າເຖິງຂໍ້ມູນໄດ້ ແຕ່ອາດເຂົ້າເຖິງໄດ້ຖີ່ໜ້ອຍລົງ. ນີ້ອາດໝາຍຄວາມວ່າ ຮູບພາບຕ່າງໆອາດບໍ່ສະແດງຈົນກວ່າທ່ານຈະແຕະໃສ່ກ່ອນ."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ເປີດຕົວປະຢັດອິນເຕີເນັດບໍ?"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 9a97d9cc..ca43ce7 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1498,6 +1498,10 @@
<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="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>
@@ -2215,7 +2219,7 @@
<string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Pokalbis"</string>
<string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Grupės pokalbis"</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">"Asmeninė"</string>
+ <string name="resolver_personal_tab" msgid="2051260504014442073">"Asmeninis"</string>
<string name="resolver_work_tab" msgid="2690019516263167035">"Darbo"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Asmeninė peržiūra"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Darbo peržiūra"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 56e89d0..47094a4 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1478,6 +1478,10 @@
<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="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>
@@ -1889,8 +1893,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Atjaunināja administrators"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Dzēsa administrators"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Labi"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Akumulatora enerģijas taupīšanas režīmā tiek ieslēgts tumšais motīvs un tiek ierobežotas vai izslēgtas darbības fonā, daži vizuālie efekti, noteiktas funkcijas un noteikti tīkla savienojumi."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Akumulatora enerģijas taupīšanas režīmā tiek ieslēgts tumšais motīvs un tiek ierobežotas vai izslēgtas darbības fonā, daži vizuālie efekti, noteiktas funkcijas un noteikti tīkla savienojumi."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Lai samazinātu datu lietojumu, datu lietojuma samazinātājs neļauj dažām lietotnēm fonā nosūtīt vai saņemt datus. Lietotne, kuru pašlaik izmantojat, var piekļūt datiem, bet, iespējams, piekļūs tiem retāk (piemēram, attēli tiks parādīti tikai tad, kad tiem pieskarsieties)."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Vai ieslēgt datu lietojuma samazinātāju?"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 674ef16..5a9486e 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ажурирано од администраторот"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Избришано од администраторот"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Во ред"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"„Штедачот на батерија“ вклучува темна тема и ја ограничува или исклучува активноста во заднина, некои визуелни ефекти, одредени функции и некои мрежни врски."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"„Штедачот на батерија“ вклучува темна тема и ја ограничува или исклучува активноста во заднина, некои визуелни ефекти, одредени функции и некои мрежни врски."</string>
<string name="data_saver_description" msgid="4995164271550590517">"За да се намали користењето интернет, „Штедачот на интернет“ спречува дел од апликациите да испраќаат или да примаат податоци во заднина. Одредена апликација што ја користите ќе може да користи интернет, но можеби тоа ќе го прави поретко. Ова значи, на пример, дека сликите нема да се прикажуваат додека не ги допрете."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Да се вклучи „Штедач на интернет“?"</string>
@@ -2089,11 +2092,11 @@
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Известувањево е рангирано повисоко. Допрете за да дадете повратни информации."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Известувањево е рангирано пониско. Допрете за да дадете повратни информации."</string>
<string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Подобрени известувања"</string>
- <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"„Подобрените известувања“ сега ги даваат предложените дејства и одговорите. „Приспособливите известувања на Android“ веќе не се достапни."</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"„Подобрените известувања“ сега ги даваат предложените дејства и одговорите. „Адаптивните известувања на Android“ веќе не се достапни."</string>
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Во ред"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Исклучи"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Дознајте повеќе"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"„Подобрените известувања“ ги заменија „Приспособливите известувања на Android“ во Android 12. Оваа функција прикажува предложени дејства и одговори и ги организира вашите известувања.\n\n„Подобрените известувања“ може да пристапат до содржините од известувањата, вклучително и личните податоци, како што се имињата на контактите и пораките. Функцијава може и да отфрла или одговара на известувања, како на пример, одговарање телефонски повици и да ја контролира „Не вознемирувај“."</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"„Подобрените известувања“ ги заменија „Адаптивните известувања на Android“ во Android 12. Оваа функција прикажува предложени дејства и одговори и ги организира вашите известувања. \n\n„Подобрените известувања“ може да пристапуваат до содржините од известувањата, вклучително и личните податоци, како што се имињата на контактите и пораките. Функцијава може и да ги отфрла или да одговара на известувањата, како на пример, да одговара на телефонски повици и да го контролира режимот „Не вознемирувај“."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Известување за информации за режимот за рутини"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батеријата може да се потроши пред вообичаеното време за полнење"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Активиран е „Штедачот на батерија“ за да се продолжи траењето на батеријата"</string>
@@ -2149,7 +2152,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">"Блокирано од вашиот IT-администратор"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 7d1bb9b..9ca392a 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -315,7 +315,7 @@
<string name="permgroupdesc_storage" msgid="6351503740613026600">"നിങ്ങളുടെ ഉപകരണത്തിലെ ഫോട്ടോകളും മീഡിയയും ഫയലുകളും ആക്സസ് ചെയ്യുക"</string>
<string name="permgrouplab_microphone" msgid="2480597427667420076">"മൈക്രോഫോണ്"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"ഓഡിയോ റെക്കോർഡ് ചെയ്യുക"</string>
- <string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"കായിക പ്രവർത്തനം"</string>
+ <string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"ശാരീരിക ആക്റ്റിവിറ്റി"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ശാരീരിക പ്രവർത്തനം ആക്സസ് ചെയ്യുക"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"ക്യാമറ"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ചിത്രങ്ങളെടുത്ത് വീഡിയോ റെക്കോർഡുചെയ്യുക"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"നിങ്ങളുടെ അഡ്മിൻ അപ്ഡേറ്റ് ചെയ്യുന്നത്"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"നിങ്ങളുടെ അഡ്മിൻ ഇല്ലാതാക്കുന്നത്"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ശരി"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"\'ബാറ്ററി ലാഭിക്കൽ\' ഡാർക്ക് തീം ഓണാക്കുന്നു, ഒപ്പം പശ്ചാത്തല ആക്റ്റിവിറ്റിയും ചില വിഷ്വൽ ഇഫക്റ്റുകളും ചില ഫീച്ചറുകളും ചില നെറ്റ്വർക്ക് കണക്ഷനുകളും പരിമിതപ്പെടുത്തുകയോ ഓഫാക്കുകയോ ചെയ്യുന്നു."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"ബാറ്ററി ലാഭിക്കൽ ഡാർക്ക് തീം ഓണാക്കുന്നു, പശ്ചാത്തല ആക്റ്റിവിറ്റിയും ചില വിഷ്വൽ ഇഫക്റ്റുകളും ചില ഫീച്ചറുകളും ചില നെറ്റ്വർക്ക് കണക്ഷനുകളും അത് പരിമിതപ്പെടുത്തുകയോ ഓഫാക്കുകയോ ചെയ്യുന്നു."</string>
<string name="data_saver_description" msgid="4995164271550590517">"ഡാറ്റാ ഉപയോഗം കുറയ്ക്കാൻ സഹായിക്കുന്നതിനായി പശ്ചാത്തലത്തിൽ ഡാറ്റ അയയ്ക്കുകയോ സ്വീകരിക്കുകയോ ചെയ്യുന്നതിൽ നിന്ന് ചില ആപ്പുകളെ ഡാറ്റാ സേവർ തടയുന്നു. നിങ്ങൾ നിലവിൽ ഉപയോഗിക്കുന്ന ഒരു ആപ്പിന് ഡാറ്റ ആക്സസ് ചെയ്യാനാകും, എന്നാൽ വല്ലപ്പോഴും മാത്രമെ സംഭവിക്കുന്നുള്ളു. ഇതിനർത്ഥം, ഉദാഹരണമായി നിങ്ങൾ ടാപ്പ് ചെയ്യുന്നത് വരെ ചിത്രങ്ങൾ പ്രദർശിപ്പിക്കുകയില്ല എന്നാണ്."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ഡാറ്റ സേവർ ഓണാക്കണോ?"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 4f87dd6..4c01871d 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Таны админ шинэчилсэн"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Таны админ устгасан"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Батарей хэмнэгч нь Бараан загварыг асааж, дэвсгэрийн үйл ажиллагаа, зарим визуал эффект, тодорхой онцлогууд болон зарим сүлжээний холболтыг хязгаарлах эсвэл унтраана."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Батарей хэмнэгч нь Бараан загварыг асааж, дэвсгэрийн үйл ажиллагаа, зарим визуал эффект, тодорхой онцлогууд болон зарим сүлжээний холболтыг хязгаарлах эсвэл унтраана."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Дата ашиглалтыг багасгахын тулд дата хэмнэгч нь ар талд ажиллаж буй зарим апп-н өгөгдлийг илгээх болон авахаас сэргийлдэг. Таны одоогийн ашиглаж буй апп нь өгөгдөлд хандах боломжтой хэдий ч тогтмол хандахгүй. Энэ нь жишээлбэл зургийг товших хүртэл харагдахгүй гэсэн үг юм."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Дата хэмнэгчийг асаах уу?"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index e490129..1dfa5de 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/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>) ने तिच्या स्वयं-लागू केलेल्या StrictMode धोरणाचे उल्लंघन केले आहे."</string>
<string name="smv_process" msgid="1398801497130695446">"<xliff:g id="PROCESS">%1$s</xliff:g> प्रक्रियेने तिच्या स्वतः-लागू केलेल्या StrictMode धोरणाचे उल्लंघन केले."</string>
<string name="android_upgrading_title" product="default" msgid="7279077384220829683">"फोन अपडेट होत आहे…"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"आपल्या प्रशासकाने अपडेट केले"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"आपल्या प्रशासकाने हटवले"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ओके"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"बॅटरी सेव्हर गडद थीम सुरू करते आणि बॅकग्राउंड ॲक्टिव्हिटी, काही व्हिज्युअल इफेक्ट, ठरावीक वैशिष्ट्ये व काही नेटवर्क कनेक्शन मर्यादित किंवा बंद करते."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"बॅटरी सेव्हर गडद थीम सुरू करते आणि बॅकग्राउंड ॲक्टिव्हिटी, काही व्हिज्युअल इफेक्ट, ठरावीक वैशिष्ट्ये व काही नेटवर्क कनेक्शन मर्यादित किंवा बंद करते."</string>
<string name="data_saver_description" msgid="4995164271550590517">"डेटाचा वापर कमी करण्यात मदत करण्यासाठी काही अॅप्सना बॅकग्राउंडमध्ये डेटा पाठवण्यास किंवा मिळवण्यास डेटा सर्व्हर प्रतिबंध करतो. तुम्ही सध्या वापरत असलेले अॅप डेटा अॅक्सेस करू शकते, पण तसे खूप कमी वेळा होते. याचाच अर्थ असा की, तुम्ही इमेजवर टॅप करेपर्यंत त्या डिस्प्ले होणार नाहीत असे होऊ शकते."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"डेटा सेव्हर सुरू करायचे?"</string>
@@ -1977,7 +1980,7 @@
<string name="app_blocked_title" msgid="7353262160455028160">"ॲप उपलब्ध नाही"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> आता उपलब्ध नाही."</string>
<string name="deprecated_target_sdk_message" msgid="5203207875657579953">"हे अॅप Android च्या जुन्या आवृत्ती साठी तयार करण्यात आले होते आणि योग्यरितीने कार्य करू शकणार नाही. अपडेट आहेत का ते तपासून पाहा, किंवा डेव्हलपरशी संपर्क साधण्याचा प्रयत्न करा."</string>
- <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अपडेट आहे का ते तपासा"</string>
+ <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अपडेटसाठी तपासा"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"आपल्याकडे नवीन मेसेज आहेत"</string>
<string name="new_sms_notification_content" msgid="3197949934153460639">"पाहण्यासाठी SMS अॅप उघडा"</string>
<string name="profile_encrypted_title" msgid="9001208667521266472">"काही कार्यक्षमता मर्यादित असू शकतात"</string>
@@ -2118,8 +2121,8 @@
<string name="mime_type_document_ext" msgid="2398002765046677311">"<xliff:g id="EXTENSION">%1$s</xliff:g> दस्तऐवज"</string>
<string name="mime_type_spreadsheet" msgid="8188407519131275838">"स्प्रेडशीट"</string>
<string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> स्प्रेडशीट"</string>
- <string name="mime_type_presentation" msgid="1145384236788242075">"सादरीकरण"</string>
- <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> सादरीकरण"</string>
+ <string name="mime_type_presentation" msgid="1145384236788242075">"प्रेझेंटेशन"</string>
+ <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> प्रेझेंटेशन"</string>
<string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"विमान मोड दरम्यान ब्लूटूथ सुरू राहील"</string>
<string name="car_loading_profile" msgid="8219978381196748070">"लोड होत आहे"</string>
<plurals name="file_count" formatted="false" msgid="7063513834724389247">
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 1bab0b2..2960ca2 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1458,6 +1458,10 @@
<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="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 2f90b58..2c0ed7b 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"သင်၏ စီမံခန့်ခွဲသူက အပ်ဒိတ်လုပ်ထားသည်"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"သင်၏ စီမံခန့်ခွဲသူက ဖျက်လိုက်ပါပြီ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"‘ဘက်ထရီ အားထိန်း’ က ‘မှောင်သည့် အပြင်အဆင်’ ကို ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်၊ ပြသမှုဆိုင်ရာ အထူးပြုလုပ်ချက်အချို့၊ ဝန်ဆောင်မှုအချို့နှင့် ကွန်ရက်ချိတ်ဆက်မှုအချို့တို့ကို ကန့်သတ်သည် သို့မဟုတ် ပိတ်သည်။"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"‘ဘက်ထရီ အားထိန်း’ က ‘မှောင်သည့် အပြင်အဆင်’ ကို ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်၊ ပြသမှုဆိုင်ရာ အထူးပြုလုပ်ချက်အချို့၊ ဝန်ဆောင်မှုအချို့နှင့် ကွန်ရက်ချိတ်ဆက်မှုအချို့တို့ကို ကန့်သတ်သည် သို့မဟုတ် ပိတ်သည်။"</string>
<string name="data_saver_description" msgid="4995164271550590517">"ဒေတာအသုံးလျှော့ချနိုင်ရန်အတွက် အက်ပ်များကို နောက်ခံတွင် ဒေတာပို့ခြင်းနှင့် လက်ခံခြင်းမပြုရန် \'ဒေတာချွေတာမှု\' စနစ်က တားဆီးထားပါသည်။ ယခုအက်ပ်ဖြင့် ဒေတာအသုံးပြုနိုင်သော်လည်း အကြိမ်လျှော့၍သုံးရပါမည်။ ဥပမာ၊ သင်က မတို့မချင်း ပုံများပေါ်လာမည် မဟုတ်ပါ။"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ဒေတာချွေတာမှုစနစ် ဖွင့်မလား။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 5228c6a..0ceebf1 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -187,7 +187,7 @@
<string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Av en ukjent tredjepart"</string>
<string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Av administratoren for jobbprofilen din"</string>
<string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"Av <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
- <string name="work_profile_deleted" msgid="5891181538182009328">"Arbeidsprofilen er slettet"</string>
+ <string name="work_profile_deleted" msgid="5891181538182009328">"Jobbprofilen er slettet"</string>
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Administratorappen for jobbprofilen mangler eller er skadet. Dette har ført til at jobbprofilen og alle data knyttet til den, har blitt slettet. Ta kontakt med administratoren for å få hjelp."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Jobbprofilen din er ikke lenger tilgjengelig på denne enheten"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"For mange passordforsøk"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1476,7 +1480,7 @@
<string name="deny" msgid="6632259981847676572">"Avslå"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"Tillatelse forespurt"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Tillatelse forespurt\nfor kontoen <xliff:g id="ACCOUNT">%s</xliff:g>."</string>
- <string name="forward_intent_to_owner" msgid="4620359037192871015">"Du bruker denne appen utenfor arbeidsprofilen"</string>
+ <string name="forward_intent_to_owner" msgid="4620359037192871015">"Du bruker denne appen utenfor jobbprofilen"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"Du bruker denne appen i jobbprofilen din"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"Inndatametode"</string>
<string name="sync_binding_label" msgid="469249309424662147">"Synkronisering"</string>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Oppdatert av administratoren din"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Slettet av administratoren din"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Batterisparing slår på mørkt tema og begrenser eller slår av bakgrunnsaktivitet, enkelte visuelle effekter, noen funksjoner og noen nettverkstilkoblinger."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Batterisparing slår på mørkt tema og begrenser eller slår av bakgrunnsaktivitet, enkelte visuelle effekter, noen funksjoner og noen nettverkstilkoblinger."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Datasparing hindrer noen apper fra å sende og motta data i bakgrunnen, for å redusere dataforbruket. Aktive apper kan bruke data, men kanskje ikke så mye som ellers – for eksempel vises ikke bilder før du trykker på dem."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Vil du slå på Datasparing?"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index ca8d403..8e7ca71 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -198,7 +198,7 @@
<string name="location_changed_notification_text" msgid="7158423339982706912">"थप जानकारी प्राप्त गर्न आफ्ना IT प्रशासकसँग सम्पर्क गर्नुहोस्"</string>
<string name="geofencing_service" msgid="3826902410740315456">"जियोफेन्सिङ सेवा"</string>
<string name="country_detector" msgid="7023275114706088854">"देश पत्ता लगाउने सुविधा"</string>
- <string name="location_service" msgid="2439187616018455546">"स्थानसम्बन्धी सेवा"</string>
+ <string name="location_service" msgid="2439187616018455546">"लोकेसन सर्भिस"</string>
<string name="gnss_service" msgid="8907781262179951385">"GNSS सेवा"</string>
<string name="sensor_notification_service" msgid="7474531979178682676">"सेन्सरको सूचनासम्बन्धी सेवा"</string>
<string name="twilight_service" msgid="8964898045693187224">"ट्वाइलाइट सेवा"</string>
@@ -910,7 +910,7 @@
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"तपाईंले गलत तरिकाले आफ्नो पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक टाइप गर्नुभयो। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"तपाईँले गलत तरिकाले तपाईँको PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक टाइप गर्नु भएको छ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"तपाईँले तपाईँको अनलक प्याटर्न गलत तरिकाले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक खिच्नु भएको छ। पछि <xliff:g id="NUMBER_1">%2$d</xliff:g> थप असफल कोसिसहरू, तपाईँको Google साइन इन प्रयोग गरी तपाईँको ट्याब्लेट अनलक गर्न भनिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फरि प्रयास गर्नुहोस्।"</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"तपाईंले आफ्नो अनलक शैली <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले कोर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंलाई आफ्नो Google खाता मार्फत साइन इन गरेर आफ्नो Android टिभी यन्त्र अनलक गर्न अनुरोध गरिनेछ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।"</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"तपाईंले आफ्नो अनलक शैली <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले कोर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंलाई आफ्नो Google खाता मार्फत साइन इन गरेर आफ्नो Android टिभी डिभाइस अनलक गर्न अनुरोध गरिनेछ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।"</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"तपाईँले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले तपाईँको अनलक ढाँचालाई कोर्नु भएको छ। पछि <xliff:g id="NUMBER_1">%2$d</xliff:g> अरू धेरै असफल कोसिसहरूपछि, तपाईँलाई तपाईँको फोन Google साइन इन प्रयोग गरेर अनलक गर्नको लागि सोधिने छ। \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा पुनः प्रयास गर्नुहोस्।"</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"तपाईँले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक ट्याब्लेटलाई अनलक गर्नको लागि गलत तरिकाले कोशिस गर्नुभएको छ। <xliff:g id="NUMBER_1">%2$d</xliff:g> अरू धेरै असफल कोसिसहरूपछि, ट्याब्लेट फ्याट्रि पूर्वनिर्धारितमा रिसेट हुने छ र सबै प्रयोगकर्ता डेटा हराउने छन्।"</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"तपाईंले आफ्नो Android टिभी यन्त्र <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंको Android टिभी यन्त्रलाई रिसेट गरेर डिफल्ट फ्याक्ट्री सेटिङ लागू गरिने छ र प्रयोगकर्ताको सम्पूर्ण डेटा गुम्ने छ।"</string>
@@ -1198,7 +1198,7 @@
<string name="whichSendToApplication" msgid="77101541959464018">"यसको प्रयोग गरी पठाउनुहोस्"</string>
<string name="whichSendToApplicationNamed" msgid="3385686512014670003">"%1$s को प्रयोग गरी पठाउनुहोस्"</string>
<string name="whichSendToApplicationLabel" msgid="3543240188816513303">"पठाउनुहोस्"</string>
- <string name="whichHomeApplication" msgid="8276350727038396616">"गृह एप चयन गर्नुहोस्"</string>
+ <string name="whichHomeApplication" msgid="8276350727038396616">"होम एप चयन गर्नुहोस्"</string>
<string name="whichHomeApplicationNamed" msgid="5855990024847433794">"%1$s लाई गृहको रूपमा प्रयोग गर्नुहोस्"</string>
<string name="whichHomeApplicationLabel" msgid="8907334282202933959">"छविलाई कैंद गर्नुहोस्"</string>
<string name="whichImageCaptureApplication" msgid="2737413019463215284">"यस मार्फत छविलाई कैंद गर्नुहोस्"</string>
@@ -1393,7 +1393,7 @@
<string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"भाषा र लेआउट चयन गर्न ट्याप गर्नुहोस्"</string>
<string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
- <string name="alert_windows_notification_channel_group_name" msgid="6063891141815714246">"अरू एपमाथि देखाउनुहोस्"</string>
+ <string name="alert_windows_notification_channel_group_name" msgid="6063891141815714246">"अरू एपमाथि देखाइयोस्"</string>
<string name="alert_windows_notification_channel_name" msgid="3437528564303192620">"<xliff:g id="NAME">%s</xliff:g> अन्य एपहरूमा देखिँदैछ"</string>
<string name="alert_windows_notification_title" msgid="6331662751095228536">"<xliff:g id="NAME">%s</xliff:g> अन्य एपहरूमा देखिँदैछ"</string>
<string name="alert_windows_notification_message" msgid="6538171456970725333">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले यो विशेषता प्रयोग नगरेको चाहनुहुन्न भने सेटिङहरू खोली यसलाई निष्क्रिय पार्न ट्याप गर्नुहोस्।"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1675,7 +1679,7 @@
<string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"तपाईंले आफ्नो Android टिभी यन्त्र <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले अनलक गर्ने प्रयास गर्नुभएको छ। अब तपाईंको Android टिभी यन्त्रलाई रिसेट गरेर डिफल्ट फ्याक्ट्री सेटिङ लागू गरिनेछ।"</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"तपाईंले गलत तरिकाले फोन <xliff:g id="NUMBER">%d</xliff:g> पटक अनलक गर्ने प्रयत्न गर्नुभयो। अब फोन फ्याक्ट्रि पूर्वनिर्धारितमा रिसेट हुने छ।"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"तपाईंले गलत तरिकाले आफ्नो अनलक प्याटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक कोर्नुभयो। <xliff:g id="NUMBER_1">%2$d</xliff:g> विफल प्रयत्नहरू पछि, तपाईंलाई आफ्नो ट्याब्लेट इमेल खाता प्रयोग गरेर अनलक गर्न सोधिने छ।\n\n फेरि प्रयास गर्नुहोस् <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डहरूमा।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"तपाईंले आफ्नो अनलक शैली <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले कोर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंलाई आफ्नो इमेल खाता प्रयोग गरेर आफ्नो Android टिभी यन्त्र अनलक गर्न अनुरोध गरिनेछ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"तपाईंले आफ्नो अनलक शैली <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले कोर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंलाई आफ्नो इमेल खाता प्रयोग गरेर आफ्नो Android टिभी डिभाइस अनलक गर्न अनुरोध गरिनेछ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"तपाईँले आफ्नो अनलक प्याटर्न गलत रूपमा <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक तान्नु भएको छ। <xliff:g id="NUMBER_1">%2$d</xliff:g> धेरै असफल प्रयासहरूपछि, तपाईँलाई एउटा इमेल खाताको प्रयोग गरेर तपाईँको फोन अनलक गर्न सोधिने छ।\n\n फेरि <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा प्रयास गर्नुहोस्।"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"हटाउनुहोस्"</string>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"तपाईंका प्रशासकले अद्यावधिक गर्नुभएको"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"तपाईंका प्रशासकले मेट्नुभएको"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ठिक छ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ब्याट्री सेभरले अँध्यारो थिम अन गर्छ र ब्याकग्राउन्डमा हुने क्रियाकलाप, केही भिजुअल इफेक्ट, निश्चित सुविधा र केही नेटवर्क कनेक्सनहरू अफ गर्छ वा सीमित रूपमा मात्र चल्न दिन्छ।"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"ब्याट्री सेभरले अँध्यारो थिम अन गर्छ र ब्याकग्राउन्डमा हुने क्रियाकलाप, केही भिजुअल इफेक्ट, निश्चित सुविधा र केही नेटवर्क कनेक्सनहरू अफ गर्छ वा सीमित रूपमा मात्र चल्न दिन्छ।"</string>
<string name="data_saver_description" msgid="4995164271550590517">"डेटा सेभरले डेटा खपत कम गर्न केही एपहरूलाई ब्याकग्राउन्डमा डेटा पठाउन वा प्राप्त गर्न दिँदैन। तपाईंले अहिले प्रयोग गरिरहनुभएको एपले सीमित रूपमा मात्र डेटा चलाउन पाउँछ। उदाहरणका लागि, तपाईंले फोटोमा ट्याप गर्नुभयो भने मात्र फोटो देखिन्छ नत्र देखिँदैन।"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"डेटा सेभर अन गर्ने हो?"</string>
@@ -1977,7 +1980,7 @@
<string name="app_blocked_title" msgid="7353262160455028160">"एप उपलब्ध छैन"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> अहिले उपलब्ध छैन।"</string>
<string name="deprecated_target_sdk_message" msgid="5203207875657579953">"यो एप Android को पुरानो संस्करणका लागि बनाइएको हुनाले यसले सही ढङ्गले काम नगर्न सक्छ। अद्यावधिकहरू उपलब्ध छन् वा छैनन् भनी जाँच गरी हेर्नुहोस् वा यसको विकासकर्तालाई सम्पर्क गर्नुहोस्।"</string>
- <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अद्यावधिक उपलब्ध छ वा छैन भनी जाँच गर्नुहोस्"</string>
+ <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अपडेट उपलब्ध छ वा छैन जाँच्नुहोस्"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"तपाईंलाई नयाँ सन्देश आएको छ"</string>
<string name="new_sms_notification_content" msgid="3197949934153460639">"हेर्नका लागि SMS एप खोल्नुहोस्"</string>
<string name="profile_encrypted_title" msgid="9001208667521266472">"केही सुविधा राम्ररी नचल्न सक्छन्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 0c9a278..9700939 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1367,7 +1367,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Analoog audioaccessoire gedetecteerd"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Het aangesloten apparaat werkt niet met deze telefoon. Tik voor meer informatie."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"USB-foutopsporing verbonden"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"Tik om USB-foutopsporing uit te zetten."</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Tik om USB-foutopsporing uit te zetten"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Selecteer deze optie om USB-foutopsporing uit te zetten."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Draadloze foutopsporing verbonden"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Tik om draadloze foutopsporing uit te zetten"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,10 +1870,9 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Geüpdatet door je beheerder"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Verwijderd door je beheerder"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Met Batterijbesparing wordt het donkere thema aangezet en worden achtergrondactiviteit, bepaalde visuele effecten, bepaalde functies en sommige netwerkverbindingen beperkt of uitgezet."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Met Batterijbesparing wordt het donkere thema aangezet en worden achtergrondactiviteit, bepaalde visuele effecten, bepaalde functies en sommige netwerkverbindingen beperkt of uitgezet."</string>
- <string name="data_saver_description" msgid="4995164271550590517">"Databesparing beperkt het datagebruik door te voorkomen dat sommige apps gegevens sturen of ontvangen op de achtergrond. De apps die je open hebt, kunnen nog steeds data verbruiken, maar doen dit minder vaak. Afbeeldingen worden dan bijvoorbeeld niet weergegeven totdat je erop tikt."</string>
+ <string name="data_saver_description" msgid="4995164271550590517">"Databesparing beperkt het datagebruik door te voorkomen dat sommige apps gegevens sturen of ontvangen op de achtergrond. De apps die je open hebt, kunnen nog steeds data verbruiken, maar doen dit minder vaak. Afbeeldingen worden dan bijvoorbeeld niet getoond totdat je erop tikt."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Databesparing aanzetten?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aanzetten"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 5584324..d6b1e1e 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -223,7 +223,7 @@
<string name="power_off" msgid="4111692782492232778">"ପାୱାର୍ ବନ୍ଦ"</string>
<string name="silent_mode_silent" msgid="5079789070221150912">"ରିଙ୍ଗର୍ ଅଫ୍ ଅଛି"</string>
<string name="silent_mode_vibrate" msgid="8821830448369552678">"ରିଙ୍ଗର୍ କମ୍ପନ"</string>
- <string name="silent_mode_ring" msgid="6039011004781526678">"ରିଙ୍ଗର୍ ଅନ୍ ଅଛି"</string>
+ <string name="silent_mode_ring" msgid="6039011004781526678">"ରିଙ୍ଗର୍ ଚାଲୁ ଅଛି"</string>
<string name="reboot_to_update_title" msgid="2125818841916373708">"Android ସିଷ୍ଟମ୍ ଅପଡେଟ୍"</string>
<string name="reboot_to_update_prepare" msgid="6978842143587422365">"ଅପଡେଟ୍ କରିବାକୁ ପ୍ରସ୍ତୁତ କରାଯାଉଛି…"</string>
<string name="reboot_to_update_package" msgid="4644104795527534811">"ଅପଡେଟ୍ ପ୍ୟାକେଜ୍ ପ୍ରୋସେସ୍ କରାଯାଉଛି…"</string>
@@ -265,7 +265,7 @@
<string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"ବଗ୍ ରିପୋର୍ଟ ସହ ସ୍କ୍ରିନସଟ୍ ନେବାରେ ବିଫଳ ହୋଇଛି"</string>
<string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"ସାଇଲେଣ୍ଟ ମୋଡ୍"</string>
<string name="global_action_silent_mode_on_status" msgid="2371892537738632013">"ସାଉଣ୍ଡ ଅଫ୍ ଅଛି"</string>
- <string name="global_action_silent_mode_off_status" msgid="6608006545950920042">"ସାଉଣ୍ଡ ଅନ୍ ଅଛି"</string>
+ <string name="global_action_silent_mode_off_status" msgid="6608006545950920042">"ସାଉଣ୍ଡ ଚାଲୁ ଅଛି"</string>
<string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍"</string>
<string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍ ଅନ୍ ଅଛି"</string>
<string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍ ଅଫ୍ ଅଛି"</string>
@@ -930,7 +930,7 @@
<string name="lockscreen_glogin_account_recovery_hint" msgid="1683405808525090649">"ଆପଣଙ୍କର ଯୁଜରନେମ୍ କିମ୍ୱା ପାସୱାର୍ଡ ଭୁଲି ଯାଇଛନ୍ତି କି?\n"<b>"google.com/accounts/recovery"</b>" ଭିଜିଟ୍ କରନ୍ତୁ।"</string>
<string name="lockscreen_glogin_checking_password" msgid="2607271802803381645">"ଯାଞ୍ଚ କରାଯାଉଛି…"</string>
<string name="lockscreen_unlock_label" msgid="4648257878373307582">"ଅନଲକ୍"</string>
- <string name="lockscreen_sound_on_label" msgid="1660281470535492430">"ସାଉଣ୍ଡ ଅନ୍ ଅଛି"</string>
+ <string name="lockscreen_sound_on_label" msgid="1660281470535492430">"ସାଉଣ୍ଡ ଚାଲୁ ଅଛି"</string>
<string name="lockscreen_sound_off_label" msgid="2331496559245450053">"ସାଉଣ୍ଡ ଅଫ୍ ଅଛି"</string>
<string name="lockscreen_access_pattern_start" msgid="3778502525702613399">"ପାଟର୍ନ ଆରମ୍ଭ ହେଲା"</string>
<string name="lockscreen_access_pattern_cleared" msgid="7493849102641167049">"ପାଟର୍ନ ଖାଲି କରାଗଲା"</string>
@@ -1033,7 +1033,7 @@
<string name="menu_function_shortcut_label" msgid="2367112760987662566">"Function+"</string>
<string name="menu_space_shortcut_label" msgid="5949311515646872071">"ସ୍ପେସ୍"</string>
<string name="menu_enter_shortcut_label" msgid="6709499510082897320">"ଏଣ୍ଟର୍"</string>
- <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"ଡିଲିଟ୍"</string>
+ <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"ଡିଲିଟ୍ କରନ୍ତୁ"</string>
<string name="search_go" msgid="2141477624421347086">"Search"</string>
<string name="search_hint" msgid="455364685740251925">"ସର୍ଚ୍ଚ…"</string>
<string name="searchview_description_search" msgid="1045552007537359343">"Search"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ଆପଣଙ୍କ ଆଡମିନ୍ ଅପଡେଟ୍ କରିଛନ୍ତି"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ଆପଣଙ୍କ ଆଡମିନ୍ ଡିଲିଟ୍ କରିଛନ୍ତି"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ଠିକ୍ ଅଛି"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ବ୍ୟାଟେରୀ ସେଭର୍ ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ୍ ଇଫେକ୍ଟ, କିଛି ଫିଚର୍ ଏବଂ କିଛି ନେଟୱାର୍କ ସଂଯୋଗକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"ବ୍ୟାଟେରୀ ସେଭର୍ ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ୍ ଇଫେକ୍ଟ, କିଛି ଫିଚର୍ ଏବଂ କିଛି ନେଟୱାର୍କ ସଂଯୋଗକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।"</string>
<string name="data_saver_description" msgid="4995164271550590517">"ଡାଟା ବ୍ୟବହାର କମ୍ କରିବାରେ ସାହାଯ୍ୟ କରିବାକୁ, ଡାଟା ସେଭର୍ ବ୍ୟାକ୍ଗ୍ରାଉଣ୍ଡରେ ଡାଟା ପଠାଇବା କିମ୍ବା ପ୍ରାପ୍ତ କରିବାକୁ କିଛି ଆପ୍କୁ ବାରଣ କରେ। ଆପଣ ବର୍ତ୍ତମାନ ବ୍ୟବହାର କରୁଥିବା ଆପ୍, ଡାଟା ଆକ୍ସେସ୍ କରିପାରେ, କିନ୍ତୁ ଏହା କମ୍ ଥର କରିପାରେ। ଏହାର ଅର୍ଥ ହୋଇପାରେ ଯେମିତି ଆପଣ ଇମେଜଗୁଡ଼ିକୁ ଟାପ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ସେଗୁଡ଼ିକ ଡିସପ୍ଲେ ହୁଏ ନାହିଁ।"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ଡାଟା ସେଭର୍ ଚାଲୁ କରିବେ?"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 1436d47..9a73f9b 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,10 +1870,9 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਮਿਟਾਇਆ ਗਿਆ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ਠੀਕ ਹੈ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ਬੈਟਰੀ ਸੇਵਰ ਗੂੜ੍ਹੇ ਥੀਮ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ ਅਤੇ ਬੈਕਗ੍ਰਾਊਂਡ ਸਰਗਰਮੀ, ਕੁਝ ਦ੍ਰਿਸ਼ਟੀਗਤ ਪ੍ਰਭਾਵਾਂ, ਕੁਝ ਖਾਸ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਅਤੇ ਕੁਝ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨਾਂ ਨੂੰ ਸੀਮਤ ਜਾਂ ਬੰਦ ਕਰਦਾ ਹੈ।"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"ਬੈਟਰੀ ਸੇਵਰ ਗੂੜ੍ਹੇ ਥੀਮ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ ਅਤੇ ਬੈਕਗ੍ਰਾਊਂਡ ਸਰਗਰਮੀ, ਕੁਝ ਦ੍ਰਿਸ਼ਟੀਗਤ ਪ੍ਰਭਾਵਾਂ, ਕੁਝ ਖਾਸ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਅਤੇ ਕੁਝ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨਾਂ ਨੂੰ ਸੀਮਤ ਜਾਂ ਬੰਦ ਕਰਦਾ ਹੈ।"</string>
- <string name="data_saver_description" msgid="4995164271550590517">"ਡਾਟਾ ਵਰਤੋਂ ਘਟਾਉਣ ਵਿੱਚ ਮਦਦ ਲਈ, ਡਾਟਾ ਸੇਵਰ ਕੁਝ ਐਪਾਂ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡਾਟਾ ਭੇਜਣ ਜਾਂ ਪ੍ਰਾਪਤ ਕਰਨ ਤੋਂ ਰੋਕਦਾ ਹੈ। ਤੁਹਾਡੇ ਵੱਲੋਂ ਵਰਤਮਾਨ ਤੌਰ \'ਤੇ ਵਰਤੀ ਜਾ ਰਹੀ ਐਪ ਡਾਟਾ \'ਤੇ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ, ਪਰ ਉਹ ਇੰਝ ਕਦੇ-ਕਦਾਈਂ ਕਰ ਸਕਦੀ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਸ ਦਾ ਮਤਲਬ ਇਹ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਚਿੱਤਰ ਤਦ ਤੱਕ ਨਹੀਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕੀਤੇ ਜਾਂਦੇ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਉਹਨਾਂ \'ਤੇ ਟੈਪ ਨਹੀਂ ਕਰਦੇ।"</string>
+ <string name="data_saver_description" msgid="4995164271550590517">"ਡਾਟਾ ਵਰਤੋਂ ਘਟਾਉਣ ਵਿੱਚ ਮਦਦ ਕਰਨ ਲਈ, ਡਾਟਾ ਸੇਵਰ ਕੁਝ ਐਪਾਂ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡਾਟਾ ਭੇਜਣ ਜਾਂ ਪ੍ਰਾਪਤ ਕਰਨ ਤੋਂ ਰੋਕਦਾ ਹੈ। ਤੁਹਾਡੇ ਵੱਲੋਂ ਵਰਤਮਾਨ ਤੌਰ \'ਤੇ ਵਰਤੀ ਜਾ ਰਹੀ ਐਪ ਡਾਟਾ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ, ਪਰ ਉਹ ਇੰਝ ਕਦੇ-ਕਦਾਈਂ ਕਰ ਸਕਦੀ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਸ ਦਾ ਮਤਲਬ ਇਹ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਚਿੱਤਰ ਤਦ ਤੱਕ ਨਹੀਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕੀਤੇ ਜਾਂਦੇ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਉਹਨਾਂ \'ਤੇ ਟੈਪ ਨਹੀਂ ਕਰਦੇ।"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ਕੀ ਡਾਟਾ ਸੇਵਰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"ਚਾਲੂ ਕਰੋ"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 564fb19..2781df7 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1252,7 +1252,7 @@
<string name="noApplications" msgid="1186909265235544019">"Żadna z aplikacji nie może wykonać tej czynności."</string>
<string name="aerr_application" msgid="4090916809370389109">"Aplikacja <xliff:g id="APPLICATION">%1$s</xliff:g> przestała działać"</string>
<string name="aerr_process" msgid="4268018696970966407">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> przestał działać"</string>
- <string name="aerr_application_repeated" msgid="7804378743218496566">"<xliff:g id="APPLICATION">%1$s</xliff:g> wciąż przestaje działać"</string>
+ <string name="aerr_application_repeated" msgid="7804378743218496566">"Aplikacja <xliff:g id="APPLICATION">%1$s</xliff:g> wciąż przestaje działać"</string>
<string name="aerr_process_repeated" msgid="1153152413537954974">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> wciąż przestaje działać"</string>
<string name="aerr_restart" msgid="2789618625210505419">"Otwórz aplikację ponownie"</string>
<string name="aerr_report" msgid="3095644466849299308">"Prześlij opinię"</string>
@@ -1498,6 +1498,10 @@
<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="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>
@@ -1724,7 +1728,7 @@
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Usuń"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zwiększyć głośność ponad zalecany poziom?\n\nSłuchanie głośno przez długi czas może uszkodzić Twój słuch."</string>
- <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Użyć skrótu do ułatwień dostępu?"</string>
+ <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Użyć skrótu ułatwień dostępu?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Gdy skrót jest włączony, jednoczesne naciskanie przez trzy sekundy obu przycisków głośności uruchamia funkcję ułatwień dostępu."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Włączyć skrót ułatwień dostępu?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Przytrzymanie obu klawiszy głośności przez kilka sekund włącza ułatwienia dostępu. Może to zmienić sposób działania urządzenia.\n\nBieżące funkcje:\n<xliff:g id="SERVICE">%1$s</xliff:g>\naby zmienić wybrane funkcje, kliknij Ustawienia > Ułatwienia dostępu."</string>
@@ -1912,8 +1916,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Zaktualizowany przez administratora"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Usunięty przez administratora"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Oszczędzanie baterii uruchamia ciemny motyw oraz wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne, pewne funkcje oraz wybrane połączenia sieciowe."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Oszczędzanie baterii uruchamia ciemny motyw oraz wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne, pewne funkcje oraz wybrane połączenia sieciowe."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Oszczędzanie danych uniemożliwia niektórym aplikacjom wysyłanie i odbieranie danych w tle, zmniejszając w ten sposób ich użycie. Aplikacja, z której w tej chwili korzystasz, może uzyskiwać dostęp do danych, ale rzadziej. Może to powodować, że obrazy będą się wyświetlać dopiero po kliknięciu."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Włączyć Oszczędzanie danych?"</string>
@@ -2036,7 +2039,7 @@
<string name="app_suspended_more_details" msgid="211260942831587014">"Więcej informacji"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Wznów działanie aplikacji"</string>
<string name="work_mode_off_title" msgid="961171256005852058">"Włączyć aplikacje służbowe?"</string>
- <string name="work_mode_off_message" msgid="7319580997683623309">"Uzyskaj dostęp do aplikacji służbowych i powiadomień"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Uzyskaj dostęp do służbowych aplikacji i powiadomień"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Włącz"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacja jest niedostępna"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest obecnie niedostępna."</string>
@@ -2159,7 +2162,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Wyłącz"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Więcej informacji"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"W Androidzie 12 ulepszone powiadomienia zastąpiły powiadomienia adaptacyjne. Ta funkcja pokazuje sugerowane działania i odpowiedzi oraz porządkuje powiadomienia.\n\nUlepszone powiadomienia mogą czytać wszystkie powiadomienia, w tym dane osobowe takie jak nazwy kontaktów i treść wiadomości. Funkcja może też zamykać powiadomienia oraz reagować na nie, np. odbierać połączenia telefoniczne i sterować trybem Nie przeszkadzać."</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"W Androidzie 12 ulepszone powiadomienia zastąpiły dotychczasowe powiadomienia adaptacyjne. Ta funkcja pokazuje sugerowane działania i odpowiedzi oraz porządkuje powiadomienia.\n\nUlepszone powiadomienia mogą czytać całą zawartość powiadomień, w tym dane osobowe takie jak nazwy kontaktów i treść wiadomości. Funkcja może też zamykać powiadomienia oraz reagować na nie, np. odbierać połączenia telefoniczne i sterować trybem Nie przeszkadzać."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Powiadomienie z informacją o trybie rutynowym"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateria może się wyczerpać przed zwykłą porą ładowania"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Włączono Oszczędzanie baterii, by wydłużyć czas pracy na baterii"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index dd899de..a60cb23 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1367,7 +1367,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Acessório de áudio analógico detectado"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"O dispositivo anexo não é compatível com esse smartphone. Toque para saber mais."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"Depuração USB conectada"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"Toque para desativar a depuração USB."</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Toque para desativar a depuração USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Selecione para desativar a depuração USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Depuração por Wi-Fi conectada"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Toque para desativar a depuração por Wi-Fi"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1869,7 +1873,7 @@
<string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"A Economia de bateria ativa o tema escuro e limita ou desativa atividades em segundo plano, alguns efeitos visuais, recursos específicos e algumas conexões de rede."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"A Economia de bateria ativa o tema escuro e limita ou desativa atividades em segundo plano, alguns efeitos visuais, recursos específicos e algumas conexões de rede."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Para ajudar a reduzir o uso de dados, a Economia de dados impede que alguns apps enviem ou recebam dados em segundo plano. Um app que você esteja usando no momento pode acessar dados, mas com menos frequência. Isso pode fazer com que imagens não sejam exibidas até que você toque nelas."</string>
- <string name="data_saver_enable_title" msgid="7080620065745260137">"Ativar \"Economia de dados\"?"</string>
+ <string name="data_saver_enable_title" msgid="7080620065745260137">"Ativar a Economia de dados?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Ativar"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
<item quantity="one">Por %1$d minutos (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 378d3b4..5f10462 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1458,6 +1458,10 @@
<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="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 dd899de..a60cb23 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1367,7 +1367,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Acessório de áudio analógico detectado"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"O dispositivo anexo não é compatível com esse smartphone. Toque para saber mais."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"Depuração USB conectada"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"Toque para desativar a depuração USB."</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Toque para desativar a depuração USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Selecione para desativar a depuração USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Depuração por Wi-Fi conectada"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Toque para desativar a depuração por Wi-Fi"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1869,7 +1873,7 @@
<string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"A Economia de bateria ativa o tema escuro e limita ou desativa atividades em segundo plano, alguns efeitos visuais, recursos específicos e algumas conexões de rede."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"A Economia de bateria ativa o tema escuro e limita ou desativa atividades em segundo plano, alguns efeitos visuais, recursos específicos e algumas conexões de rede."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Para ajudar a reduzir o uso de dados, a Economia de dados impede que alguns apps enviem ou recebam dados em segundo plano. Um app que você esteja usando no momento pode acessar dados, mas com menos frequência. Isso pode fazer com que imagens não sejam exibidas até que você toque nelas."</string>
- <string name="data_saver_enable_title" msgid="7080620065745260137">"Ativar \"Economia de dados\"?"</string>
+ <string name="data_saver_enable_title" msgid="7080620065745260137">"Ativar a Economia de dados?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Ativar"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
<item quantity="one">Por %1$d minutos (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index c5cb90c..dc351a2 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1478,6 +1478,10 @@
<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="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>
@@ -1889,8 +1893,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizat de administratorul dvs."</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Șters de administratorul dvs."</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Economisirea bateriei activează tema întunecată și restricționează sau dezactivează activitatea în fundal, unele efecte vizuale, alte funcții și câteva conexiuni la rețea."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Economisirea bateriei activează tema întunecată și restricționează sau dezactivează activitatea în fundal, unele efecte vizuale, alte funcții și câteva conexiuni la rețea."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Pentru a contribui la reducerea utilizării de date, Economizorul de date împiedică unele aplicații să trimită sau să primească date în fundal. O aplicație pe care o folosiți poate accesa datele, însă mai rar. Aceasta poate însemna, de exemplu, că imaginile se afișează numai după ce le atingeți."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Activați Economizorul de date?"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index fe86339..ea9e292 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -331,7 +331,7 @@
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"чтение и запись телефонных звонков"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Телефон"</string>
<string name="permgroupdesc_phone" msgid="270048070781478204">"осуществлять вызовы и управлять ими"</string>
- <string name="permgrouplab_sensors" msgid="9134046949784064495">"Датчики на теле"</string>
+ <string name="permgrouplab_sensors" msgid="9134046949784064495">"Нательные датчики"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"доступ к данным датчиков о состоянии организма"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Получать содержимое окна"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Анализировать содержимое активного окна."</string>
@@ -1498,6 +1498,10 @@
<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="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>
@@ -1912,8 +1916,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Обновлено администратором"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Удалено администратором"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, некоторые визуальные эффекты, определенные функции и ряд сетевых подключений."</string>
- <string name="battery_saver_description" msgid="8518809702138617167">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, некоторые визуальные эффекты, определенные функции и ряд сетевых подключений."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, а также некоторые визуальные эффекты, функции и сетевые подключения."</string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, а также некоторые визуальные эффекты, функции и сетевые подключения."</string>
<string name="data_saver_description" msgid="4995164271550590517">"В режиме экономии трафика фоновая передача данных для некоторых приложений отключена. Приложение, которым вы пользуетесь, может получать и отправлять данные, но реже, чем обычно. Например, изображения могут не загружаться, пока вы не нажмете на них."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Включить экономию трафика?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Включить"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 4e188d9..6064103 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ඔබගේ පරිපාලක මඟින් යාවත්කාලීන කර ඇත"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ඔබගේ පරිපාලක මඟින් මකා දමා ඇත"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"හරි"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"බැටරි සුරැකුම අඳුරු තේමාව ක්රියාත්මක කර පසුබිම් ක්රියාකාරකම්, සමහර දෘශ්ය ප්රයෝග, යම් විශේෂාංග සහ සමහර ජාල සම්බන්ධතා සීමා හෝ ක්රියාවිරහිත කරයි."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"බැටරි සුරැකුම අඳුරු තේමාව ක්රියාත්මක කර පසුබිම් ක්රියාකාරකම්, සමහර දෘශ්ය ප්රයෝග, යම් විශේෂාංග සහ සමහර ජාල සම්බන්ධතා සීමා හෝ ක්රියාවිරහිත කරයි."</string>
<string name="data_saver_description" msgid="4995164271550590517">"දත්ත භාවිතය අඩු කිරීමට උදවු වීමට, දත්ත සුරැකුම සමහර යෙදුම් පසුබිමින් දත්ත යැවීම සහ ලබා ගැනීම වළක්වයි. ඔබ දැනට භාවිත කරන යෙදුමකට දත්ත වෙත පිවිසීමට හැකිය, නමුත් එසේ කරන්නේ කලාතුරකින් විය හැකිය. මෙයින් අදහස් වන්නේ, උදාහරණයක් ලෙස, එම රූප ඔබ ඒවාට තට්ටු කරන තෙක් සංදර්ශනය නොවන බවය."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"දත්ත සුරැකුම ක්රියාත්මක කරන්නද?"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 928ff12..e42cc01 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1498,6 +1498,10 @@
<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="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>
@@ -1912,8 +1916,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Aktualizoval správca"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Odstránil správca"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Šetrič batérie zapne tmavý motív a obmedzí alebo vypne aktivitu na pozadí, niektoré vizuálne efekty, určité funkcie a niektoré pripojenia k sieti."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Šetrič batérie zapne tmavý motív a obmedzí alebo vypne aktivitu na pozadí, niektoré vizuálne efekty, určité funkcie a niektoré pripojenia k sieti."</string>
<string name="data_saver_description" msgid="4995164271550590517">"S cieľom znížiť spotrebu dát bráni šetrič dát niektorým aplikáciám odosielať alebo prijímať dáta na pozadí. Aplikácia, ktorú práve používate, môže využívať dáta, ale možno to bude robiť menej často. Môže to napríklad znamenať, že sa obrázky zobrazia, až keď na ne klepnete."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Chcete zapnúť šetrič dát?"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ed33ec3..506c066 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1406,8 +1406,8 @@
<string name="usb_power_notification_message" msgid="7284765627437897702">"Polnjenje akumulatorja v povezani napravi. Dotaknite se za več možnosti."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Zaznana je analogna dodatna zvočna oprema"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Priključena naprava ni združljiva s tem telefonom. Dotaknite se za več informacij."</string>
- <string name="adb_active_notification_title" msgid="408390247354560331">"Iskanje napak prek USB je povezano"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"Dotaknite se, če želite izklop. odpravlj. napak prek USB-ja"</string>
+ <string name="adb_active_notification_title" msgid="408390247354560331">"Iskanje napak prek USB-ja je povezano"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Dotaknite se, če želite izklopiti odpravljanje napak prek USB-ja."</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Izberite, če želite onemogočiti iskanje in odpravljanje napak prek vrat USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Povezava za brezžično odpravljanje napak je vzpostavljena"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Dotaknite se, če želite izklopiti brezžično odpravljanje napak."</string>
@@ -1498,6 +1498,10 @@
<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="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>
@@ -1912,10 +1916,9 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Posodobil skrbnik"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisal skrbnik"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"V redu"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Funkcija varčevanja z energijo baterije vklopi temno temo ter omeji ali izklopi dejavnost v ozadju, nekatere vizualne učinke, določene funkcije in nekatere omrežne povezave."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Funkcija varčevanja z energijo baterije vklopi temno temo ter omeji ali izklopi dejavnost v ozadju, nekatere vizualne učinke, določene funkcije in nekatere omrežne povezave."</string>
- <string name="data_saver_description" msgid="4995164271550590517">"Zaradi zmanjševanja prenesene količine podatkov funkcija varčevanja s podatki nekaterim aplikacijam preprečuje, da bi v ozadju pošiljale ali prejemale podatke. Aplikacija, ki jo trenutno uporabljate, lahko prenaša podatke, vendar to morda počne manj pogosto. To na primer pomeni, da se slike ne prikažejo, dokler se jih ne dotaknete."</string>
+ <string name="data_saver_description" msgid="4995164271550590517">"Zaradi zmanjševanja prenesene količine podatkov funkcija varčevanja s podatki nekaterim aplikacijam preprečuje, da bi v ozadju pošiljale ali prejemale podatke. Aplikacija, ki jo trenutno uporabljate, lahko dostopa do podatkov, vendar to morda počne manj pogosto. To na primer pomeni, da se slike ne prikažejo, dokler se jih ne dotaknete."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Vklop varčevanja s podatki?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Vklopi"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
@@ -2036,8 +2039,8 @@
<string name="app_suspended_more_details" msgid="211260942831587014">"Več o tem"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Prekliči začasno zaustavitev aplikacije"</string>
<string name="work_mode_off_title" msgid="961171256005852058">"Vklop delovnih aplikacij?"</string>
- <string name="work_mode_off_message" msgid="7319580997683623309">"Omogočanje dostopa do delovnih aplikacij in obvestil za delovni profil"</string>
- <string name="work_mode_turn_on" msgid="3662561662475962285">"Vklop"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Pridobite dostop do delovnih aplikacij in obvestil za delovni profil."</string>
+ <string name="work_mode_turn_on" msgid="3662561662475962285">"Vklopi"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija ni na voljo"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno ni na voljo."</string>
<string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ta aplikacija je bila zasnovana za starejšo različico Androida in morda ne bo delovala pravilno. Preverite, ali so na voljo posodobitve, ali pa se obrnite na razvijalca."</string>
@@ -2194,7 +2197,7 @@
<item quantity="few"><xliff:g id="FILE_NAME_2">%s</xliff:g> in še <xliff:g id="COUNT_3">%d</xliff:g> datoteke</item>
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> in še <xliff:g id="COUNT_3">%d</xliff:g> datotek</item>
</plurals>
- <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Ni priporočenih oseb za deljenje vsebine"</string>
+ <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Ni priporočenih oseb za deljenje vsebine."</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Seznam aplikacij"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Ta aplikacija sicer nima dovoljenja za snemanje, vendar bi lahko zajemala zvok prek te naprave USB."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Začetni zaslon"</string>
@@ -2227,7 +2230,7 @@
<string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"Te vsebine ni mogoče odpreti z osebnimi aplikacijami."</string>
<string name="resolver_turn_on_work_apps" msgid="884910835250037247">"Delovni profil je začasno zaustavljen"</string>
<string name="resolver_switch_on_work" msgid="463709043650610420">"Dotaknite se za vklop"</string>
- <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nobena delovna aplikacija"</string>
+ <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nobena delovna aplikacija ni na voljo"</string>
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nobena osebna aplikacija"</string>
<string name="miniresolver_open_in_personal" msgid="2937599899213467617">"Želite odpreti v aplikaciji <xliff:g id="APP">%s</xliff:g> v osebnem profilu?"</string>
<string name="miniresolver_open_in_work" msgid="152208044699347924">"Želite odpreti v aplikaciji <xliff:g id="APP">%s</xliff:g> v delovnem profilu?"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 34e4ead..ed6a616 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Përditësuar nga administratori"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Fshirë nga administratori"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Në rregull"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"\"Kursyesi i baterisë\" aktivizon \"Temën e errët\" dhe kufizon ose çaktivizon aktivitetin në sfond, disa efekte vizuale, veçori të caktuara dhe disa lidhje të rrjetit."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"\"Kursyesi i baterisë\" aktivizon \"Temën e errët\" dhe kufizon ose çaktivizon aktivitetin në sfond, disa efekte vizuale, veçori të caktuara dhe disa lidhje të rrjetit."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Për të ndihmuar në reduktimin e përdorimit të të dhënave, \"Kursyesi i të dhënave\" pengon që disa aplikacione të dërgojnë apo të marrin të dhëna në sfond. Një aplikacion që po përdor aktualisht mund të ketë qasje te të dhënat, por këtë mund ta bëjë më rrallë. Kjo mund të nënkuptojë, për shembull, se imazhet nuk shfaqen kur troket mbi to."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Të aktivizohet \"Kursyesi i të dhënave\"?"</string>
@@ -1972,7 +1975,7 @@
<string name="app_suspended_more_details" msgid="211260942831587014">"Mëso më shumë"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Anulo pauzën për aplikacionin"</string>
<string name="work_mode_off_title" msgid="961171256005852058">"Të aktivizohen aplikacionet e punës?"</string>
- <string name="work_mode_off_message" msgid="7319580997683623309">"Merr qasjen tek aplikacionet e punës dhe njoftimet e tua"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Merr qasje tek aplikacionet e punës dhe njoftimet e tua"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivizo"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacioni nuk ofrohet"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk ofrohet për momentin."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 458677c..14f5673 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1478,6 +1478,10 @@
<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="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>
@@ -1889,8 +1893,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ажурирао је администратор"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Избрисао је администратор"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Потврди"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Уштеда батерије укључује тамну тему и ограничава или искључује активности у позадини, неке визуелне ефекте, одређене функције и неке мрежне везе."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Уштеда батерије укључује тамну тему и ограничава или искључује активности у позадини, неке визуелне ефекте, одређене функције и неке мрежне везе."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Да би се смањила потрошња података, Уштеда података спречава неке апликације да шаљу или примају податке у позадини. Апликација коју тренутно користите може да приступа подацима, али ће то чинити ређе. На пример, слике се неће приказивати док их не додирнете."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Желите да укључите Уштеду података?"</string>
@@ -2003,7 +2006,7 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Апликација <xliff:g id="APP_NAME_0">%1$s</xliff:g> тренутно није доступна. <xliff:g id="APP_NAME_1">%2$s</xliff:g> управља доступношћу."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Сазнајте више"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Опозови паузирање апликације"</string>
- <string name="work_mode_off_title" msgid="961171256005852058">"Укључити пословне апликације?"</string>
+ <string name="work_mode_off_title" msgid="961171256005852058">"Укључујете пословне апликације?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Приступајте пословним апликацијама и обавештењима"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Укључи"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Апликација није доступна"</string>
@@ -2126,7 +2129,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Потврди"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Искључи"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Сазнајте више"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Побољшана обавештења су заменила Android прилагодљива обавештења у Android-у 12. Ова функција показује предложене радње и одговоре и организује обавештења.\n\nПобољшана обавештења могу да приступају садржају обавештења, укључујући личне податке попут имена контаката и порука. Ова функција може и да одбацује обавештења или да одговара на њих, на пример, да се јавља на телефонске позиве и контролише режим Не узнемиравај."</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Побољшана обавештења су заменила Android прилагодљива обавештења у Android-у 12. Ова функција показује предложене радње и одговоре, и организује обавештења.\n\nПобољшана обавештења могу да приступају садржају обавештења, укључујући личне податке попут имена контаката и порука. Ова функција може и да одбацује обавештења или да одговара на њих, на пример, да се јавља на телефонске позиве и контролише режим Не узнемиравај."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Обавештење о информацијама Рутинског режима"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батерија ће се можда испразнити пре уобичајеног пуњења"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Уштеда батерије је активирана да би се продужило трајање батерије"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 944c868..f5e1f81 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administratören uppdaterade paketet"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administratören raderade paketet"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"I batterisparläget aktiveras mörkt tema medan bakgrundsaktivitet, vissa visuella effekter och funktioner samt vissa nätverksanslutningar begränsas eller inaktiveras."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"I batterisparläget aktiveras mörkt tema medan bakgrundsaktivitet, vissa visuella effekter och funktioner samt vissa nätverksanslutningar begränsas eller inaktiveras."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Med Databesparing kan du minska dataanvändningen genom att hindra en del appar från att skicka eller ta emot data i bakgrunden. Appar som du använder kan komma åt data, men det sker kanske inte lika ofta. Detta innebär t.ex. att bilder inte visas förrän du trycker på dem."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Vill du aktivera Databesparing?"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 41c4c0d..c05f866 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Imesasishwa na msimamizi wako"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Imefutwa na msimamizi wako"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Sawa"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Kiokoa Betri huwasha Mandhari meusi na kudhibiti au kuzima shughuli za chinichini, baadhi ya madoido yanayoonekana, vipengele fulani na baadhi ya miunganisho ya mtandao."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Kiokoa Betri huwasha Mandhari meusi na kudhibiti au kuzima shughuli za chinichini, baadhi ya madoido yanayoonekana, vipengele fulani na baadhi ya miunganisho ya mtandao."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Ili kusaidia kupunguza matumizi ya data, Kiokoa Data huzuia baadhi ya programu kupokea na kutuma data chinichini. Programu ambayo unatumia sasa inaweza kufikia data, lakini si kila wakati. Kwa mfano, haitaonyesha picha hadi utakapozifungua."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Ungependa Kuwasha Kiokoa Data?"</string>
@@ -1971,7 +1974,7 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> haipatikani kwa sasa. Inasimamiwa na <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Pata maelezo zaidi"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Acha kusimamisha programu"</string>
- <string name="work_mode_off_title" msgid="961171256005852058">"Utawasha programu za kazini?"</string>
+ <string name="work_mode_off_title" msgid="961171256005852058">"Iwashe programu za kazini?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Pata uwezo wa kufikia arifa na programu zako za kazini"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Washa"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Programu haipatikani"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 6fc392a..9be38c9 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"உங்கள் நிர்வாகி புதுப்பித்துள்ளார்"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"உங்கள் நிர்வாகி நீக்கியுள்ளார்"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"சரி"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"பேட்டரி சேமிப்பான் அம்சம் டார்க் தீமை இயக்குவதோடு பின்னணிச் செயல்பாடு, சில விஷுவல் எஃபக்ட்கள், குறிப்பிட்ட அம்சங்கள், சில நெட்வொர்க் இணைப்புகள் ஆகியவற்றைக் கட்டுப்படுத்தும் அல்லது முடக்கும்."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"பேட்டரி சேமிப்பான் டார்க் தீமினை ஆன் செய்து பின்னணிச் செயல்பாடு, சில விஷுவல் எஃபெக்ட்கள், குறிப்பிட்ட அம்சங்கள், சில நெட்வொர்க் இணைப்புகள் ஆகியவற்றைக் கட்டுப்படுத்தும் அல்லது ஆஃப் செய்யும்."</string>
<string name="data_saver_description" msgid="4995164271550590517">"டேட்டா உபயோகத்தைக் குறைப்பதற்கு உதவ, பின்புலத்தில் டேட்டாவை அனுப்புவது அல்லது பெறுவதிலிருந்து சில ஆப்ஸை டேட்டா சேமிப்பான் தடுக்கும். தற்போது பயன்படுத்தும் ஆப்ஸானது எப்போதாவது டேட்டாவை அணுகலாம். எடுத்துக்காட்டாக, படங்களை நீங்கள் தட்டும் வரை அவை காட்டப்படாது."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"டேட்டா சேமிப்பானை இயக்கவா?"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 4a2c0f9..d910224 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -247,7 +247,7 @@
<string name="global_action_power_off" msgid="4404936470711393203">"పవర్ ఆఫ్ చేయి"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"పవర్"</string>
<string name="global_action_restart" msgid="4678451019561687074">"రీస్టార్ట్ చేయి"</string>
- <string name="global_action_emergency" msgid="1387617624177105088">"అత్యవసరం"</string>
+ <string name="global_action_emergency" msgid="1387617624177105088">"ఎమర్జెన్సీ"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"బగ్ నివేదిక"</string>
<string name="global_action_logout" msgid="6093581310002476511">"సెషన్ను ముగించు"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"స్క్రీన్షాట్"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"మీ నిర్వాహకులు నవీకరించారు"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"మీ నిర్వాహకులు తొలగించారు"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"సరే"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేసి, బ్యాక్గ్రౌండ్ యాక్టివిటీ, కొన్ని విజువల్ ఎఫెక్ట్లు, నిర్దిష్ట ఫీచర్లు, ఇంకా కొన్ని నెట్వర్క్ కనెక్షన్లను పరిమితం చేస్తుంది లేదా ఆఫ్ చేస్తుంది."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేసి, బ్యాక్గ్రౌండ్ యాక్టివిటీ, కొన్ని విజువల్ ఎఫెక్ట్లు, నిర్దిష్ట ఫీచర్లు, ఇంకా కొన్ని నెట్వర్క్ కనెక్షన్లను పరిమితం చేస్తుంది లేదా ఆఫ్ చేస్తుంది."</string>
<string name="data_saver_description" msgid="4995164271550590517">"డేటా వినియోగాన్ని తగ్గించడంలో డేటా సేవర్ సహాయకరంగా ఉంటుంది. బ్యాక్గ్రౌండ్లో కొన్ని యాప్లు డేటాను పంపకుండా లేదా స్వీకరించకుండా నిరోధిస్తుంది. మీరు ప్రస్తుతం ఉపయోగిస్తోన్న యాప్, డేటాను యాక్సెస్ చేయగలదు. కానీ తక్కువ సార్లు మాత్రమే అలా చేయవచ్చు. ఉదాహరణకు, మీరు నొక్కే వరకు ఫోటోలు ప్రదర్శించబడవు."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"డేటా సేవర్ను ఆన్ చేయాలా?"</string>
@@ -2157,7 +2160,7 @@
<string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"ఈ కంటెంట్ వర్క్ యాప్తో తెరవడం సాధ్యం కాదు"</string>
<string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"ఈ కంటెంట్ వ్యక్తిగత యాప్తో షేర్ చేయడం సాధ్యం కాదు"</string>
<string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"ఈ కంటెంట్ వ్యక్తిగత యాప్తో తెరవడం సాధ్యం కాదు"</string>
- <string name="resolver_turn_on_work_apps" msgid="884910835250037247">"కార్యాలయ ప్రొఫైల్ పాజ్ చేయబడింది"</string>
+ <string name="resolver_turn_on_work_apps" msgid="884910835250037247">"వర్క్ ప్రొఫైల్ పాజ్ చేయబడింది"</string>
<string name="resolver_switch_on_work" msgid="463709043650610420">"ఆన్ చేయడానికి ట్యాప్ చేయి"</string>
<string name="resolver_no_work_apps_available" msgid="3298291360133337270">"వర్క్ యాప్లు లేవు"</string>
<string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"వ్యక్తిగత యాప్లు లేవు"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 58dc371..b6c6ed5c2 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"อัปเดตโดยผู้ดูแลระบบ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ลบโดยผู้ดูแลระบบ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ตกลง"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"โหมดประหยัดแบตเตอรี่จะเปิดธีมมืดและจำกัดหรือปิดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง ฟีเจอร์บางส่วน และการเชื่อมต่อบางเครือข่าย"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"โหมดประหยัดแบตเตอรี่จะเปิดธีมมืดและจำกัดหรือปิดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง ฟีเจอร์บางส่วน และการเชื่อมต่อบางเครือข่าย"</string>
<string name="data_saver_description" msgid="4995164271550590517">"เพื่อช่วยลดปริมาณการใช้อินเทอร์เน็ต โปรแกรมประหยัดอินเทอร์เน็ตจะช่วยป้องกันไม่ให้บางแอปส่งหรือรับข้อมูลโดยการใช้อินเทอร์เน็ตอยู่เบื้องหลัง แอปที่คุณกำลังใช้งานสามารถเข้าถึงอินเทอร์เน็ตได้ แต่อาจไม่บ่อยเท่าเดิม ตัวอย่างเช่น ภาพต่างๆ จะไม่แสดงจนกว่าคุณจะแตะที่ภาพเหล่านั้น"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"เปิดการประหยัดอินเทอร์เน็ตไหม"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 4ab94db..4ea1da9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1458,6 +1458,10 @@
<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="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 6702ce4..306fc82 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1458,6 +1458,10 @@
<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="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 96c80fd..baf4a44 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1407,7 +1407,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Виявлено аналоговий аксесуар для аудіо"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Під’єднаний пристрій несумісний із цим телефоном. Торкніться, щоб дізнатися більше."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"Налагодження USB підключено"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"Торкніться, щоб вимкнути налагодження через USB"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Торкніться, щоб вимкнути його"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Виберіть, щоб вимкнути налагодження за USB"</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Активне налагодження через Wi-Fi"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Натисніть, щоб вимкнути налагодження через Wi-Fi"</string>
@@ -1498,6 +1498,10 @@
<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="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 88adb50..8318021 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"آپ کے منتظم کے ذریعے اپ ڈیٹ کیا گیا"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"آپ کے منتظم کے ذریعے حذف کیا گیا"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ٹھیک ہے"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"بیٹری سیور گہری تھیم کو آن کرتی ہے اور پس منظر کی سرگرمی، کچھ بصری اثرات، مخصوص خصوصیات اور کچھ نیٹ ورک کنکشنز کو محدود یا آف کرتی ہے۔"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"بیٹری سیور گہری تھیم کو آن کرتی ہے اور پس منظر کی سرگرمی، کچھ بصری اثرات، مخصوص خصوصیات اور کچھ نیٹ ورک کنکشنز کو محدود یا آف کرتی ہے۔"</string>
<string name="data_saver_description" msgid="4995164271550590517">"ڈیٹا کے استعمال کو کم کرنے میں مدد کیلئے، ڈیٹا سیور پس منظر میں کچھ ایپس کو ڈیٹا بھیجنے یا موصول کرنے سے روکتی ہے۔ آپ جو ایپ فی الحال استعمال کر رہے ہیں وہ ڈیٹا تک رسائی کر سکتی ہے مگر ہو سکتا ہے ایسا اکثر نہ ہو۔ اس کا مطلب مثال کے طور پر یہ ہو سکتا ہے کہ تصاویر تھپتھپانے تک ظاہر نہ ہوں۔"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ڈیٹا سیور آن کریں؟"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index aea9b57..4c30b54 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1355,7 +1355,7 @@
<string name="no_permissions" msgid="5729199278862516390">"Hech qanday ruxsat talab qilinmaydi"</string>
<string name="perm_costs_money" msgid="749054595022779685">"buning uchun sizdan haq olinishi mumkin"</string>
<string name="dlg_ok" msgid="5103447663504839312">"OK"</string>
- <string name="usb_charging_notification_title" msgid="1674124518282666955">"Bu qurilma USB orqali quvvatlanmoqda"</string>
+ <string name="usb_charging_notification_title" msgid="1674124518282666955">"Qurilma USB orqali quvvatlanmoqda"</string>
<string name="usb_supplying_notification_title" msgid="5378546632408101811">"USB orqali ulangan qurilma quvvatlanmoqda"</string>
<string name="usb_mtp_notification_title" msgid="1065989144124499810">"USB orqali fayl uzatish yoqildi"</string>
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB orqali PTP rejimi yoqildi"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administrator tomonidan yangilangan"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administrator tomonidan o‘chirilgan"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Quvvat tejash funksiyasi Tungi mavzuni va cheklovlarni yoqadi hamda fondagi harakatlar, vizual effektlar, ayrim funksiyalar va tarmoq aloqalari kabi boshqa funksiyalarni faolsizlantiradi yoki cheklaydi."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Quvvat tejash funksiyasi Tungi mavzuni va cheklovlarni yoqadi hamda fondagi harakatlar, vizual effektlar, ayrim funksiyalar va tarmoq aloqalari kabi boshqa funksiyalarni faolsizlantiradi yoki cheklaydi."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Trafik tejash rejimida ayrim ilovalar uchun orqa fonda internetdan foydalanish imkoniyati cheklanadi. Siz ishlatayotgan ilova zaruratga qarab internet-trafik sarflashi mumkin, biroq cheklangan miqdorda. Masalan, rasmlar ustiga bosmaguningizcha ular yuklanmaydi."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Trafik tejash yoqilsinmi?"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7df4ebc..61aba14 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1575,7 +1579,7 @@
<string name="storage_usb" msgid="2391213347883616886">"Bộ lưu trữ USB"</string>
<string name="extract_edit_menu_button" msgid="63954536535863040">"Chỉnh sửa"</string>
<string name="data_usage_warning_title" msgid="9034893717078325845">"Cảnh báo dữ liệu"</string>
- <string name="data_usage_warning_body" msgid="1669325367188029454">"Bạn đã sử dụng <xliff:g id="APP">%s</xliff:g> dữ liệu"</string>
+ <string name="data_usage_warning_body" msgid="1669325367188029454">"Bạn đã dùng <xliff:g id="APP">%s</xliff:g> dữ liệu"</string>
<string name="data_usage_mobile_limit_title" msgid="3911447354393775241">"Đã đạt đến giới hạn dữ liệu di động"</string>
<string name="data_usage_wifi_limit_title" msgid="2069698056520812232">"Đã đạt tới g.hạn dữ liệu Wi-Fi"</string>
<string name="data_usage_limit_body" msgid="3567699582000085710">"Đã tạm dừng dữ liệu đối với chu kỳ còn lại của bạn"</string>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Do quản trị viên của bạn cập nhật"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Do quản trị viên của bạn xóa"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Trình tiết kiệm pin sẽ bật Giao diện tối, đồng thời hạn chế hoặc tắt hoạt động chạy trong nền, một số hiệu ứng hình ảnh, các tính năng nhất định và một số đường kết nối mạng."</string>
<string name="battery_saver_description" msgid="8518809702138617167">"Trình tiết kiệm pin sẽ bật Giao diện tối, đồng thời hạn chế hoặc tắt hoạt động chạy trong nền, một số hiệu ứng hình ảnh, các tính năng nhất định, và một số kết nối mạng."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Để giúp giảm mức sử dụng dữ liệu, Trình tiết kiệm dữ liệu sẽ chặn một số ứng dụng gửi hoặc nhận dữ liệu trong nền. Ứng dụng mà bạn hiện sử dụng có thể dùng dữ liệu nhưng tần suất sẽ giảm. Ví dụ: hình ảnh sẽ không hiển thị cho đến khi bạn nhấn vào hình ảnh đó."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Bật Trình tiết kiệm dữ liệu?"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 1198cf6..7fefe74 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"已由您的管理员更新"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"已由您的管理员删除"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"确定"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"在省电模式下,系统会启用深色主题,并限制或关闭后台活动、某些视觉效果、特定功能和部分网络连接。"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"在省电模式下,系统会启用深色主题,并限制或关闭后台活动、某些视觉效果、特定功能和部分网络连接。"</string>
<string name="data_saver_description" msgid="4995164271550590517">"为了减少流量消耗,流量节省程序会阻止某些应用在后台收发数据。您当前使用的应用可以收发数据,但频率可能会降低。举例而言,这可能意味着图片只有在您点按之后才会显示。"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"要开启流量节省程序吗?"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 576ec6a..457f0d5 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"已由您的管理員更新"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"已由您的管理員刪除"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"好"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"「省電模式」會開啟深色主題背景,並限制或關閉背景活動、部分視覺效果、特定功能和部分網絡連線。"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"「省電模式」會開啟深色主題背景,並限制或關閉背景活動、部分視覺效果、特定功能和部分網絡連線。"</string>
<string name="data_saver_description" msgid="4995164271550590517">"「數據節省模式」可防止部分應用程式在背景收發資料,以節省數據用量。您正在使用的應用程式可存取資料,但次數可能會減少。例如,圖片可能需要輕按才會顯示。"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"要開啟「數據節省模式」嗎?"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5da2ca5..82be318 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -250,7 +250,7 @@
<string name="global_action_emergency" msgid="1387617624177105088">"緊急電話"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"錯誤報告"</string>
<string name="global_action_logout" msgid="6093581310002476511">"結束"</string>
- <string name="global_action_screenshot" msgid="2610053466156478564">"擷取螢幕畫面"</string>
+ <string name="global_action_screenshot" msgid="2610053466156478564">"螢幕截圖"</string>
<string name="bugreport_title" msgid="8549990811777373050">"錯誤報告"</string>
<string name="bugreport_message" msgid="5212529146119624326">"這會收集你目前裝置狀態的相關資訊,以便透過電子郵件傳送。從錯誤報告開始建立到準備傳送的這段過程可能需要一點時間,敬請耐心等候。"</string>
<string name="bugreport_option_interactive_title" msgid="7968287837902871289">"互動式報告"</string>
@@ -1458,6 +1458,10 @@
<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="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>
@@ -1866,8 +1870,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"已由你的管理員更新"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"已由你的管理員刪除"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"確定"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (5444908404021316250) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"省電模式會開啟深色主題,並限制或關閉背景活動、某些視覺效果、特定功能和部分網路連線。"</string>
<string name="battery_saver_description" msgid="8518809702138617167">"省電模式會開啟深色主題,並限制或關閉背景活動、某些視覺效果、特定功能和部分網路連線。"</string>
<string name="data_saver_description" msgid="4995164271550590517">"「數據節省模式」可防止部分應用程式在背景收發資料,以節省數據用量。你目前使用的應用程式可以存取資料,但存取頻率可能不如平時高。舉例來說,圖片可能不會自動顯示,在你輕觸後才會顯示。"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"要開啟數據節省模式嗎?"</string>
@@ -2093,7 +2096,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"確定"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"關閉"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"瞭解詳情"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"在 Android 12 中,加強型通知功能已取代 Android 自動調整通知。這項功能可以顯示建議的操作和回覆內容,也可以整理通知。\n\n加強型通知功能可存取通知內容,包括聯絡人名稱和訊息內文等個人資訊。此外,這項功能還能關閉或回覆通知,例如接聽來電及控管「零打擾」功能。"</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"在 Android 12 中,加強型通知功能已取代 Android 自動調整通知。這項功能可以顯示建議的操作和回覆內容,也可以幫你整理通知訊息。\n\n加強型通知功能可存取通知內容,包括聯絡人名稱和訊息內文等個人資訊。此外,這項功能還能關閉或回覆通知,例如接聽來電及控管「零打擾」功能。"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"日常安排模式資訊通知"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"電池電力可能會在你平常的充電時間前耗盡"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"已啟用省電模式以延長電池續航力"</string>
@@ -2136,7 +2139,7 @@
<string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"快速設定"</string>
<string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"開啟電源對話方塊"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"螢幕鎖定"</string>
- <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"擷取螢幕畫面"</string>
+ <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"螢幕截圖"</string>
<string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"螢幕上的無障礙捷徑"</string>
<string name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" msgid="1057878690209817886">"螢幕上的無障礙捷徑選擇器"</string>
<string name="accessibility_system_action_hardware_a11y_shortcut_label" msgid="5764644187715255107">"無障礙捷徑"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 899cdd7..85cf88c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1458,6 +1458,10 @@
<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="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/config.xml b/core/res/res/values/config.xml
index bc63df6..5ac2336 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1759,6 +1759,13 @@
<item>com.android.location.fused</item>
</string-array>
+ <!-- Package name(s) of Advanced Driver Assistance applications. These packages have additional
+ management of access to location, specific to driving assistance use-cases. They must be system
+ packages. This configuration is only applicable to devices that declare
+ PackageManager.FEATURE_AUTOMOTIVE. -->
+ <string-array name="config_locationDriverAssistancePackageNames" translatable="false">
+ </string-array>
+
<!-- This string array can be overriden to enable test location providers initially. -->
<!-- Array of "[locationProviderName],[requiresNetwork],
[requiresSatellite],[requiresCell],[hasMonetaryCost],
@@ -4973,6 +4980,11 @@
<!-- List containing the allowed install sources for accessibility service. -->
<string-array name="config_accessibility_allowed_install_source" translatable="false"/>
+ <!-- Default value for Settings.ASSIST_LONG_PRESS_HOME_ENABLED -->
+ <bool name="config_assistLongPressHomeEnabledDefault">true</bool>
+ <!-- Default value for Settings.ASSIST_TOUCH_GESTURE_ENABLED -->
+ <bool name="config_assistTouchGestureEnabledDefault">true</bool>
+
<!-- The amount of dimming to apply to wallpapers with mid range luminance. 0 displays
the wallpaper at full brightness. 1 displays the wallpaper as fully black. -->
<item name="config_wallpaperDimAmount" format="float" type="dimen">0.05</item>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 766ad16..bdeff893 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3895,6 +3895,11 @@
<!-- Description of an application permission that lets it ask user to ignore battery optimizations for that app-->
<string name="permdesc_requestIgnoreBatteryOptimizations">Allows an app to ask for permission to ignore battery optimizations for that app.</string>
+ <!-- Title of an application permission that lets query all other packages. [CHAR LIMIT=NONE] -->
+ <string name="permlab_queryAllPackages">query all packages</string>
+ <!-- Description of an application permission that lets it query all other packages. [CHAR LIMIT=NONE] -->
+ <string name="permdesc_queryAllPackages">Allows an app to see all installed packages.</string>
+
<!-- Shown in the tutorial for tap twice for zoom control. -->
<string name="tutorial_double_tap_to_zoom_message_short">Tap twice for zoom control</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 49ed213..b574415 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1899,6 +1899,7 @@
<java-symbol type="array" name="radioAttributes" />
<java-symbol type="array" name="config_oemUsbModeOverride" />
<java-symbol type="array" name="config_locationProviderPackageNames" />
+ <java-symbol type="array" name="config_locationDriverAssistancePackageNames" />
<java-symbol type="array" name="config_locationExtraPackageNames" />
<java-symbol type="array" name="config_testLocationProviders" />
<java-symbol type="array" name="config_defaultNotificationVibePattern" />
@@ -4393,5 +4394,8 @@
<java-symbol type="dimen" name="starting_surface_icon_size" />
<java-symbol type="dimen" name="starting_surface_default_icon_size" />
+ <java-symbol type="bool" name="config_assistLongPressHomeEnabledDefault" />
+ <java-symbol type="bool" name="config_assistTouchGestureEnabledDefault" />
+
<java-symbol type="dimen" name="config_wallpaperDimAmount" />
</resources>
diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp
index 36cb554..5260835 100644
--- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp
+++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp
@@ -14,9 +14,11 @@
static_libs: [
"androidx.test.rules",
"junit",
+ "mockito-target-minus-junit4",
"platform-test-annotations",
"platformprotosnano",
"statsdprotolite",
+ "truth-prebuilt",
],
libs: ["android.test.runner"],
diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
index 333eebb..7f9d618 100644
--- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
+++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
@@ -17,10 +17,14 @@
import static android.os.BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.os.BatteryConsumer;
import android.os.BatteryUsageStats;
@@ -37,7 +41,6 @@
import java.util.List;
-
@SmallTest
public class BatteryUsageStatsPulledTest {
@@ -225,4 +228,75 @@
return builder.build();
}
+
+ @Test
+ public void testLargeAtomTruncated() {
+ final BatteryUsageStats.Builder builder =
+ new BatteryUsageStats.Builder(new String[0]);
+ // If not truncated, this BatteryUsageStats object would generate a proto buffer
+ // larger than 70 Kb
+ for (int i = 0; i < 20000; i++) {
+ BatteryStatsImpl.Uid mockUid = mock(BatteryStatsImpl.Uid.class);
+ when(mockUid.getUid()).thenReturn(i);
+ builder.getOrCreateUidBatteryConsumerBuilder(mockUid)
+ .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_FOREGROUND, 1 * 60 * 1000)
+ .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_BACKGROUND, 2 * 60 * 1000)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, 30)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 40);
+ }
+
+ // Add a UID with much larger battery footprint
+ final int largeConsumerUid = 20001;
+ BatteryStatsImpl.Uid largeConsumerMockUid = mock(BatteryStatsImpl.Uid.class);
+ when(largeConsumerMockUid.getUid()).thenReturn(largeConsumerUid);
+ builder.getOrCreateUidBatteryConsumerBuilder(largeConsumerMockUid)
+ .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_FOREGROUND, 10 * 60 * 1000)
+ .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_BACKGROUND, 20 * 60 * 1000)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, 300)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 400);
+
+ // Add a UID with much larger usage duration
+ final int highUsageUid = 20002;
+ BatteryStatsImpl.Uid highUsageMockUid = mock(BatteryStatsImpl.Uid.class);
+ when(highUsageMockUid.getUid()).thenReturn(highUsageUid);
+ builder.getOrCreateUidBatteryConsumerBuilder(highUsageMockUid)
+ .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_FOREGROUND, 60 * 60 * 1000)
+ .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_BACKGROUND, 120 * 60 * 1000)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, 3)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 4);
+
+ BatteryUsageStats batteryUsageStats = builder.build();
+ final byte[] bytes = batteryUsageStats.getStatsProto();
+ assertThat(bytes.length).isGreaterThan(40000);
+ assertThat(bytes.length).isLessThan(50000);
+
+ BatteryUsageStatsAtomsProto proto;
+ try {
+ proto = BatteryUsageStatsAtomsProto.parseFrom(bytes);
+ } catch (InvalidProtocolBufferNanoException e) {
+ fail("Invalid proto: " + e);
+ return;
+ }
+
+ boolean largeConsumerIncluded = false;
+ boolean highUsageAppIncluded = false;
+ for (int i = 0; i < proto.uidBatteryConsumers.length; i++) {
+ if (proto.uidBatteryConsumers[i].uid == largeConsumerUid) {
+ largeConsumerIncluded = true;
+ BatteryUsageStatsAtomsProto.BatteryConsumerData consumerData =
+ proto.uidBatteryConsumers[i].batteryConsumerData;
+ assertThat(consumerData.totalConsumedPowerDeciCoulombs / 36)
+ .isEqualTo(300 + 400);
+ } else if (proto.uidBatteryConsumers[i].uid == highUsageUid) {
+ highUsageAppIncluded = true;
+ BatteryUsageStatsAtomsProto.BatteryConsumerData consumerData =
+ proto.uidBatteryConsumers[i].batteryConsumerData;
+ assertThat(consumerData.totalConsumedPowerDeciCoulombs / 36)
+ .isEqualTo(3 + 4);
+ }
+ }
+
+ assertThat(largeConsumerIncluded).isTrue();
+ assertThat(highUsageAppIncluded).isTrue();
+ }
}
diff --git a/core/tests/coretests/apks/overlay_config/Android.bp b/core/tests/coretests/apks/overlay_config/Android.bp
index 9c971fd..0777523 100644
--- a/core/tests/coretests/apks/overlay_config/Android.bp
+++ b/core/tests/coretests/apks/overlay_config/Android.bp
@@ -10,4 +10,5 @@
android_test_helper_app {
name: "FrameworksCoreTests_overlay_config",
defaults: ["FrameworksCoreTests_apks_defaults"],
+ min_sdk_version: "20",
}
diff --git a/core/tests/coretests/apks/overlay_config/AndroidManifest.xml b/core/tests/coretests/apks/overlay_config/AndroidManifest.xml
index b15338e..092a575 100644
--- a/core/tests/coretests/apks/overlay_config/AndroidManifest.xml
+++ b/core/tests/coretests/apks/overlay_config/AndroidManifest.xml
@@ -19,7 +19,7 @@
<application android:hasCode="false" />
- <uses-sdk android:targetSdkVersion="21"/>
+ <uses-sdk android:minSdkVersion="20" android:targetSdkVersion="21"/>
<overlay android:targetPackage="android"
android:targetName="TestResources" />
diff --git a/core/tests/coretests/apks/overlay_config/OWNERS b/core/tests/coretests/apks/overlay_config/OWNERS
new file mode 100644
index 0000000..3e79d8f
--- /dev/null
+++ b/core/tests/coretests/apks/overlay_config/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/res/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/content/res/OWNERS b/core/tests/coretests/src/com/android/internal/content/res/OWNERS
new file mode 100644
index 0000000..3e79d8f
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/content/res/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/res/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java
similarity index 98%
rename from core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
rename to core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java
index a01459f..c50c818 100644
--- a/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
+++ b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.internal.content;
+package com.android.internal.content.res;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
diff --git a/core/tests/coretests/src/com/android/internal/content/OverlayConfigTest.java b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java
similarity index 99%
rename from core/tests/coretests/src/com/android/internal/content/OverlayConfigTest.java
rename to core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java
index dee118f..178c2dd 100644
--- a/core/tests/coretests/src/com/android/internal/content/OverlayConfigTest.java
+++ b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.internal.content;
+package com.android.internal.content.res;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/data/etc/car/com.android.car.shell.xml b/data/etc/car/com.android.car.shell.xml
index d48d751..c058cb9 100644
--- a/data/etc/car/com.android.car.shell.xml
+++ b/data/etc/car/com.android.car.shell.xml
@@ -33,5 +33,8 @@
<permission name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY" />
<permission name="android.car.permission.USE_CAR_EVS_CAMERA" />
<permission name="android.car.permission.MONITOR_CAR_EVS_STATUS" />
+ <permission name="android.car.permission.USE_CAR_WATCHDOG" />
+ <permission name="android.car.permission.COLLECT_CAR_WATCHDOG_METRICS" />
+ <permission name="android.car.permission.CONTROL_CAR_WATCHDOG_CONFIG" />
</privapp-permissions>
</permissions>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index a64129e..756425e 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -293,4 +293,7 @@
be able to connect to the internet when such a proxy is in use, since
all outgoing connections originate from this app. -->
<allow-in-power-save-except-idle package="com.android.proxyhandler" />
+
+ <!-- Allow IMS service entitlement app to schedule jobs to run when app in background. -->
+ <allow-in-power-save-except-idle package="com.android.imsserviceentitlement" />
</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 99d7167..04291e3 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -488,6 +488,7 @@
<permission name="android.permission.BRIGHTNESS_SLIDER_USAGE" />
<permission name="android.permission.ACCESS_AMBIENT_LIGHT_STATS" />
<permission name="android.permission.CONFIGURE_DISPLAY_BRIGHTNESS" />
+ <permission name="android.permission.GET_TOP_ACTIVITY_INFO" />
<permission name="android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER" />
<permission name="android.permission.SET_MEDIA_KEY_LISTENER" />
<permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS" />
@@ -497,6 +498,8 @@
<privapp-permissions package="com.android.statementservice">
<permission name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"/>
+ <permission name="android.permission.DOMAIN_VERIFICATION_AGENT"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
</privapp-permissions>
<privapp-permissions package="com.android.traceur">
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 1163536..d757a8c 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -39,11 +39,7 @@
<axis tag="wdth" stylevalue="100" />
<axis tag="wght" stylevalue="300" />
</font>
- <font weight="400" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="400" />
- </font>
+ <font weight="400" style="normal">RobotoStatic-Regular.ttf</font>
<font weight="500" style="normal">Roboto-Regular.ttf
<axis tag="ital" stylevalue="0" />
<axis tag="wdth" stylevalue="100" />
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index b88751a..61f7fac 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1387,6 +1387,7 @@
static {
// Preload Roboto-Regular.ttf in Zygote for improving app launch performance.
preloadFontFile("/system/fonts/Roboto-Regular.ttf");
+ preloadFontFile("/system/fonts/RobotoStatic-Regular.ttf");
String locale = SystemProperties.get("persist.sys.locale", "en-US");
String script = ULocale.addLikelySubtags(ULocale.forLanguageTag(locale)).getScript();
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 73e65c2..fe80b58 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -182,6 +182,7 @@
private Canvas mMaskCanvas;
private Matrix mMaskMatrix;
private PorterDuffColorFilter mMaskColorFilter;
+ private PorterDuffColorFilter mFocusColorFilter;
private boolean mHasValidMask;
private int mComputedRadius = -1;
@@ -330,18 +331,18 @@
private void setRippleActive(boolean active) {
if (mRippleActive != active) {
mRippleActive = active;
- }
- if (mState.mRippleStyle == STYLE_SOLID) {
- if (active) {
- tryRippleEnter();
+ if (mState.mRippleStyle == STYLE_SOLID) {
+ if (active) {
+ tryRippleEnter();
+ } else {
+ tryRippleExit();
+ }
} else {
- tryRippleExit();
- }
- } else {
- if (active) {
- startPatternedAnimation();
- } else {
- exitPatternedAnimation();
+ if (active) {
+ startPatternedAnimation();
+ } else {
+ exitPatternedAnimation();
+ }
}
}
}
@@ -938,7 +939,7 @@
final int alpha = Math.min((int) (origAlpha * newOpacity + 0.5f), 255);
if (alpha > 0) {
ColorFilter origFilter = p.getColorFilter();
- p.setColorFilter(mMaskColorFilter);
+ p.setColorFilter(mFocusColorFilter);
p.setAlpha(alpha);
c.drawCircle(cx, cy, getComputedRadius(), p);
p.setAlpha(origAlpha);
@@ -1091,6 +1092,7 @@
if (mMaskColorFilter == null) {
mMaskColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_IN);
+ mFocusColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_IN);
}
// Draw the appropriate mask anchored to (0,0).
@@ -1219,6 +1221,8 @@
int maskColor = mState.mRippleStyle == STYLE_PATTERNED ? color : color | 0xFF000000;
if (mMaskColorFilter.getColor() != maskColor) {
mMaskColorFilter = new PorterDuffColorFilter(maskColor, mMaskColorFilter.getMode());
+ mFocusColorFilter = new PorterDuffColorFilter(color | 0xFF000000,
+ mFocusColorFilter.getMode());
}
p.setColor(color & 0xFF000000);
p.setColorFilter(mMaskColorFilter);
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index 4da2a28..67484d4 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -21,18 +21,13 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
-import android.os.Build;
-import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterCertificateChain;
-import android.security.keymaster.KeymasterDefs;
-import android.telephony.TelephonyManager;
-import android.util.ArraySet;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.nio.charset.StandardCharsets;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
+import java.security.ProviderException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
@@ -41,7 +36,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Random;
-import java.util.Set;
/**
* Utilities for attesting the device's hardware identifiers.
@@ -110,92 +104,6 @@
}
}
- @NonNull private static KeymasterArguments prepareAttestationArgumentsForDeviceId(
- Context context, @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
- DeviceIdAttestationException {
- // Verify that device ID attestation types are provided.
- if (idTypes == null) {
- throw new NullPointerException("Missing id types");
- }
-
- return prepareAttestationArguments(context, idTypes, attestationChallenge);
- }
-
- /**
- * Prepares Keymaster Arguments with attestation data.
- * @hide should only be used by KeyChain.
- */
- @NonNull public static KeymasterArguments prepareAttestationArguments(Context context,
- @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
- DeviceIdAttestationException {
- // Check method arguments, retrieve requested device IDs and prepare attestation arguments.
- if (attestationChallenge == null) {
- throw new NullPointerException("Missing attestation challenge");
- }
- final KeymasterArguments attestArgs = new KeymasterArguments();
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, attestationChallenge);
- // Return early if the caller did not request any device identifiers to be included in the
- // attestation record.
- if (idTypes == null) {
- return attestArgs;
- }
- final Set<Integer> idTypesSet = new ArraySet<>(idTypes.length);
- for (int idType : idTypes) {
- idTypesSet.add(idType);
- }
- TelephonyManager telephonyService = null;
- if (idTypesSet.contains(ID_TYPE_IMEI) || idTypesSet.contains(ID_TYPE_MEID)) {
- telephonyService = (TelephonyManager) context.getSystemService(
- Context.TELEPHONY_SERVICE);
- if (telephonyService == null) {
- throw new DeviceIdAttestationException("Unable to access telephony service");
- }
- }
- for (final Integer idType : idTypesSet) {
- switch (idType) {
- case ID_TYPE_SERIAL:
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_SERIAL,
- Build.getSerial().getBytes(StandardCharsets.UTF_8));
- break;
- case ID_TYPE_IMEI: {
- final String imei = telephonyService.getImei(0);
- if (imei == null) {
- throw new DeviceIdAttestationException("Unable to retrieve IMEI");
- }
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_IMEI,
- imei.getBytes(StandardCharsets.UTF_8));
- break;
- }
- case ID_TYPE_MEID: {
- final String meid = telephonyService.getMeid(0);
- if (meid == null) {
- throw new DeviceIdAttestationException("Unable to retrieve MEID");
- }
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MEID,
- meid.getBytes(StandardCharsets.UTF_8));
- break;
- }
- case USE_INDIVIDUAL_ATTESTATION: {
- attestArgs.addBoolean(KeymasterDefs.KM_TAG_DEVICE_UNIQUE_ATTESTATION);
- break;
- }
- default:
- throw new IllegalArgumentException("Unknown device ID type " + idType);
- }
- }
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND,
- Build.BRAND.getBytes(StandardCharsets.UTF_8));
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE,
- Build.DEVICE.getBytes(StandardCharsets.UTF_8));
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT,
- Build.PRODUCT.getBytes(StandardCharsets.UTF_8));
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER,
- Build.MANUFACTURER.getBytes(StandardCharsets.UTF_8));
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MODEL,
- Build.MODEL.getBytes(StandardCharsets.UTF_8));
- return attestArgs;
- }
-
/**
* Performs attestation of the device's identifiers. This method returns a certificate chain
* whose first element contains the requested device identifiers in an extension. The device's
@@ -229,6 +137,13 @@
@NonNull public static X509Certificate[] attestDeviceIds(Context context,
@NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
DeviceIdAttestationException {
+ if (attestationChallenge == null) {
+ throw new NullPointerException("Missing attestation challenge");
+ }
+ if (idTypes == null) {
+ throw new NullPointerException("Missing id types");
+ }
+
String keystoreAlias = generateRandomAlias();
KeyGenParameterSpec.Builder builder =
new KeyGenParameterSpec.Builder(keystoreAlias, KeyProperties.PURPOSE_SIGN)
@@ -265,6 +180,12 @@
if (e.getCause() instanceof DeviceIdAttestationException) {
throw (DeviceIdAttestationException) e.getCause();
}
+ // Illegal argument errors are wrapped up by a ProviderException. Catch those so that
+ // we can unwrap them into a more meaningful exception type for the caller.
+ if (e instanceof ProviderException
+ && e.getCause() instanceof IllegalArgumentException) {
+ throw (IllegalArgumentException) e.getCause();
+ }
throw new DeviceIdAttestationException("Unable to perform attestation", e);
}
}
diff --git a/libs/WindowManager/Shell/AndroidManifest.xml b/libs/WindowManager/Shell/AndroidManifest.xml
index 10df726..8881be7 100644
--- a/libs/WindowManager/Shell/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/AndroidManifest.xml
@@ -19,7 +19,7 @@
package="com.android.wm.shell">
<!-- System permission required by WM Shell Task Organizer. -->
<uses-permission android:name="android.permission.CAPTURE_BLACKOUT_CONTENT" />
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
</manifest>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 0e02541..6d3e0a9 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -45,10 +45,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Yuxarı 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Yuxarı 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Aşağı tam ekran"</string>
- <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Bir əlli rejimdən istifadə edilir"</string>
+ <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Birəlli rejim istifadəsi"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Çıxmaq üçün ekranın aşağısından yuxarıya doğru sürüşdürün və ya tətbiqin yuxarısında istənilən yerə toxunun"</string>
- <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Bir əlli rejimi başladın"</string>
- <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Bir əlli rejimdən çıxın"</string>
+ <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Birəlli rejim başlasın"</string>
+ <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Birəlli rejimdən çıxın"</string>
<string name="bubbles_settings_button_description" msgid="1301286017420516912">"<xliff:g id="APP_NAME">%1$s</xliff:g> yumrucuqları üçün ayarlar"</string>
<string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"Kənara çıxma"</string>
<string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"Yenidən dəstəyə əlavə edin"</string>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 0195f3d..c5e79f8 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -62,9 +62,9 @@
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Bubble schließen"</string>
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Unterhaltung nicht als Bubble anzeigen"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Bubbles zum Chatten verwenden"</string>
- <string name="bubbles_user_education_description" msgid="4215862563054175407">"Neue Unterhaltungen erscheinen als unverankerte Symbole, \"Bubbles\" genannt. Wenn du die Bubble öffnen möchtest, tippe sie an. Wenn du sie verschieben möchtest, zieh an ihr."</string>
+ <string name="bubbles_user_education_description" msgid="4215862563054175407">"Neue Unterhaltungen erscheinen als unverankerte Symbole, „Bubbles“ genannt. Wenn du eine Bubble öffnen möchtest, tippe sie an. Wenn du sie verschieben möchtest, zieh an ihr."</string>
<string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Bubble-Einstellungen festlegen"</string>
- <string name="bubbles_user_education_manage" msgid="3460756219946517198">"Tippe auf \"Verwalten\", um Bubbles für diese App zu deaktivieren"</string>
+ <string name="bubbles_user_education_manage" msgid="3460756219946517198">"Tippe auf „Verwalten“, um Bubbles für diese App zu deaktivieren"</string>
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Keine kürzlich geschlossenen Bubbles"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Hier werden aktuelle und geschlossene Bubbles angezeigt"</string>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index 23b0ed1..5949099 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -62,7 +62,7 @@
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Cerrar burbuja"</string>
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"No mostrar conversación en burbuja"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatea con burbujas"</string>
- <string name="bubbles_user_education_description" msgid="4215862563054175407">"Las conversaciones nuevas aparecen como iconos flotantes llamadas \"burbujas\". Toca para abrir la burbuja. Arrastra para moverla."</string>
+ <string name="bubbles_user_education_description" msgid="4215862563054175407">"Las conversaciones nuevas aparecen como iconos flotantes llamadas \"burbujas\". Toca una burbuja para abrirla. Arrástrala para moverla."</string>
<string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Controla las burbujas"</string>
<string name="bubbles_user_education_manage" msgid="3460756219946517198">"Toca Gestionar para desactivar las burbujas de esta aplicación"</string>
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Entendido"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index 9117413..eecc9cb 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -63,7 +63,7 @@
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ne pas afficher la conversation dans une bulle"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatter en utilisant des bulles"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Les nouvelles conversations s\'affichent sous forme d\'icônes flottantes ou bulles. Appuyez sur la bulle pour l\'ouvrir. Faites-la glisser pour la déplacer."</string>
- <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Contrôler les paramètres des bulles"</string>
+ <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Contrôlez les bulles à tout moment"</string>
<string name="bubbles_user_education_manage" msgid="3460756219946517198">"Appuyez sur \"Gérer\" pour désactiver les bulles de cette application"</string>
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Aucune bulle récente"</string>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index 34f75da..c788a03 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -62,7 +62,7 @@
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignora bolla"</string>
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Non mettere la conversazione nella bolla"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatta utilizzando le bolle"</string>
- <string name="bubbles_user_education_description" msgid="4215862563054175407">"Le nuove conversazioni vengono visualizzate come icone mobili o bolle. Tocca per aprire la bolla. Trascinala per spostarla."</string>
+ <string name="bubbles_user_education_description" msgid="4215862563054175407">"Le nuove conversazioni vengono mostrate come icone mobili o bolle. Tocca per aprire la bolla. Trascinala per spostarla."</string>
<string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Controlla le bolle quando vuoi"</string>
<string name="bubbles_user_education_manage" msgid="3460756219946517198">"Tocca Gestisci per disattivare le bolle dall\'app"</string>
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index ef5ed00..36700bd 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -63,7 +63,7 @@
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"会話をバブルで表示しない"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"チャットでバブルを使う"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"新しい会話はフローティング アイコン(バブル)として表示されます。タップするとバブルが開きます。ドラッグしてバブルを移動できます。"</string>
- <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"いつでもバブルを管理"</string>
+ <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"バブルはいつでも管理可能"</string>
<string name="bubbles_user_education_manage" msgid="3460756219946517198">"このアプリからのバブルを OFF にするには、[管理] をタップしてください"</string>
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"最近閉じたバブルはありません"</string>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index 76e4c73..6deb0b8 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -70,7 +70,7 @@
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Соңғы және жабылған қалқыма хабарлар осы жерде көрсетіледі."</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Көпіршік"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Басқару"</string>
- <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Қалқымалы анықтама өшірілді."</string>
+ <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Қалқыма хабар жабылды."</string>
<string name="restart_button_description" msgid="5887656107651190519">"Бұл қолданбаны қайта қосып, толық экранға өту үшін түртіңіз."</string>
<string name="got_it" msgid="4428750913636945527">"Түсінікті"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index 0738ed2..f0bf513 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -68,9 +68,9 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"മനസ്സിലായി"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"അടുത്തിടെയുള്ള ബബിളുകൾ ഒന്നുമില്ല"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"അടുത്തിടെയുള്ള ബബിളുകൾ, ഡിസ്മിസ് ചെയ്ത ബബിളുകൾ എന്നിവ ഇവിടെ ദൃശ്യമാവും"</string>
- <string name="notification_bubble_title" msgid="6082910224488253378">"ബബ്ൾ"</string>
+ <string name="notification_bubble_title" msgid="6082910224488253378">"ബബിൾ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"മാനേജ് ചെയ്യുക"</string>
- <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ബബ്ൾ ഡിസ്മിസ് ചെയ്തു."</string>
+ <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ബബിൾ ഡിസ്മിസ് ചെയ്തു."</string>
<string name="restart_button_description" msgid="5887656107651190519">"ഈ ആപ്പ് റീസ്റ്റാർട്ട് ചെയ്ത് പൂർണ്ണ സ്ക്രീനിലേക്ക് മാറാൻ ടാപ്പ് ചെയ്യുക."</string>
<string name="got_it" msgid="4428750913636945527">"മനസ്സിലായി"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index dddf2c1..70f03d2 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -44,7 +44,7 @@
<dimen name="pip_bottom_offset_buffer">1dp</dimen>
<!-- The corner radius for PiP window. -->
- <dimen name="pip_corner_radius">8dp</dimen>
+ <dimen name="pip_corner_radius">16dp</dimen>
<!-- The bottom margin of the PIP drag to dismiss info text shown when moving a PIP. -->
<dimen name="pip_dismiss_text_bottom_margin">24dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index a88be31..f7fb63d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -46,6 +46,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.sizecompatui.SizeCompatUIController;
import com.android.wm.shell.startingsurface.StartingWindowController;
@@ -55,6 +56,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.function.Consumer;
/**
* Unified task organizer for all components in the shell.
@@ -342,6 +344,19 @@
notifySizeCompatUI(info.getTaskInfo(), listener);
}
+ /**
+ * Take a screenshot of a task.
+ */
+ public void screenshotTask(RunningTaskInfo taskInfo, Rect crop,
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
+ final TaskAppearedInfo info = mTasks.get(taskInfo.taskId);
+ if (info == null) {
+ return;
+ }
+ ScreenshotUtils.captureLayer(info.getLeash(), crop, consumer);
+ }
+
+
@Override
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
synchronized (mLock) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java
index 176c620..798250d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java
@@ -312,6 +312,13 @@
}
/**
+ * @return a velocity considered fast
+ */
+ public float getHighVelocityPxPerSecond() {
+ return mHighVelocityPxPerSecond;
+ }
+
+ /**
* An interpolator which interpolates two interpolators with an interpolator.
*/
private static final class InterpolatorInterpolator implements Interpolator {
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 b674c68..f81f086 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
@@ -290,27 +290,6 @@
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
- // ActivityView'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.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
index 2fc696c..35a4f33 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
@@ -231,7 +231,8 @@
* Fade animation for consecutive flyouts.
*/
void animateUpdate(Bubble.FlyoutMessage flyoutMessage, float parentWidth, PointF stackPos,
- boolean hideDot) {
+ boolean hideDot, Runnable onHide) {
+ mOnHide = onHide;
final Runnable afterFadeOut = () -> {
updateFlyoutMessage(flyoutMessage, parentWidth);
// Wait for TextViews to layout with updated height.
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 d821c6f..16b8150 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
@@ -852,13 +852,6 @@
mTaskbarScrim.setAlpha(0f);
mTaskbarScrim.setVisibility(GONE);
- setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
- if (!mIsExpanded || mIsExpansionAnimating) {
- return view.onApplyWindowInsets(insets);
- }
- return view.onApplyWindowInsets(insets);
- });
-
mOrientationChangedListener =
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
mPositioner.update();
@@ -908,20 +901,16 @@
}
});
- // If the stack itself is touched, it means none of its touchable views (bubbles, flyouts,
- // ActivityViews, etc.) were touched. Collapse the stack if it's expanded.
- setOnTouchListener((view, ev) -> {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (mShowingManage) {
- showManageMenu(false /* show */);
- } else if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) {
- mStackEduView.hide(false);
- } else if (mBubbleData.isExpanded()) {
- mBubbleData.setExpanded(false);
- }
+ // If the stack itself is clicked, it means none of its touchable views (bubbles, flyouts,
+ // TaskView, etc.) were touched. Collapse the stack if it's expanded.
+ setOnClickListener(view -> {
+ if (mShowingManage) {
+ showManageMenu(false /* show */);
+ } else if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) {
+ mStackEduView.hide(false);
+ } else if (mBubbleData.isExpanded()) {
+ mBubbleData.setExpanded(false);
}
-
- return true;
});
animate()
@@ -1492,22 +1481,22 @@
mStackAnimationController.setStackPosition(mPositioner.getDefaultStartPosition());
}
- if (getBubbleCount() == 0) {
- mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
- }
-
if (bubble.getIconView() == null) {
return;
}
+ mBubbleContainer.addView(bubble.getIconView(), 0,
+ new FrameLayout.LayoutParams(mPositioner.getBubbleSize(),
+ mPositioner.getBubbleSize()));
+
+ if (getBubbleCount() == 0) {
+ mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
+ }
// Set the dot position to the opposite of the side the stack is resting on, since the stack
// resting slightly off-screen would result in the dot also being off-screen.
bubble.getIconView().setDotBadgeOnLeft(!mStackOnLeftOrWillBe /* onLeft */);
bubble.getIconView().setOnClickListener(mBubbleClickListener);
bubble.getIconView().setOnTouchListener(mBubbleTouchListener);
- mBubbleContainer.addView(bubble.getIconView(), 0,
- new FrameLayout.LayoutParams(mPositioner.getBubbleSize(),
- mPositioner.getBubbleSize()));
updateBubbleShadows(false /* showForAllBubbles */);
animateInFlyoutForBubble(bubble);
requestUpdate();
@@ -2400,7 +2389,8 @@
if (mFlyout.getVisibility() == View.VISIBLE) {
mFlyout.animateUpdate(bubble.getFlyoutMessage(), getWidth(),
- mStackAnimationController.getStackPosition(), !bubble.showDot());
+ mStackAnimationController.getStackPosition(), !bubble.showDot(),
+ mAfterFlyoutHidden /* onHide */);
} else {
mFlyout.setVisibility(INVISIBLE);
mFlyout.setupFlyoutStartingAsDot(bubble.getFlyoutMessage(),
@@ -2408,7 +2398,7 @@
mStackAnimationController.isStackOnLeftSide(),
bubble.getIconView().getDotColor() /* dotColor */,
expandFlyoutAfterDelay /* onLayoutComplete */,
- mAfterFlyoutHidden,
+ mAfterFlyoutHidden /* onHide */,
bubble.getIconView().getDotCenter(),
!bubble.showDot(),
mPositioner);
@@ -2464,6 +2454,10 @@
}
} else {
mBubbleContainer.getBoundsOnScreen(outRect);
+ // Account for the IME in the touchable region so that the touchable region of the
+ // Bubble window doesn't obscure the IME. The touchable region affects which areas
+ // of the screen can be excluded by lower windows (IME is just above the embedded task)
+ outRect.bottom -= (int) mStackAnimationController.getImeHeight();
}
if (mFlyout.getVisibility() == View.VISIBLE) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
index 8043d2b..0802fb5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
@@ -124,9 +124,6 @@
*/
private Rect mAnimatingToBounds = new Rect();
- /** Initial starting location for the stack. */
- @Nullable private BubbleStackView.RelativeStackPosition mStackStartPosition;
-
/** Whether or not the stack's start position has been set. */
private boolean mStackMovedToStartPosition = false;
@@ -532,6 +529,11 @@
mImeHeight = imeHeight;
}
+ /** Returns the current IME height that the stack is offset by. */
+ public float getImeHeight() {
+ return mImeHeight;
+ }
+
/**
* Animates the stack either away from the newly visible IME, or back to its original position
* due to the IME going away.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
index 32575fa..eea6e3c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
@@ -21,6 +21,8 @@
import android.graphics.Rect;
import android.view.SurfaceControl;
+import java.util.function.Consumer;
+
/**
* Helpers for working with screenshots.
*/
@@ -29,6 +31,60 @@
/**
* Take a screenshot of the specified SurfaceControl.
*
+ * @param sc the SurfaceControl to take a screenshot of
+ * @param crop the crop to use when capturing the screenshot
+ * @param consumer Consumer for the captured buffer
+ */
+ public static void captureLayer(SurfaceControl sc, Rect crop,
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
+ consumer.accept(SurfaceControl.captureLayers(
+ new SurfaceControl.LayerCaptureArgs.Builder(sc)
+ .setSourceCrop(crop)
+ .setCaptureSecureLayers(true)
+ .setAllowProtected(true)
+ .build()));
+ }
+
+ private static class BufferConsumer implements
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> {
+ SurfaceControl mScreenshot = null;
+ SurfaceControl.Transaction mTransaction;
+ SurfaceControl mSurfaceControl;
+ int mLayer;
+
+ BufferConsumer(SurfaceControl.Transaction t, SurfaceControl sc, int layer) {
+ mTransaction = t;
+ mSurfaceControl = sc;
+ mLayer = layer;
+ }
+
+ @Override
+ public void accept(SurfaceControl.ScreenshotHardwareBuffer buffer) {
+ if (buffer == null || buffer.getHardwareBuffer() == null) {
+ return;
+ }
+ final GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
+ buffer.getHardwareBuffer());
+ mScreenshot = new SurfaceControl.Builder()
+ .setName("ScreenshotUtils screenshot")
+ .setFormat(PixelFormat.TRANSLUCENT)
+ .setSecure(buffer.containsSecureLayers())
+ .setCallsite("ScreenshotUtils.takeScreenshot")
+ .setBLASTLayer()
+ .build();
+
+ mTransaction.setBuffer(mScreenshot, graphicBuffer);
+ mTransaction.setColorSpace(mScreenshot, buffer.getColorSpace());
+ mTransaction.reparent(mScreenshot, mSurfaceControl);
+ mTransaction.setLayer(mScreenshot, mLayer);
+ mTransaction.show(mScreenshot);
+ mTransaction.apply();
+ }
+ }
+
+ /**
+ * Take a screenshot of the specified SurfaceControl.
+ *
* @param t the transaction used to set changes on the resulting screenshot.
* @param sc the SurfaceControl to take a screenshot of
* @param crop the crop to use when capturing the screenshot
@@ -38,32 +94,8 @@
*/
public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc,
Rect crop, int layer) {
- final SurfaceControl.ScreenshotHardwareBuffer buffer = SurfaceControl.captureLayers(
- new SurfaceControl.LayerCaptureArgs.Builder(sc)
- .setSourceCrop(crop)
- .setCaptureSecureLayers(true)
- .setAllowProtected(true)
- .build()
- );
- if (buffer == null || buffer.getHardwareBuffer() == null) {
- return null;
- }
- final GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
- buffer.getHardwareBuffer());
- final SurfaceControl screenshot = new SurfaceControl.Builder()
- .setName("ScreenshotUtils screenshot")
- .setFormat(PixelFormat.TRANSLUCENT)
- .setSecure(buffer.containsSecureLayers())
- .setCallsite("ScreenshotUtils.takeScreenshot")
- .setBLASTLayer()
- .build();
-
- t.setBuffer(screenshot, graphicBuffer);
- t.setColorSpace(screenshot, buffer.getColorSpace());
- t.reparent(screenshot, sc);
- t.setLayer(screenshot, layer);
- t.show(screenshot);
- t.apply();
- return screenshot;
+ BufferConsumer consumer = new BufferConsumer(t, sc, layer);
+ captureLayer(sc, crop, consumer);
+ return consumer.mScreenshot;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 9dabec7..ef113dc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -317,11 +317,11 @@
public void locationInParentDisplayChanged(Point offset) {}
@Override
- public void insetsChanged(InsetsState insetsState) {}
+ public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) {}
@Override
public void insetsControlChanged(InsetsState insetsState,
- InsetsSourceControl[] activeControls) {}
+ InsetsSourceControl[] activeControls, boolean willMove, boolean willResize) {}
@Override
public void showInsets(int types, boolean fromIme) {}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
index ee2202a..261ff2f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
@@ -550,12 +550,14 @@
update(mDisplayController.getDisplayContext(
mContext.getDisplayId()).getResources().getConfiguration());
// Set resizable directly here because applyEnterSplit already resizes home stack.
- mHomeStackResizable = mWindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout);
+ mHomeStackResizable = mWindowManagerProxy.applyEnterSplit(mSplits,
+ mRotateSplitLayout != null ? mRotateSplitLayout : mSplitLayout);
}
public void prepareEnterSplitTransition(WindowContainerTransaction outWct) {
// Set resizable directly here because buildEnterSplit already resizes home stack.
- mHomeStackResizable = mWindowManagerProxy.buildEnterSplit(outWct, mSplits, mSplitLayout);
+ mHomeStackResizable = mWindowManagerProxy.buildEnterSplit(outWct, mSplits,
+ mRotateSplitLayout != null ? mRotateSplitLayout : mSplitLayout);
}
public void finishEnterSplitTransition(boolean minimized) {
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 49266ce..c275d50 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
@@ -71,6 +71,7 @@
"persist.debug.one_handed_offset_percentage";
private static final String ONE_HANDED_MODE_GESTURAL_OVERLAY =
"com.android.internal.systemui.onehanded.gestural";
+ private static final int OVERLAY_ENABLED_DELAY_MS = 250;
static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
@@ -493,9 +494,11 @@
setOneHandedEnabled(enabled);
// Also checks swipe to notification settings since they all need gesture overlay.
- setEnabledGesturalOverlay(
+ // 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(
enabled || mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
- mContext.getContentResolver(), mUserId));
+ mContext.getContentResolver(), mUserId)), OVERLAY_ENABLED_DELAY_MS);
}
@VisibleForTesting
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index a2c6567..c46b559 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -435,7 +435,8 @@
SurfaceControl.Transaction tx, float fraction) {
final float alpha = getStartValue() * (1 - fraction) + getEndValue() * fraction;
setCurrentValue(alpha);
- getSurfaceTransactionHelper().alpha(tx, leash, alpha);
+ getSurfaceTransactionHelper().alpha(tx, leash, alpha)
+ .round(tx, leash, shouldApplyCornerRadius());
tx.apply();
}
@@ -526,16 +527,22 @@
float angle = (1.0f - fraction) * startingAngle;
setCurrentValue(bounds);
if (inScaleTransition() || sourceHintRect == null) {
-
if (isOutPipDirection) {
getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
} else {
- getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle);
+ getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle)
+ .round(tx, leash, base, bounds);
}
} else {
final Rect insets = computeInsets(fraction);
getSurfaceTransactionHelper().scaleAndCrop(tx, leash,
initialSourceValue, bounds, insets);
+ if (shouldApplyCornerRadius()) {
+ final Rect destinationBounds = new Rect(bounds);
+ destinationBounds.inset(insets);
+ getSurfaceTransactionHelper().round(tx, leash,
+ initialContainerRect, destinationBounds);
+ }
}
if (!handlePipTransaction(leash, tx, bounds)) {
tx.apply();
@@ -564,9 +571,11 @@
x = fraction * (end.left - start.left) + start.left;
y = fraction * (end.bottom - start.top) + start.top;
}
- getSurfaceTransactionHelper().rotateAndScaleWithCrop(tx, leash,
- initialContainerRect, bounds, insets, degree, x, y, isOutPipDirection,
- rotationDelta == ROTATION_270 /* clockwise */);
+ getSurfaceTransactionHelper()
+ .rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds,
+ insets, degree, x, y, isOutPipDirection,
+ rotationDelta == ROTATION_270 /* clockwise */)
+ .round(tx, leash, initialContainerRect, bounds);
tx.apply();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
index 48a15d8..728794d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
@@ -149,10 +149,10 @@
// Shrink bounds (expand insets) in destination orientation.
if (clockwise) {
positionX -= insets.top * scale;
- positionY -= insets.left * scale;
+ positionY += insets.left * scale;
} else {
positionX += insets.top * scale;
- positionY += insets.left * scale;
+ positionY -= insets.left * scale;
}
}
mTmpTransform.setScale(scale, scale);
@@ -186,6 +186,18 @@
}
/**
+ * Operates the round corner radius on a given transaction and leash, scaled by bounds
+ * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
+ */
+ public PipSurfaceTransactionHelper round(SurfaceControl.Transaction tx, SurfaceControl leash,
+ Rect fromBounds, Rect toBounds) {
+ final float scale = (float) (Math.hypot(fromBounds.width(), fromBounds.height())
+ / Math.hypot(toBounds.width(), toBounds.height()));
+ tx.setCornerRadius(leash, mCornerRadius * scale);
+ return this;
+ }
+
+ /**
* Re-parents the snapshot to the parent's surface control and shows it.
*/
public PipSurfaceTransactionHelper reparentAndShowSurfaceSnapshot(
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 e1b198c..6451b94 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
@@ -184,6 +184,7 @@
mTaskOrganizer.applyTransaction(wct);
// The final task bounds will be applied by onFixedRotationFinished so that all
// coordinates are in new rotation.
+ mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
mDeferredAnimEndTransaction = tx;
return;
}
@@ -627,8 +628,10 @@
final Rect destinationBounds = mPipBoundsState.getBounds();
final SurfaceControl swipeToHomeOverlay = mSwipePipToHomeOverlay;
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
- mSurfaceTransactionHelper.resetScale(tx, mLeash, destinationBounds);
- mSurfaceTransactionHelper.crop(tx, mLeash, destinationBounds);
+ mSurfaceTransactionHelper
+ .resetScale(tx, mLeash, destinationBounds)
+ .crop(tx, mLeash, destinationBounds)
+ .round(tx, mLeash, isInPip());
// The animation is finished in the Launcher and here we directly apply the final touch.
applyEnterPipSyncTransaction(destinationBounds, () -> {
// Ensure menu's settled in its final bounds first.
@@ -830,10 +833,14 @@
public void onMovementBoundsChanged(Rect destinationBoundsOut, boolean fromRotation,
boolean fromImeAdjustment, boolean fromShelfAdjustment,
WindowContainerTransaction wct) {
- // note that this can be called when swiping pip to home is happening. For instance,
- // swiping an app in landscape to portrait home. skip this entirely if that's the case.
- if (mInSwipePipToHomeTransition && fromRotation) {
- if (DEBUG) Log.d(TAG, "skip onMovementBoundsChanged due to swipe-pip-to-home");
+ // 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) {
+ if (DEBUG) {
+ Log.d(TAG, "Skip onMovementBoundsChanged on rotation change"
+ + " mInSwipePipToHomeTransition=" + mInSwipePipToHomeTransition
+ + " mWaitForFixedRotation=" + mWaitForFixedRotation);
+ }
return;
}
final PipAnimationController.PipTransitionAnimator animator =
@@ -1041,7 +1048,9 @@
}
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
- mSurfaceTransactionHelper.scale(tx, mLeash, startBounds, toBounds, degrees);
+ mSurfaceTransactionHelper
+ .scale(tx, mLeash, startBounds, toBounds, degrees)
+ .round(tx, mLeash, startBounds, toBounds);
if (mPipMenuController.isMenuVisible()) {
mPipMenuController.movePipMenu(mLeash, tx, toBounds);
} else {
@@ -1216,6 +1225,7 @@
// Just a resize in PIP
taskBounds = destinationBounds;
}
+ mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
wct.setBounds(mToken, taskBounds);
wct.setBoundsChangeTransaction(mToken, tx);
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 02451c3..f6b5889 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
@@ -202,6 +202,7 @@
mSystemWindows.updateViewLayout(mPipMenuView,
getPipMenuLayoutParams(MENU_WINDOW_TITLE, destinationBounds.width(),
destinationBounds.height()));
+ updateMenuLayout(destinationBounds);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
index 604ebc0..c42750d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
@@ -684,7 +684,7 @@
// Intentionally resize here even if the current bounds match the destination bounds.
// This is so all the proper callbacks are performed.
mPipTaskOrganizer.scheduleAnimateResizePip(toBounds, duration,
- TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND, mUpdateBoundsCallback);
+ TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND, null /* updateBoundsCallback */);
setAnimatingToBounds(toBounds);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl
index f562c8f..630c8e7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl
@@ -25,6 +25,7 @@
* Notifies when Shell going to create a new starting window.
* @param taskId The task Id
* @param supportedType The starting window type
+ * @param splashScreenBackgroundColor The splash screen's background color
*/
- oneway void onTaskLaunching(int taskId, int supportedType);
+ oneway void onTaskLaunching(int taskId, int supportedType, int splashScreenBackgroundColor);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java
index c303a33..1a365fe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java
@@ -85,7 +85,7 @@
}
View iconView = view.getIconView();
- if (iconView == null) {
+ if (iconView == null || iconView.getBackground() == null) {
mIconFadeOutDuration = 0;
mIconStartAlpha = 0;
mAppRevealDelay = 0;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 1d37a12..df3fee0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -22,7 +22,10 @@
import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.app.ActivityThread;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -34,15 +37,19 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
+import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Trace;
+import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.Slog;
import android.view.SurfaceControl;
import android.view.View;
import android.window.SplashScreenView;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.palette.Palette;
import com.android.internal.graphics.palette.Quantizer;
import com.android.internal.graphics.palette.VariationalKMeansQuantizer;
@@ -51,6 +58,9 @@
import java.util.List;
import java.util.function.Consumer;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
/**
* Util class to create the view for a splash screen content.
@@ -76,9 +86,12 @@
private int mBrandingImageWidth;
private int mBrandingImageHeight;
private int mMainWindowShiftLength;
+ private int mLastPackageContextConfigHash;
private final TransactionPool mTransactionPool;
private final SplashScreenWindowAttrs mTmpAttrs = new SplashScreenWindowAttrs();
private final Handler mSplashscreenWorkerHandler;
+ @VisibleForTesting
+ final ColorCache mColorCache;
SplashscreenContentDrawer(Context context, TransactionPool pool) {
mContext = context;
@@ -92,6 +105,7 @@
new HandlerThread("wmshell.splashworker", THREAD_PRIORITY_TOP_APP_BOOST);
shellSplashscreenWorkerThread.start();
mSplashscreenWorkerHandler = shellSplashscreenWorkerThread.getThreadHandler();
+ mColorCache = new ColorCache(mContext, mSplashscreenWorkerHandler);
}
/**
@@ -183,17 +197,26 @@
updateDensity();
getWindowAttrs(context, mTmpAttrs);
- final StartingWindowViewBuilder builder = new StartingWindowViewBuilder();
- final int themeBGColor = peekWindowBGColor(context, this.mTmpAttrs);
+ mLastPackageContextConfigHash = context.getResources().getConfiguration().hashCode();
+ final int themeBGColor = mColorCache.getWindowColor(ai.packageName,
+ mLastPackageContextConfigHash, mTmpAttrs.mWindowBgColor, mTmpAttrs.mWindowBgResId,
+ () -> peekWindowBGColor(context, mTmpAttrs)).mBgColor;
// TODO (b/173975965) Tracking the performance on improved splash screen.
- return builder
- .setContext(context)
+ return new StartingWindowViewBuilder(context, ai)
.setWindowBGColor(themeBGColor)
.makeEmptyView(emptyView)
- .setActivityInfo(ai)
.build();
}
+ private static <T> T safeReturnAttrDefault(UnaryOperator<T> getMethod, T def) {
+ try {
+ return getMethod.apply(def);
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Get attribute fail, return default: " + e.getMessage());
+ return def;
+ }
+ }
+
/**
* Get the {@link SplashScreenWindowAttrs} from {@code context} and fill them into
* {@code attrs}.
@@ -202,16 +225,18 @@
final TypedArray typedArray = context.obtainStyledAttributes(
com.android.internal.R.styleable.Window);
attrs.mWindowBgResId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
- attrs.mWindowBgColor = typedArray.getColor(
- R.styleable.Window_windowSplashScreenBackground, Color.TRANSPARENT);
- attrs.mReplaceIcon = typedArray.getDrawable(
- R.styleable.Window_windowSplashScreenAnimatedIcon);
- attrs.mAnimationDuration = typedArray.getInt(
- R.styleable.Window_windowSplashScreenAnimationDuration, 0);
- attrs.mBrandingImage = typedArray.getDrawable(
- R.styleable.Window_windowSplashScreenBrandingImage);
- attrs.mIconBgColor = typedArray.getColor(
- R.styleable.Window_windowSplashScreenIconBackgroundColor, Color.TRANSPARENT);
+ attrs.mWindowBgColor = safeReturnAttrDefault((def) -> typedArray.getColor(
+ R.styleable.Window_windowSplashScreenBackground, def),
+ Color.TRANSPARENT);
+ attrs.mReplaceIcon = safeReturnAttrDefault((def) -> typedArray.getDrawable(
+ R.styleable.Window_windowSplashScreenAnimatedIcon), null);
+ attrs.mAnimationDuration = safeReturnAttrDefault((def) -> typedArray.getInt(
+ R.styleable.Window_windowSplashScreenAnimationDuration, def), 0);
+ attrs.mBrandingImage = safeReturnAttrDefault((def) -> typedArray.getDrawable(
+ R.styleable.Window_windowSplashScreenBrandingImage), null);
+ attrs.mIconBgColor = safeReturnAttrDefault((def) -> typedArray.getColor(
+ R.styleable.Window_windowSplashScreenIconBackgroundColor, def),
+ Color.TRANSPARENT);
typedArray.recycle();
if (DEBUG) {
Slog.d(TAG, "window attributes color: "
@@ -232,50 +257,30 @@
}
private class StartingWindowViewBuilder {
- private ActivityInfo mActivityInfo;
- private Context mContext;
- private boolean mEmptyView;
+ private final Context mContext;
+ private final ActivityInfo mActivityInfo;
- // result
- private boolean mBuildComplete = false;
- private SplashScreenView mCachedResult;
+ private boolean mEmptyView;
private int mThemeColor;
private Drawable mFinalIconDrawable;
private int mFinalIconSize = mIconSize;
+ StartingWindowViewBuilder(@NonNull Context context, @NonNull ActivityInfo aInfo) {
+ mContext = context;
+ mActivityInfo = aInfo;
+ }
+
StartingWindowViewBuilder setWindowBGColor(@ColorInt int background) {
mThemeColor = background;
- mBuildComplete = false;
return this;
}
StartingWindowViewBuilder makeEmptyView(boolean empty) {
mEmptyView = empty;
- mBuildComplete = false;
- return this;
- }
-
- StartingWindowViewBuilder setActivityInfo(ActivityInfo ai) {
- mActivityInfo = ai;
- mBuildComplete = false;
- return this;
- }
-
- StartingWindowViewBuilder setContext(Context context) {
- mContext = context;
- mBuildComplete = false;
return this;
}
SplashScreenView build() {
- if (mBuildComplete) {
- return mCachedResult;
- }
- if (mContext == null || mActivityInfo == null) {
- Slog.e(TAG, "Unable to create StartingWindowView, lack of materials!");
- return null;
- }
-
Drawable iconDrawable;
final int animationDuration;
if (mEmptyView) {
@@ -292,7 +297,9 @@
final int densityDpi = mContext.getResources().getDisplayMetrics().densityDpi;
final int scaledIconDpi =
(int) (0.5f + iconScale * densityDpi * NO_BACKGROUND_SCALE);
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "getIcon");
iconDrawable = mIconProvider.getIcon(mActivityInfo, scaledIconDpi);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (iconDrawable == null) {
iconDrawable = mContext.getPackageManager().getDefaultActivityIcon();
}
@@ -306,9 +313,7 @@
animationDuration = 0;
}
- mCachedResult = fillViewWithIcon(mFinalIconSize, mFinalIconDrawable, animationDuration);
- mBuildComplete = true;
- return mCachedResult;
+ return fillViewWithIcon(mFinalIconSize, mFinalIconDrawable, animationDuration);
}
private void createIconDrawable(Drawable iconDrawable, boolean legacy) {
@@ -331,28 +336,20 @@
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "processAdaptiveIcon");
- final AdaptiveIconDrawable adaptiveIconDrawable =
- (AdaptiveIconDrawable) iconDrawable;
- final DrawableColorTester backIconTester =
- new DrawableColorTester(adaptiveIconDrawable.getBackground());
-
+ final AdaptiveIconDrawable adaptiveIconDrawable = (AdaptiveIconDrawable) iconDrawable;
final Drawable iconForeground = adaptiveIconDrawable.getForeground();
- final DrawableColorTester foreIconTester =
- new DrawableColorTester(iconForeground, true /* filterTransparent */);
-
- final boolean foreComplex = foreIconTester.isComplexColor();
- final int foreMainColor = foreIconTester.getDominateColor();
+ final ColorCache.IconColor iconColor = mColorCache.getIconColor(
+ mActivityInfo.packageName, mActivityInfo.getIconResource(),
+ mLastPackageContextConfigHash,
+ () -> new DrawableColorTester(iconForeground, true /* filterTransparent */),
+ () -> new DrawableColorTester(adaptiveIconDrawable.getBackground()));
if (DEBUG) {
- Slog.d(TAG, "foreground complex color? " + foreComplex + " main color: "
- + Integer.toHexString(foreMainColor));
- }
- final boolean backComplex = backIconTester.isComplexColor();
- final int backMainColor = backIconTester.getDominateColor();
- if (DEBUG) {
- Slog.d(TAG, "background complex color? " + backComplex + " main color: "
- + Integer.toHexString(backMainColor));
- Slog.d(TAG, "theme color? " + Integer.toHexString(mThemeColor));
+ Slog.d(TAG, "FgMainColor=" + Integer.toHexString(iconColor.mFgColor)
+ + " BgMainColor=" + Integer.toHexString(iconColor.mBgColor)
+ + " IsBgComplex=" + iconColor.mIsBgComplex
+ + " FromCache=" + (iconColor.mReuseCount > 0)
+ + " ThemeColor=" + Integer.toHexString(mThemeColor));
}
// Only draw the foreground of AdaptiveIcon to the splash screen if below condition
@@ -363,17 +360,17 @@
// C. The background of the adaptive icon is grayscale, and the foreground of the
// adaptive icon forms a certain contrast with the theme color.
// D. Didn't specify icon background color.
- if (!backComplex && mTmpAttrs.mIconBgColor == Color.TRANSPARENT
- && (isRgbSimilarInHsv(mThemeColor, backMainColor)
- || (backIconTester.isGrayscale()
- && !isRgbSimilarInHsv(mThemeColor, foreMainColor)))) {
+ if (!iconColor.mIsBgComplex && mTmpAttrs.mIconBgColor == Color.TRANSPARENT
+ && (isRgbSimilarInHsv(mThemeColor, iconColor.mBgColor)
+ || (iconColor.mIsBgGrayscale
+ && !isRgbSimilarInHsv(mThemeColor, iconColor.mFgColor)))) {
if (DEBUG) {
Slog.d(TAG, "makeSplashScreenContentView: choose fg icon");
}
// Reference AdaptiveIcon description, outer is 108 and inner is 72, so we
// scale by 192/160 if we only draw adaptiveIcon's foreground.
final float noBgScale =
- foreIconTester.nonTransparentRatio() < ENLARGE_FOREGROUND_ICON_THRESHOLD
+ iconColor.mFgNonTransparentRatio < ENLARGE_FOREGROUND_ICON_THRESHOLD
? NO_BACKGROUND_SCALE : 1f;
// Using AdaptiveIconDrawable here can help keep the shape consistent with the
// current settings.
@@ -410,7 +407,6 @@
}
if (mEmptyView) {
splashScreenView.setNotCopyable();
- splashScreenView.setRevealAnimationSupported(false);
}
splashScreenView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
@@ -491,9 +487,14 @@
drawable = layerDrawable.getDrawable(0);
}
}
- mColorChecker = drawable instanceof ColorDrawable
- ? new SingleColorTester((ColorDrawable) drawable)
- : new ComplexDrawableTester(drawable, filterTransparent);
+ if (drawable == null) {
+ mColorChecker = new SingleColorTester(
+ (ColorDrawable) createDefaultBackgroundDrawable());
+ } else {
+ mColorChecker = drawable instanceof ColorDrawable
+ ? new SingleColorTester((ColorDrawable) drawable)
+ : new ComplexDrawableTester(drawable, filterTransparent);
+ }
}
public float nonTransparentRatio() {
@@ -689,6 +690,150 @@
}
}
+ /** Cache the result of {@link DrawableColorTester} to reduce expensive calculation. */
+ @VisibleForTesting
+ static class ColorCache extends BroadcastReceiver {
+ /**
+ * The color may be different according to resource id and configuration (e.g. night mode),
+ * so this allows to cache more than one color per package.
+ */
+ private static final int CACHE_SIZE = 2;
+
+ /** The computed colors of packages. */
+ private final ArrayMap<String, Colors> mColorMap = new ArrayMap<>();
+
+ private static class Colors {
+ final WindowColor[] mWindowColors = new WindowColor[CACHE_SIZE];
+ final IconColor[] mIconColors = new IconColor[CACHE_SIZE];
+ }
+
+ private static class Cache {
+ /** The hash used to check whether this cache is hit. */
+ final int mHash;
+
+ /** The number of times this cache has been reused. */
+ int mReuseCount;
+
+ Cache(int hash) {
+ mHash = hash;
+ }
+ }
+
+ static class WindowColor extends Cache {
+ final int mBgColor;
+
+ WindowColor(int hash, int bgColor) {
+ super(hash);
+ mBgColor = bgColor;
+ }
+ }
+
+ static class IconColor extends Cache {
+ final int mFgColor;
+ final int mBgColor;
+ final boolean mIsBgComplex;
+ final boolean mIsBgGrayscale;
+ final float mFgNonTransparentRatio;
+
+ IconColor(int hash, int fgColor, int bgColor, boolean isBgComplex,
+ boolean isBgGrayscale, float fgNonTransparentRatio) {
+ super(hash);
+ mFgColor = fgColor;
+ mBgColor = bgColor;
+ mIsBgComplex = isBgComplex;
+ mIsBgGrayscale = isBgGrayscale;
+ mFgNonTransparentRatio = fgNonTransparentRatio;
+ }
+ }
+
+ ColorCache(Context context, Handler handler) {
+ // This includes reinstall and uninstall.
+ final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme(IntentFilter.SCHEME_PACKAGE);
+ context.registerReceiverAsUser(this, UserHandle.ALL, filter,
+ null /* broadcastPermission */, handler);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final Uri packageUri = intent.getData();
+ if (packageUri != null) {
+ mColorMap.remove(packageUri.getEncodedSchemeSpecificPart());
+ }
+ }
+
+ /**
+ * Gets the existing cache if the hash matches. If null is returned, the caller can use
+ * outLeastUsedIndex to put the new cache.
+ */
+ private static <T extends Cache> T getCache(T[] caches, int hash, int[] outLeastUsedIndex) {
+ int minReuseCount = Integer.MAX_VALUE;
+ for (int i = 0; i < CACHE_SIZE; i++) {
+ final T cache = caches[i];
+ if (cache == null) {
+ // Empty slot has the highest priority to put new cache.
+ minReuseCount = -1;
+ outLeastUsedIndex[0] = i;
+ continue;
+ }
+ if (cache.mHash == hash) {
+ cache.mReuseCount++;
+ return cache;
+ }
+ if (cache.mReuseCount < minReuseCount) {
+ minReuseCount = cache.mReuseCount;
+ outLeastUsedIndex[0] = i;
+ }
+ }
+ return null;
+ }
+
+ @NonNull WindowColor getWindowColor(String packageName, int configHash, int windowBgColor,
+ int windowBgResId, IntSupplier windowBgColorSupplier) {
+ Colors colors = mColorMap.get(packageName);
+ int hash = 31 * configHash + windowBgColor;
+ hash = 31 * hash + windowBgResId;
+ final int[] leastUsedIndex = { 0 };
+ if (colors != null) {
+ final WindowColor windowColor = getCache(colors.mWindowColors, hash,
+ leastUsedIndex);
+ if (windowColor != null) {
+ return windowColor;
+ }
+ } else {
+ colors = new Colors();
+ mColorMap.put(packageName, colors);
+ }
+ final WindowColor windowColor = new WindowColor(hash, windowBgColorSupplier.getAsInt());
+ colors.mWindowColors[leastUsedIndex[0]] = windowColor;
+ return windowColor;
+ }
+
+ @NonNull IconColor getIconColor(String packageName, int configHash, int iconResId,
+ Supplier<DrawableColorTester> fgColorTesterSupplier,
+ Supplier<DrawableColorTester> bgColorTesterSupplier) {
+ Colors colors = mColorMap.get(packageName);
+ final int hash = configHash * 31 + iconResId;
+ final int[] leastUsedIndex = { 0 };
+ if (colors != null) {
+ final IconColor iconColor = getCache(colors.mIconColors, hash, leastUsedIndex);
+ if (iconColor != null) {
+ return iconColor;
+ }
+ } else {
+ colors = new Colors();
+ mColorMap.put(packageName, colors);
+ }
+ final DrawableColorTester fgTester = fgColorTesterSupplier.get();
+ final DrawableColorTester bgTester = bgColorTesterSupplier.get();
+ final IconColor iconColor = new IconColor(hash, fgTester.getDominateColor(),
+ bgTester.getDominateColor(), bgTester.isComplexColor(), bgTester.isGrayscale(),
+ fgTester.nonTransparentRatio());
+ colors.mIconColors[leastUsedIndex[0]] = iconColor;
+ return iconColor;
+ }
+ }
+
/**
* Create and play the default exit animation for splash screen view.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index ff91d82..4d33cb0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -17,6 +17,7 @@
package com.android.wm.shell.startingsurface;
import static android.content.Context.CONTEXT_RESTRICTED;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Choreographer.CALLBACK_INSETS_ANIMATION;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -31,9 +32,10 @@
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
-import android.os.SystemProperties;
+import android.os.Trace;
import android.os.UserHandle;
import android.util.Slog;
import android.util.SparseArray;
@@ -49,8 +51,10 @@
import android.window.TaskSnapshot;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
import java.util.function.Supplier;
@@ -90,6 +94,7 @@
* => WM#addView -> .. waiting for Choreographer#doFrame -> relayout -> draw -> (draw the Paint
* directly).
*/
+@ShellSplashscreenThread
public class StartingSurfaceDrawer {
static final String TAG = StartingSurfaceDrawer.class.getSimpleName();
static final boolean DEBUG_SPLASH_SCREEN = StartingWindowController.DEBUG_SPLASH_SCREEN;
@@ -98,11 +103,10 @@
private final Context mContext;
private final DisplayManager mDisplayManager;
private final ShellExecutor mSplashScreenExecutor;
- private final SplashscreenContentDrawer mSplashscreenContentDrawer;
+ @VisibleForTesting
+ final SplashscreenContentDrawer mSplashscreenContentDrawer;
private Choreographer mChoreographer;
- private static final boolean DEBUG_ENABLE_REVEAL_ANIMATION =
- SystemProperties.getBoolean("persist.debug.enable_reveal_animation", true);
/**
* @param splashScreenExecutor The thread used to control add and remove starting window.
*/
@@ -276,6 +280,7 @@
final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
final FrameLayout rootLayout = new FrameLayout(context);
final Runnable setViewSynchronized = () -> {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addSplashScreenView");
// waiting for setContentView before relayoutWindow
SplashScreenView contentView = viewSupplier.get();
final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
@@ -294,13 +299,14 @@
}
record.setSplashScreenView(contentView);
}
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
};
mSplashscreenContentDrawer.createContentView(context, emptyView, activityInfo, taskId,
viewSupplier::setView);
try {
final WindowManager wm = context.getSystemService(WindowManager.class);
- if (postAddWindow(taskId, appToken, rootLayout, wm, params)) {
+ if (addWindow(taskId, appToken, rootLayout, wm, params)) {
// We use the splash screen worker thread to create SplashScreenView while adding
// the window, as otherwise Choreographer#doFrame might be delayed on this thread.
// And since Choreographer#doFrame won't happen immediately after adding the window,
@@ -318,6 +324,12 @@
}
}
+ int getStartingWindowBackgroundColorForTask(int taskId) {
+ StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
+ if (startingWindowRecord == null || startingWindowRecord.mContentView == null) return 0;
+ return ((ColorDrawable) startingWindowRecord.mContentView.getBackground()).getColor();
+ }
+
private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
private SplashScreenView mView;
private boolean mIsViewSet;
@@ -393,10 +405,11 @@
ActivityTaskManager.getInstance().onSplashScreenViewCopyFinished(taskId, parcelable);
}
- protected boolean postAddWindow(int taskId, IBinder appToken, View view, WindowManager wm,
+ protected boolean addWindow(int taskId, IBinder appToken, View view, WindowManager wm,
WindowManager.LayoutParams params) {
boolean shouldSaveView = true;
try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
wm.addView(view, params);
} catch (WindowManager.BadTokenException e) {
// ignore
@@ -404,6 +417,7 @@
+ e.getMessage());
shouldSaveView = false;
} finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (view != null && view.getParent() == null) {
Slog.w(TAG, "view not successfully added to wm, removing view");
wm.removeViewImmediate(view);
@@ -435,24 +449,19 @@
if (DEBUG_SPLASH_SCREEN) {
Slog.v(TAG, "Removing splash screen window for task: " + taskId);
}
- if (record.mContentView != null
- && record.mContentView.isRevealAnimationSupported()) {
+ if (record.mContentView != null) {
if (playRevealAnimation) {
- if (DEBUG_ENABLE_REVEAL_ANIMATION) {
- mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
- leash, frame,
- () -> removeWindowInner(record.mDecorView, true));
- } else {
- // using the default exit animation from framework
- removeWindowInner(record.mDecorView, false);
- }
+ mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
+ leash, frame,
+ () -> removeWindowInner(record.mDecorView, true));
} else {
// the SplashScreenView has been copied to client, hide the view to skip
// default exit animation
removeWindowInner(record.mDecorView, true);
}
} else {
- // this is a blank splash screen, don't apply reveal animation
+ // shouldn't happen
+ Slog.e(TAG, "Found empty splash screen, remove!");
removeWindowInner(record.mDecorView, false);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
index cb7afc7..cffc789 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -36,12 +36,11 @@
import androidx.annotation.BinderThread;
+import com.android.internal.util.function.TriConsumer;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
-import java.util.function.BiConsumer;
-
/**
* Implementation to draw the starting window to an application, and remove the starting window
* until the application displays its own window.
@@ -68,7 +67,7 @@
private final StartingSurfaceDrawer mStartingSurfaceDrawer;
private final StartingWindowTypeAlgorithm mStartingWindowTypeAlgorithm;
- private BiConsumer<Integer, Integer> mTaskLaunchingCallback;
+ private TriConsumer<Integer, Integer, Integer> mTaskLaunchingCallback;
private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl();
private final Context mContext;
private final ShellExecutor mSplashScreenExecutor;
@@ -103,7 +102,7 @@
*
* @param listener The callback when need a starting window.
*/
- void setStartingWindowListener(BiConsumer<Integer, Integer> listener) {
+ void setStartingWindowListener(TriConsumer<Integer, Integer, Integer> listener) {
mTaskLaunchingCallback = listener;
}
@@ -121,9 +120,6 @@
final int suggestionType = mStartingWindowTypeAlgorithm.getSuggestedWindowType(
windowInfo);
final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
- if (mTaskLaunchingCallback != null && shouldSendToListener(suggestionType)) {
- mTaskLaunchingCallback.accept(runningTaskInfo.taskId, suggestionType);
- }
if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
false /* emptyView */);
@@ -137,6 +133,11 @@
} else /* suggestionType == STARTING_WINDOW_TYPE_NONE */ {
// Don't add a staring window.
}
+ if (mTaskLaunchingCallback != null && shouldSendToListener(suggestionType)) {
+ int taskId = runningTaskInfo.taskId;
+ int color = mStartingSurfaceDrawer.getStartingWindowBackgroundColorForTask(taskId);
+ mTaskLaunchingCallback.accept(taskId, suggestionType, color);
+ }
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
});
@@ -181,7 +182,7 @@
private static class IStartingWindowImpl extends IStartingWindow.Stub {
private StartingWindowController mController;
private IStartingWindowListener mListener;
- private final BiConsumer<Integer, Integer> mStartingWindowListener =
+ private final TriConsumer<Integer, Integer, Integer> mStartingWindowListener =
this::notifyIStartingWindowListener;
private final IBinder.DeathRecipient mListenerDeathRecipient =
new IBinder.DeathRecipient() {
@@ -230,13 +231,14 @@
});
}
- private void notifyIStartingWindowListener(int taskId, int supportedType) {
+ private void notifyIStartingWindowListener(int taskId, int supportedType,
+ int startingWindowBackgroundColor) {
if (mListener == null) {
return;
}
try {
- mListener.onTaskLaunching(taskId, supportedType);
+ mListener.onTaskLaunching(taskId, supportedType, startingWindowBackgroundColor);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to notify task launching", e);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java
index fbbd09f..ad9dda6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java
@@ -16,6 +16,13 @@
package com.android.wm.shell.tasksurfacehelper;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.graphics.Rect;
+import android.view.SurfaceControl;
+
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
/**
* Interface to communicate with a Task's SurfaceControl.
*/
@@ -23,4 +30,8 @@
/** Sets the METADATA_GAME_MODE for the layer corresponding to the task **/
default void setGameModeForTask(int taskId, int gameMode) {}
+
+ /** Takes a screenshot for a task **/
+ default void screenshotTask(RunningTaskInfo taskInfo, Rect crop, Executor executor,
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java
index b459b9f..064d9d1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java
@@ -16,11 +16,16 @@
package com.android.wm.shell.tasksurfacehelper;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.graphics.Rect;
import android.view.SurfaceControl;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
/**
* Intermediary controller that communicates with {@link ShellTaskOrganizer} to send commands
* to SurfaceControl.
@@ -49,6 +54,14 @@
mTaskOrganizer.setSurfaceMetadata(taskId, SurfaceControl.METADATA_GAME_MODE, gameMode);
}
+ /**
+ * Take screenshot of the specified task.
+ */
+ public void screenshotTask(RunningTaskInfo taskInfo, Rect crop,
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
+ mTaskOrganizer.screenshotTask(taskInfo, crop, consumer);
+ }
+
private class TaskSurfaceHelperImpl implements TaskSurfaceHelper {
@Override
public void setGameModeForTask(int taskId, int gameMode) {
@@ -56,5 +69,14 @@
TaskSurfaceHelperController.this.setGameModeForTask(taskId, gameMode);
});
}
+
+ @Override
+ public void screenshotTask(RunningTaskInfo taskInfo, Rect crop, Executor executor,
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
+ mMainExecutor.execute(() -> {
+ TaskSurfaceHelperController.this.screenshotTask(taskInfo, crop,
+ (t) -> executor.execute(() -> consumer.accept(t)));
+ });
+ }
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 4e3e133..903e63a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -18,25 +18,27 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Rect;
+import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.os.UserHandle;
import android.testing.TestableContext;
import android.view.SurfaceControl;
import android.view.View;
@@ -58,6 +60,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.function.IntSupplier;
+
/**
* Tests for the starting surface drawer.
*/
@@ -71,6 +75,9 @@
@Mock
private TransactionPool mTransactionPool;
+ private final Handler mTestHandler = new Handler(Looper.getMainLooper());
+ private final TestableContext mTestContext = new TestContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext());
TestStartingSurfaceDrawer mStartingSurfaceDrawer;
static final class TestStartingSurfaceDrawer extends StartingSurfaceDrawer{
@@ -83,7 +90,7 @@
}
@Override
- protected boolean postAddWindow(int taskId, IBinder appToken,
+ protected boolean addWindow(int taskId, IBinder appToken,
View view, WindowManager wm, WindowManager.LayoutParams params) {
// listen for addView
mAddWindowForTask = taskId;
@@ -101,45 +108,50 @@
}
}
+ private static class TestContext extends TestableContext {
+ TestContext(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
+ throws PackageManager.NameNotFoundException {
+ return this;
+ }
+
+ @Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ return null;
+ }
+ }
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- final TestableContext context = new TestableContext(
- InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
- final WindowManager realWindowManager = context.getSystemService(WindowManager.class);
+ final WindowManager realWindowManager = mTestContext.getSystemService(WindowManager.class);
final WindowMetrics metrics = realWindowManager.getMaximumWindowMetrics();
- context.addMockSystemService(WindowManager.class, mMockWindowManager);
+ mTestContext.addMockSystemService(WindowManager.class, mMockWindowManager);
- spyOn(context);
- spyOn(realWindowManager);
- try {
- doReturn(context).when(context)
- .createPackageContextAsUser(anyString(), anyInt(), any());
- } catch (PackageManager.NameNotFoundException e) {
- //
- }
doReturn(metrics).when(mMockWindowManager).getMaximumWindowMetrics();
doNothing().when(mMockWindowManager).addView(any(), any());
- final HandlerExecutor testExecutor =
- new HandlerExecutor(new Handler(Looper.getMainLooper()));
- mStartingSurfaceDrawer = spy(new TestStartingSurfaceDrawer(context, testExecutor,
- mTransactionPool));
+ mStartingSurfaceDrawer = spy(new TestStartingSurfaceDrawer(mTestContext,
+ new HandlerExecutor(mTestHandler), mTransactionPool));
}
@Test
public void testAddSplashScreenSurface() {
final int taskId = 1;
- final Handler mainLoop = new Handler(Looper.getMainLooper());
final StartingWindowInfo windowInfo =
createWindowInfo(taskId, android.R.style.Theme);
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, false);
- waitHandlerIdle(mainLoop);
- verify(mStartingSurfaceDrawer).postAddWindow(eq(taskId), eq(mBinder), any(), any(), any());
+ waitHandlerIdle(mTestHandler);
+ verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any());
assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
mStartingSurfaceDrawer.removeStartingWindow(windowInfo.taskInfo.taskId, null, null, false);
- waitHandlerIdle(mainLoop);
+ waitHandlerIdle(mTestHandler);
verify(mStartingSurfaceDrawer).removeWindowSynced(eq(taskId), any(), any(), eq(false));
assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, 0);
}
@@ -147,15 +159,45 @@
@Test
public void testFallbackDefaultTheme() {
final int taskId = 1;
- final Handler mainLoop = new Handler(Looper.getMainLooper());
final StartingWindowInfo windowInfo =
createWindowInfo(taskId, 0);
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, false);
- waitHandlerIdle(mainLoop);
- verify(mStartingSurfaceDrawer).postAddWindow(eq(taskId), eq(mBinder), any(), any(), any());
+ waitHandlerIdle(mTestHandler);
+ verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any());
assertNotEquals(mStartingSurfaceDrawer.mViewThemeResId, 0);
}
+ @Test
+ public void testColorCache() {
+ final String packageName = mTestContext.getPackageName();
+ final int configHash = 1;
+ final int windowBgColor = 0xff000000;
+ final int windowBgResId = 1;
+ final IntSupplier windowBgColorSupplier = () -> windowBgColor;
+ final SplashscreenContentDrawer.ColorCache colorCache =
+ mStartingSurfaceDrawer.mSplashscreenContentDrawer.mColorCache;
+ final SplashscreenContentDrawer.ColorCache.WindowColor windowColor1 =
+ colorCache.getWindowColor(packageName, configHash, windowBgColor, windowBgResId,
+ windowBgColorSupplier);
+ assertEquals(windowBgColor, windowColor1.mBgColor);
+ assertEquals(0, windowColor1.mReuseCount);
+
+ final SplashscreenContentDrawer.ColorCache.WindowColor windowColor2 =
+ colorCache.getWindowColor(packageName, configHash, windowBgColor, windowBgResId,
+ windowBgColorSupplier);
+ assertEquals(windowColor1, windowColor2);
+ assertEquals(1, windowColor1.mReuseCount);
+
+ final Intent packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED);
+ packageRemoved.setData(Uri.parse("package:" + packageName));
+ colorCache.onReceive(mTestContext, packageRemoved);
+
+ final SplashscreenContentDrawer.ColorCache.WindowColor windowColor3 =
+ colorCache.getWindowColor(packageName, configHash, windowBgColor, windowBgResId,
+ windowBgColorSupplier);
+ assertEquals(0, windowColor3.mReuseCount);
+ }
+
private StartingWindowInfo createWindowInfo(int taskId, int themeResId) {
StartingWindowInfo windowInfo = new StartingWindowInfo();
final ActivityInfo info = new ActivityInfo();
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 3a0153f..0cde3d1 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -1345,7 +1345,10 @@
}
std::unique_ptr<Theme> AssetManager2::NewTheme() {
- return std::unique_ptr<Theme>(new Theme(this));
+ constexpr size_t kInitialReserveSize = 32;
+ auto theme = std::unique_ptr<Theme>(new Theme(this));
+ theme->entries_.reserve(kInitialReserveSize);
+ return theme;
}
Theme::Theme(AssetManager2* asset_manager) : asset_manager_(asset_manager) {
@@ -1353,28 +1356,20 @@
Theme::~Theme() = default;
-namespace {
-
-struct ThemeEntry {
+struct Theme::Entry {
+ uint32_t attr_res_id;
ApkAssetsCookie cookie;
uint32_t type_spec_flags;
Res_value value;
};
-struct ThemeType {
- int entry_count;
- ThemeEntry entries[0];
+namespace {
+struct ThemeEntryKeyComparer {
+ bool operator() (const Theme::Entry& entry, uint32_t attr_res_id) const noexcept {
+ return entry.attr_res_id < attr_res_id;
+ }
};
-
-constexpr size_t kTypeCount = std::numeric_limits<uint8_t>::max() + 1;
-
-} // namespace
-
-struct Theme::Package {
- // Each element of Type will be a dynamically sized object
- // allocated to have the entries stored contiguously with the Type.
- std::array<util::unique_cptr<ThemeType>, kTypeCount> types;
-};
+} // namespace
base::expected<std::monostate, NullOrIOError> Theme::ApplyStyle(uint32_t resid, bool force) {
ATRACE_NAME("Theme::ApplyStyle");
@@ -1387,116 +1382,74 @@
// Merge the flags from this style.
type_spec_flags_ |= (*bag)->type_spec_flags;
- int last_type_idx = -1;
- int last_package_idx = -1;
- Package* last_package = nullptr;
- ThemeType* last_type = nullptr;
-
- // Iterate backwards, because each bag is sorted in ascending key ID order, meaning we will only
- // need to perform one resize per type.
- using reverse_bag_iterator = std::reverse_iterator<const ResolvedBag::Entry*>;
- const auto rbegin = reverse_bag_iterator(begin(*bag));
- for (auto it = reverse_bag_iterator(end(*bag)); it != rbegin; ++it) {
- const uint32_t attr_resid = it->key;
+ for (auto it = begin(*bag); it != end(*bag); ++it) {
+ const uint32_t attr_res_id = it->key;
// If the resource ID passed in is not a style, the key can be some other identifier that is not
// a resource ID. We should fail fast instead of operating with strange resource IDs.
- if (!is_valid_resid(attr_resid)) {
+ if (!is_valid_resid(attr_res_id)) {
return base::unexpected(std::nullopt);
}
- // We don't use the 0-based index for the type so that we can avoid doing ID validation
- // upon lookup. Instead, we keep space for the type ID 0 in our data structures. Since
- // the construction of this type is guarded with a resource ID check, it will never be
- // populated, and querying type ID 0 will always fail.
- const int package_idx = get_package_id(attr_resid);
- const int type_idx = get_type_id(attr_resid);
- const int entry_idx = get_entry_id(attr_resid);
-
- if (last_package_idx != package_idx) {
- std::unique_ptr<Package>& package = packages_[package_idx];
- if (package == nullptr) {
- package.reset(new Package());
- }
- last_package_idx = package_idx;
- last_package = package.get();
- last_type_idx = -1;
+ // DATA_NULL_EMPTY (@empty) is a valid resource value and DATA_NULL_UNDEFINED represents
+ // an absence of a valid value.
+ bool is_undefined = it->value.dataType == Res_value::TYPE_NULL &&
+ it->value.data != Res_value::DATA_NULL_EMPTY;
+ if (!force && is_undefined) {
+ continue;
}
- if (last_type_idx != type_idx) {
- util::unique_cptr<ThemeType>& type = last_package->types[type_idx];
- if (type == nullptr) {
- // Allocate enough memory to contain this entry_idx. Since we're iterating in reverse over
- // a sorted list of attributes, this shouldn't be resized again during this method call.
- type.reset(reinterpret_cast<ThemeType*>(
- calloc(sizeof(ThemeType) + (entry_idx + 1) * sizeof(ThemeEntry), 1)));
- type->entry_count = entry_idx + 1;
- } else if (entry_idx >= type->entry_count) {
- // Reallocate the memory to contain this entry_idx. Since we're iterating in reverse over
- // a sorted list of attributes, this shouldn't be resized again during this method call.
- const int new_count = entry_idx + 1;
- type.reset(reinterpret_cast<ThemeType*>(
- realloc(type.release(), sizeof(ThemeType) + (new_count * sizeof(ThemeEntry)))));
-
- // Clear out the newly allocated space (which isn't zeroed).
- memset(type->entries + type->entry_count, 0,
- (new_count - type->entry_count) * sizeof(ThemeEntry));
- type->entry_count = new_count;
+ Theme::Entry new_entry{attr_res_id, it->cookie, (*bag)->type_spec_flags, it->value};
+ auto entry_it = std::lower_bound(entries_.begin(), entries_.end(), attr_res_id,
+ ThemeEntryKeyComparer{});
+ if (entry_it != entries_.end() && entry_it->attr_res_id == attr_res_id) {
+ if (is_undefined) {
+ // DATA_NULL_UNDEFINED clears the value of the attribute in the theme only when `force` is
+ /// true.
+ entries_.erase(entry_it);
+ } else if (force) {
+ *entry_it = new_entry;
}
- last_type_idx = type_idx;
- last_type = type.get();
- }
-
- ThemeEntry& entry = last_type->entries[entry_idx];
- if (force || (entry.value.dataType == Res_value::TYPE_NULL &&
- entry.value.data != Res_value::DATA_NULL_EMPTY)) {
- entry.cookie = it->cookie;
- entry.type_spec_flags |= (*bag)->type_spec_flags;
- entry.value = it->value;
+ } else {
+ entries_.insert(entry_it, new_entry);
}
}
return {};
}
+void Theme::Rebase(AssetManager2* am, const uint32_t* style_ids, const uint8_t* force,
+ size_t style_count) {
+ ATRACE_NAME("Theme::Rebase");
+ // Reset the entries without changing the vector capacity to prevent reallocations during
+ // ApplyStyle.
+ entries_.clear();
+ asset_manager_ = am;
+ for (size_t i = 0; i < style_count; i++) {
+ ApplyStyle(style_ids[i], force[i]);
+ }
+}
+
std::optional<AssetManager2::SelectedValue> Theme::GetAttribute(uint32_t resid) const {
- int cnt = 20;
+ constexpr const uint32_t kMaxIterations = 20;
uint32_t type_spec_flags = 0u;
- do {
- const int package_idx = get_package_id(resid);
- const Package* package = packages_[package_idx].get();
- if (package != nullptr) {
- // The themes are constructed with a 1-based type ID, so no need to decrement here.
- const int type_idx = get_type_id(resid);
- const ThemeType* type = package->types[type_idx].get();
- if (type != nullptr) {
- const int entry_idx = get_entry_id(resid);
- if (entry_idx < type->entry_count) {
- const ThemeEntry& entry = type->entries[entry_idx];
- type_spec_flags |= entry.type_spec_flags;
-
- if (entry.value.dataType == Res_value::TYPE_ATTRIBUTE) {
- if (cnt > 0) {
- cnt--;
- resid = entry.value.data;
- continue;
- }
- return std::nullopt;
- }
-
- // @null is different than @empty.
- if (entry.value.dataType == Res_value::TYPE_NULL &&
- entry.value.data != Res_value::DATA_NULL_EMPTY) {
- return std::nullopt;
- }
-
- return AssetManager2::SelectedValue(entry.value.dataType, entry.value.data, entry.cookie,
- type_spec_flags, 0U /* resid */, {} /* config */);
- }
- }
+ for (uint32_t i = 0; i <= kMaxIterations; i++) {
+ auto entry_it = std::lower_bound(entries_.begin(), entries_.end(), resid,
+ ThemeEntryKeyComparer{});
+ if (entry_it == entries_.end() || entry_it->attr_res_id != resid) {
+ return std::nullopt;
}
- break;
- } while (true);
+
+ type_spec_flags |= entry_it->type_spec_flags;
+ if (entry_it->value.dataType == Res_value::TYPE_ATTRIBUTE) {
+ resid = entry_it->value.data;
+ continue;
+ }
+
+ return AssetManager2::SelectedValue(entry_it->value.dataType, entry_it->value.data,
+ entry_it->cookie, type_spec_flags, 0U /* resid */,
+ {} /* config */);
+ }
return std::nullopt;
}
@@ -1520,56 +1473,25 @@
}
void Theme::Clear() {
- type_spec_flags_ = 0u;
- for (std::unique_ptr<Package>& package : packages_) {
- package.reset();
- }
+ entries_.clear();
}
-base::expected<std::monostate, IOError> Theme::SetTo(const Theme& o) {
- if (this == &o) {
+base::expected<std::monostate, IOError> Theme::SetTo(const Theme& source) {
+ if (this == &source) {
return {};
}
- type_spec_flags_ = o.type_spec_flags_;
+ type_spec_flags_ = source.type_spec_flags_;
- if (asset_manager_ == o.asset_manager_) {
- // The theme comes from the same asset manager so all theme data can be copied exactly
- for (size_t p = 0; p < packages_.size(); p++) {
- const Package *package = o.packages_[p].get();
- if (package == nullptr) {
- // The other theme doesn't have this package, clear ours.
- packages_[p].reset();
- continue;
- }
-
- if (packages_[p] == nullptr) {
- // The other theme has this package, but we don't. Make one.
- packages_[p].reset(new Package());
- }
-
- for (size_t t = 0; t < package->types.size(); t++) {
- const ThemeType *type = package->types[t].get();
- if (type == nullptr) {
- // The other theme doesn't have this type, clear ours.
- packages_[p]->types[t].reset();
- continue;
- }
-
- // Create a new type and update it to theirs.
- const size_t type_alloc_size = sizeof(ThemeType) + (type->entry_count * sizeof(ThemeEntry));
- void *copied_data = malloc(type_alloc_size);
- memcpy(copied_data, type, type_alloc_size);
- packages_[p]->types[t].reset(reinterpret_cast<ThemeType *>(copied_data));
- }
- }
+ if (asset_manager_ == source.asset_manager_) {
+ entries_ = source.entries_;
} else {
std::map<ApkAssetsCookie, ApkAssetsCookie> src_to_dest_asset_cookies;
typedef std::map<int, int> SourceToDestinationRuntimePackageMap;
std::map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map;
// Determine which ApkAssets are loaded in both theme AssetManagers.
- const auto src_assets = o.asset_manager_->GetApkAssets();
+ const auto src_assets = source.asset_manager_->GetApkAssets();
for (size_t i = 0; i < src_assets.size(); i++) {
const ApkAssets* src_asset = src_assets[i];
@@ -1587,7 +1509,8 @@
// asset in th destination AssetManager.
SourceToDestinationRuntimePackageMap package_map;
for (const auto& loaded_package : src_asset->GetLoadedArsc()->GetPackages()) {
- const int src_package_id = o.asset_manager_->GetAssignedPackageId(loaded_package.get());
+ const int src_package_id = source.asset_manager_->GetAssignedPackageId(
+ loaded_package.get());
const int dest_package_id = asset_manager_->GetAssignedPackageId(loaded_package.get());
package_map[src_package_id] = dest_package_id;
}
@@ -1599,130 +1522,88 @@
}
// Reset the data in the destination theme.
- for (size_t p = 0; p < packages_.size(); p++) {
- if (packages_[p] != nullptr) {
- packages_[p].reset();
- }
- }
+ entries_.clear();
- for (size_t p = 0; p < packages_.size(); p++) {
- const Package *package = o.packages_[p].get();
- if (package == nullptr) {
- continue;
- }
+ for (const auto& entry : source.entries_) {
+ bool is_reference = (entry.value.dataType == Res_value::TYPE_ATTRIBUTE
+ || entry.value.dataType == Res_value::TYPE_REFERENCE
+ || entry.value.dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE
+ || entry.value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE)
+ && entry.value.data != 0x0;
- for (size_t t = 0; t < package->types.size(); t++) {
- const ThemeType *type = package->types[t].get();
- if (type == nullptr) {
+ // If the attribute value represents an attribute or reference, the package id of the
+ // value needs to be rewritten to the package id of the value in the destination.
+ uint32_t attribute_data = entry.value.data;
+ if (is_reference) {
+ // Determine the package id of the reference in the destination AssetManager.
+ auto value_package_map = src_asset_cookie_id_map.find(entry.cookie);
+ if (value_package_map == src_asset_cookie_id_map.end()) {
continue;
}
- for (size_t e = 0; e < type->entry_count; e++) {
- const ThemeEntry &entry = type->entries[e];
- if (entry.value.dataType == Res_value::TYPE_NULL &&
- entry.value.data != Res_value::DATA_NULL_EMPTY) {
- continue;
- }
+ auto value_dest_package = value_package_map->second.find(
+ get_package_id(entry.value.data));
+ if (value_dest_package == value_package_map->second.end()) {
+ continue;
+ }
- bool is_reference = (entry.value.dataType == Res_value::TYPE_ATTRIBUTE
- || entry.value.dataType == Res_value::TYPE_REFERENCE
- || entry.value.dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE
- || entry.value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE)
- && entry.value.data != 0x0;
+ attribute_data = fix_package_id(entry.value.data, value_dest_package->second);
+ }
- // If the attribute value represents an attribute or reference, the package id of the
- // value needs to be rewritten to the package id of the value in the destination.
- uint32_t attribute_data = entry.value.data;
- if (is_reference) {
- // Determine the package id of the reference in the destination AssetManager.
- auto value_package_map = src_asset_cookie_id_map.find(entry.cookie);
- if (value_package_map == src_asset_cookie_id_map.end()) {
- continue;
- }
-
- auto value_dest_package = value_package_map->second.find(
- get_package_id(entry.value.data));
- if (value_dest_package == value_package_map->second.end()) {
- continue;
- }
-
- attribute_data = fix_package_id(entry.value.data, value_dest_package->second);
- }
-
- // Find the cookie of the value in the destination. If the source apk is not loaded in the
- // destination, only copy resources that do not reference resources in the source.
- ApkAssetsCookie data_dest_cookie;
- auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie);
- if (value_dest_cookie != src_to_dest_asset_cookies.end()) {
- data_dest_cookie = value_dest_cookie->second;
- } else {
- if (is_reference || entry.value.dataType == Res_value::TYPE_STRING) {
- continue;
- } else {
- data_dest_cookie = 0x0;
- }
- }
-
- // The package id of the attribute needs to be rewritten to the package id of the
- // attribute in the destination.
- int attribute_dest_package_id = p;
- if (attribute_dest_package_id != 0x01) {
- // Find the cookie of the attribute resource id in the source AssetManager
- base::expected<FindEntryResult, NullOrIOError> attribute_entry_result =
- o.asset_manager_->FindEntry(make_resid(p, t, e), 0 /* density_override */ ,
- true /* stop_at_first_match */,
- true /* ignore_configuration */);
- if (UNLIKELY(IsIOError(attribute_entry_result))) {
- return base::unexpected(GetIOError(attribute_entry_result.error()));
- }
- if (!attribute_entry_result.has_value()) {
- continue;
- }
-
- // Determine the package id of the attribute in the destination AssetManager.
- auto attribute_package_map = src_asset_cookie_id_map.find(
- attribute_entry_result->cookie);
- if (attribute_package_map == src_asset_cookie_id_map.end()) {
- continue;
- }
- auto attribute_dest_package = attribute_package_map->second.find(
- attribute_dest_package_id);
- if (attribute_dest_package == attribute_package_map->second.end()) {
- continue;
- }
- attribute_dest_package_id = attribute_dest_package->second;
- }
-
- // Lazily instantiate the destination package.
- std::unique_ptr<Package>& dest_package = packages_[attribute_dest_package_id];
- if (dest_package == nullptr) {
- dest_package.reset(new Package());
- }
-
- // Lazily instantiate and resize the destination type.
- util::unique_cptr<ThemeType>& dest_type = dest_package->types[t];
- if (dest_type == nullptr || dest_type->entry_count < type->entry_count) {
- const size_t type_alloc_size = sizeof(ThemeType)
- + (type->entry_count * sizeof(ThemeEntry));
- void* dest_data = malloc(type_alloc_size);
- memset(dest_data, 0, type->entry_count * sizeof(ThemeEntry));
-
- // Copy the existing destination type values if the type is resized.
- if (dest_type != nullptr) {
- memcpy(dest_data, type, sizeof(ThemeType)
- + (dest_type->entry_count * sizeof(ThemeEntry)));
- }
-
- dest_type.reset(reinterpret_cast<ThemeType *>(dest_data));
- dest_type->entry_count = type->entry_count;
- }
-
- dest_type->entries[e].cookie = data_dest_cookie;
- dest_type->entries[e].value.dataType = entry.value.dataType;
- dest_type->entries[e].value.data = attribute_data;
- dest_type->entries[e].type_spec_flags = entry.type_spec_flags;
+ // Find the cookie of the value in the destination. If the source apk is not loaded in the
+ // destination, only copy resources that do not reference resources in the source.
+ ApkAssetsCookie data_dest_cookie;
+ auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie);
+ if (value_dest_cookie != src_to_dest_asset_cookies.end()) {
+ data_dest_cookie = value_dest_cookie->second;
+ } else {
+ if (is_reference || entry.value.dataType == Res_value::TYPE_STRING) {
+ continue;
+ } else {
+ data_dest_cookie = 0x0;
}
}
+
+ // The package id of the attribute needs to be rewritten to the package id of the
+ // attribute in the destination.
+ int attribute_dest_package_id = get_package_id(entry.attr_res_id);
+ if (attribute_dest_package_id != 0x01) {
+ // Find the cookie of the attribute resource id in the source AssetManager
+ base::expected<FindEntryResult, NullOrIOError> attribute_entry_result =
+ source.asset_manager_->FindEntry(entry.attr_res_id, 0 /* density_override */ ,
+ true /* stop_at_first_match */,
+ true /* ignore_configuration */);
+ if (UNLIKELY(IsIOError(attribute_entry_result))) {
+ return base::unexpected(GetIOError(attribute_entry_result.error()));
+ }
+ if (!attribute_entry_result.has_value()) {
+ continue;
+ }
+
+ // Determine the package id of the attribute in the destination AssetManager.
+ auto attribute_package_map = src_asset_cookie_id_map.find(
+ attribute_entry_result->cookie);
+ if (attribute_package_map == src_asset_cookie_id_map.end()) {
+ continue;
+ }
+ auto attribute_dest_package = attribute_package_map->second.find(
+ attribute_dest_package_id);
+ if (attribute_dest_package == attribute_package_map->second.end()) {
+ continue;
+ }
+ attribute_dest_package_id = attribute_dest_package->second;
+ }
+
+ auto dest_attr_id = make_resid(attribute_dest_package_id, get_type_id(entry.attr_res_id),
+ get_entry_id(entry.attr_res_id));
+ Theme::Entry new_entry{dest_attr_id, data_dest_cookie, entry.type_spec_flags,
+ Res_value{.dataType = entry.value.dataType,
+ .data = attribute_data}};
+
+ // Since the entries were cleared, the attribute resource id has yet been mapped to any value.
+ auto entry_it = std::lower_bound(entries_.begin(), entries_.end(), dest_attr_id,
+ ThemeEntryKeyComparer{});
+ entries_.insert(entry_it, new_entry);
}
}
return {};
@@ -1730,31 +1611,10 @@
void Theme::Dump() const {
LOG(INFO) << base::StringPrintf("Theme(this=%p, AssetManager2=%p)", this, asset_manager_);
-
- for (int p = 0; p < packages_.size(); p++) {
- auto& package = packages_[p];
- if (package == nullptr) {
- continue;
- }
-
- for (int t = 0; t < package->types.size(); t++) {
- auto& type = package->types[t];
- if (type == nullptr) {
- continue;
- }
-
- for (int e = 0; e < type->entry_count; e++) {
- auto& entry = type->entries[e];
- if (entry.value.dataType == Res_value::TYPE_NULL &&
- entry.value.data != Res_value::DATA_NULL_EMPTY) {
- continue;
- }
-
- LOG(INFO) << base::StringPrintf(" entry(0x%08x)=(0x%08x) type=(0x%02x), cookie(%d)",
- make_resid(p, t, e), entry.value.data,
- entry.value.dataType, entry.cookie);
- }
- }
+ for (auto& entry : entries_) {
+ LOG(INFO) << base::StringPrintf(" entry(0x%08x)=(0x%08x) type=(0x%02x), cookie(%d)",
+ entry.attr_res_id, entry.value.data, entry.value.dataType,
+ entry.cookie);
}
}
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index df3abf6..7d01395 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -508,13 +508,18 @@
// data failed.
base::expected<std::monostate, NullOrIOError> ApplyStyle(uint32_t resid, bool force = false);
- // Sets this Theme to be a copy of `other` if `other` has the same AssetManager as this Theme.
+ // Clears the existing theme, sets the new asset manager to use for this theme, and applies the
+ // styles in `style_ids` through repeated invocations of `ApplyStyle`.
+ void Rebase(AssetManager2* am, const uint32_t* style_ids, const uint8_t* force,
+ size_t style_count);
+
+ // Sets this Theme to be a copy of `source` if `source` has the same AssetManager as this Theme.
//
- // If `other` does not have the same AssetManager as this theme, only attributes from ApkAssets
+ // If `source` does not have the same AssetManager as this theme, only attributes from ApkAssets
// loaded into both AssetManagers will be copied to this theme.
//
// Returns an I/O error if reading resource data failed.
- base::expected<std::monostate, IOError> SetTo(const Theme& other);
+ base::expected<std::monostate, IOError> SetTo(const Theme& source);
void Clear();
@@ -546,20 +551,16 @@
void Dump() const;
+ struct Entry;
private:
DISALLOW_COPY_AND_ASSIGN(Theme);
- // Called by AssetManager2.
explicit Theme(AssetManager2* asset_manager);
- AssetManager2* asset_manager_;
+ AssetManager2* asset_manager_ = nullptr;
uint32_t type_spec_flags_ = 0u;
- // Defined in the cpp.
- struct Package;
-
- constexpr static size_t kPackageCount = std::numeric_limits<uint8_t>::max() + 1;
- std::array<std::unique_ptr<Package>, kPackageCount> packages_;
+ std::vector<Entry> entries_;
};
inline const ResolvedBag::Entry* begin(const ResolvedBag* bag) {
diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp
index f658735..77114f2 100644
--- a/libs/androidfw/tests/Theme_test.cpp
+++ b/libs/androidfw/tests/Theme_test.cpp
@@ -251,6 +251,80 @@
EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), value->flags);
}
+TEST_F(ThemeTest, ThemeRebase) {
+ AssetManager2 am;
+ am.SetApkAssets({style_assets_.get()});
+
+ AssetManager2 am_night;
+ am_night.SetApkAssets({style_assets_.get()});
+
+ ResTable_config night{};
+ night.uiMode = ResTable_config::UI_MODE_NIGHT_YES;
+ night.version = 8u;
+ am_night.SetConfiguration(night);
+
+ auto theme = am.NewTheme();
+ {
+ const uint32_t styles[] = {app::R::style::StyleOne, app::R::style::StyleDayNight};
+ const uint8_t force[] = {true, true};
+ theme->Rebase(&am, styles, force, arraysize(styles));
+ }
+
+ // attr_one in StyleDayNight force overrides StyleOne. attr_one is defined in the StyleOne.
+ auto value = theme->GetAttribute(app::R::attr::attr_one);
+ ASSERT_TRUE(value);
+ EXPECT_EQ(10u, value->data);
+ EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC | ResTable_config::CONFIG_UI_MODE |
+ ResTable_config::CONFIG_VERSION), value->flags);
+
+ // attr_two is defined in the StyleOne.
+ value = theme->GetAttribute(app::R::attr::attr_two);
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Res_value::TYPE_INT_DEC, value->type);
+ EXPECT_EQ(2u, value->data);
+ EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), value->flags);
+
+ {
+ const uint32_t styles[] = {app::R::style::StyleOne, app::R::style::StyleDayNight};
+ const uint8_t force[] = {false, false};
+ theme->Rebase(&am, styles, force, arraysize(styles));
+ }
+
+ // attr_one in StyleDayNight does not override StyleOne because `force` is false.
+ value = theme->GetAttribute(app::R::attr::attr_one);
+ ASSERT_TRUE(value);
+ EXPECT_EQ(1u, value->data);
+ EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), value->flags);
+
+ // attr_two is defined in the StyleOne.
+ value = theme->GetAttribute(app::R::attr::attr_two);
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Res_value::TYPE_INT_DEC, value->type);
+ EXPECT_EQ(2u, value->data);
+ EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), value->flags);
+
+ {
+ const uint32_t styles[] = {app::R::style::StyleOne, app::R::style::StyleDayNight};
+ const uint8_t force[] = {false, true};
+ theme->Rebase(&am_night, styles, force, arraysize(styles));
+ }
+
+ // attr_one is defined in the StyleDayNight.
+ value = theme->GetAttribute(app::R::attr::attr_one);
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Res_value::TYPE_INT_DEC, value->type);
+ EXPECT_EQ(100u, value->data);
+ EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC | ResTable_config::CONFIG_UI_MODE |
+ ResTable_config::CONFIG_VERSION), value->flags);
+
+ // attr_two is now not here.
+ value = theme->GetAttribute(app::R::attr::attr_two);
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Res_value::TYPE_INT_DEC, value->type);
+ EXPECT_EQ(2u, value->data);
+ EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), value->flags);
+}
+
TEST_F(ThemeTest, OnlyCopySameAssetsThemeWhenAssetManagersDiffer) {
AssetManager2 assetmanager_dst;
assetmanager_dst.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(),
diff --git a/libs/androidfw/tests/data/styles/R.h b/libs/androidfw/tests/data/styles/R.h
index f11486f..393a207 100644
--- a/libs/androidfw/tests/data/styles/R.h
+++ b/libs/androidfw/tests/data/styles/R.h
@@ -52,6 +52,7 @@
StyleFive = 0x7f020004u,
StyleSix = 0x7f020005u,
StyleSeven = 0x7f020006u,
+ StyleDayNight = 0x7f020007u,
};
};
};
diff --git a/libs/androidfw/tests/data/styles/res/values/styles.xml b/libs/androidfw/tests/data/styles/res/values/styles.xml
index 06774a8..fe46a3fa 100644
--- a/libs/androidfw/tests/data/styles/res/values/styles.xml
+++ b/libs/androidfw/tests/data/styles/res/values/styles.xml
@@ -89,4 +89,9 @@
<item name="android:theme">@empty</item>
</style>
+ <public type="style" name="StyleDayNight" id="0x7f020007" />
+ <style name="StyleDayNight">
+ <item name="attr_one">10</item>
+ </style>
+
</resources>
diff --git a/libs/androidfw/tests/data/styles/styles.apk b/libs/androidfw/tests/data/styles/styles.apk
index 92e9bf9..91cd654 100644
--- a/libs/androidfw/tests/data/styles/styles.apk
+++ b/libs/androidfw/tests/data/styles/styles.apk
Binary files differ
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index d8715db..0a232d6 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -87,8 +87,8 @@
cflags: [
"-Wno-unused-variable",
],
- }
- }
+ },
+ },
}
cc_defaults {
@@ -108,7 +108,6 @@
shared_libs: [
"liblog",
"libcutils",
- "libstatslog",
"libutils",
"libEGL",
"libGLESv1_CM",
@@ -122,12 +121,13 @@
"libandroidfw",
"libcrypto",
"libsync",
- "libstatspull",
- "libstatssocket",
],
static_libs: [
"libEGL_blobCache",
"libprotoutil",
+ "libstatslog_hwui",
+ "libstatspull_lazy",
+ "libstatssocket_lazy",
],
},
host: {
@@ -135,8 +135,8 @@
"libandroidfw",
"libutils",
],
- }
- }
+ },
+ },
}
cc_defaults {
@@ -220,7 +220,7 @@
srcs: [
"apex/java/**/*.java",
],
- path: "apex/java"
+ path: "apex/java",
}
// ------------------------
@@ -238,7 +238,7 @@
windows: {
enabled: true,
},
- }
+ },
}
cc_defaults {
@@ -263,7 +263,7 @@
"apex/android_region.cpp",
],
- header_libs: [ "android_graphics_apex_headers" ],
+ header_libs: ["android_graphics_apex_headers"],
target: {
android: {
@@ -278,7 +278,7 @@
srcs: [
"apex/LayoutlibLoader.cpp",
],
- }
+ },
},
}
@@ -297,7 +297,7 @@
windows: {
enabled: true,
},
- }
+ },
}
cc_defaults {
@@ -370,7 +370,7 @@
"jni/text/TextShaper.cpp",
],
- header_libs: [ "android_graphics_jni_headers" ],
+ header_libs: ["android_graphics_jni_headers"],
include_dirs: [
"external/skia/include/private",
@@ -391,7 +391,10 @@
"libjpeg",
],
- static_libs: ["libnativehelper_lazy", "libziparchive_for_incfs"],
+ static_libs: [
+ "libnativehelper_lazy",
+ "libziparchive_for_incfs",
+ ],
target: {
android: {
@@ -417,13 +420,13 @@
"libmediandk",
"libnativedisplay",
"libnativewindow",
- "libstatspull",
- "libstatssocket",
"libpdfium",
],
static_libs: [
"libgif",
- "libstatslog",
+ "libstatslog_hwui",
+ "libstatspull_lazy",
+ "libstatssocket_lazy",
],
},
host: {
@@ -434,10 +437,41 @@
static_libs: [
"libandroidfw",
],
- }
+ },
},
}
+cc_library_static {
+ name: "libstatslog_hwui",
+ generated_sources: ["statslog_hwui.cpp"],
+ generated_headers: ["statslog_hwui.h"],
+ export_generated_headers: ["statslog_hwui.h"],
+ static_libs: [
+ "libstatssocket_lazy",
+ "libstatspull_lazy",
+ ],
+}
+
+genrule {
+ name: "statslog_hwui.h",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_hwui.h --module hwui" +
+ " --namespace android,uirenderer,stats",
+ out: [
+ "statslog_hwui.h",
+ ],
+}
+
+genrule {
+ name: "statslog_hwui.cpp",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_hwui.cpp --module hwui" +
+ " --namespace android,uirenderer,stats --importHeader statslog_hwui.h",
+ out: [
+ "statslog_hwui.cpp",
+ ],
+}
+
// ------------------------
// library
// ------------------------
@@ -449,8 +483,8 @@
export_include_dirs: [
".",
],
- header_libs: [ "android_graphics_jni_headers" ],
- export_header_lib_headers: [ "android_graphics_jni_headers" ],
+ header_libs: ["android_graphics_jni_headers"],
+ export_header_lib_headers: ["android_graphics_jni_headers"],
}
cc_defaults {
@@ -514,7 +548,7 @@
target: {
android: {
- header_libs: ["libandroid_headers_private" ],
+ header_libs: ["libandroid_headers_private"],
srcs: [
"hwui/AnimatedImageThread.cpp",
@@ -572,8 +606,8 @@
export_static_lib_headers: [
"libarect",
],
- }
- }
+ },
+ },
}
cc_library {
@@ -589,7 +623,7 @@
target: {
android: {
version_script: "libhwui.map.txt",
- }
+ },
},
}
@@ -608,10 +642,10 @@
target: {
android: {
shared_libs: [
- "libgui",
- "libui",
- ],
- }
+ "libgui",
+ "libui",
+ ],
+ },
},
srcs: [
"tests/common/scenes/*.cpp",
@@ -732,5 +766,5 @@
required: [
"hwuimicro",
"hwuimacro",
- ]
+ ],
}
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 7702f9b..dd977c3 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -20,7 +20,6 @@
#include <errno.h>
#include <inttypes.h>
#include <log/log.h>
-#include <statslog.h>
#include <sys/mman.h>
#include <algorithm>
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 8a8b418..d8735ce 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -275,6 +275,14 @@
return copyResult;
}
+CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, SkBitmap* bitmap) {
+ Rect srcRect;
+ Matrix4 transform;
+ transform.loadScale(1, -1, 1);
+ transform.translate(0, -1);
+ return copyImageInto(image, transform, srcRect, bitmap);
+}
+
CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTransform,
const Rect& srcRect, SkBitmap* bitmap) {
ATRACE_CALL();
diff --git a/libs/hwui/Readback.h b/libs/hwui/Readback.h
index 4cb4bd8..da25269 100644
--- a/libs/hwui/Readback.h
+++ b/libs/hwui/Readback.h
@@ -50,6 +50,7 @@
CopyResult copySurfaceInto(ANativeWindow* window, const Rect& srcRect, SkBitmap* bitmap);
CopyResult copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap);
+ CopyResult copyImageInto(const sk_sp<SkImage>& image, SkBitmap* bitmap);
CopyResult copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 9a9e6d4..332f7e6 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -306,11 +306,17 @@
info.damageAccumulator->popTransform();
syncProperties();
- const StretchEffect& stagingStretch =
- mProperties.layerProperties().getStretchEffect();
+ auto& layerProperties = mProperties.layerProperties();
+ const StretchEffect& stagingStretch = layerProperties.getStretchEffect();
if (stagingStretch.isEmpty()) {
mStretchMask.clear();
}
+
+ if (layerProperties.getImageFilter() == nullptr) {
+ mSnapshotResult.snapshot = nullptr;
+ mTargetImageFilter = nullptr;
+ }
+
// We could try to be clever and only re-damage if the matrix changed.
// However, we don't need to worry about that. The cost of over-damaging
// here is only going to be a single additional map rect of this node
@@ -321,6 +327,44 @@
}
}
+std::optional<RenderNode::SnapshotResult> RenderNode::updateSnapshotIfRequired(
+ GrRecordingContext* context,
+ const SkImageFilter* imageFilter,
+ const SkIRect& clipBounds
+) {
+ auto* layerSurface = getLayerSurface();
+ if (layerSurface == nullptr) {
+ return std::nullopt;
+ }
+
+ sk_sp<SkImage> snapshot = layerSurface->makeImageSnapshot();
+ const auto subset = SkIRect::MakeWH(properties().getWidth(),
+ properties().getHeight());
+ // If we don't have an ImageFilter just return the snapshot
+ if (imageFilter == nullptr) {
+ mSnapshotResult.snapshot = snapshot;
+ mSnapshotResult.outSubset = subset;
+ mSnapshotResult.outOffset = SkIPoint::Make(0.0f, 0.0f);
+ mImageFilterClipBounds = clipBounds;
+ mTargetImageFilter = nullptr;
+ } else if (mSnapshotResult.snapshot == nullptr ||
+ imageFilter != mTargetImageFilter.get() ||
+ mImageFilterClipBounds != clipBounds) {
+ // Otherwise create a new snapshot with the given filter and snapshot
+ mSnapshotResult.snapshot =
+ snapshot->makeWithFilter(context,
+ imageFilter,
+ subset,
+ clipBounds,
+ &mSnapshotResult.outSubset,
+ &mSnapshotResult.outOffset);
+ mTargetImageFilter = sk_ref_sp(imageFilter);
+ mImageFilterClipBounds = clipBounds;
+ }
+
+ return mSnapshotResult;
+}
+
void RenderNode::syncDisplayList(TreeObserver& observer, TreeInfo* info) {
// Make sure we inc first so that we don't fluctuate between 0 and 1,
// which would thrash the layer cache
@@ -411,6 +455,8 @@
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 6a0b1aa..8595b6e 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -345,6 +345,16 @@
return mSkiaLayer.get() ? mSkiaLayer->layerSurface.get() : nullptr;
}
+ struct SnapshotResult {
+ sk_sp<SkImage> snapshot;
+ SkIRect outSubset;
+ SkIPoint outOffset;
+ };
+
+ std::optional<SnapshotResult> updateSnapshotIfRequired(GrRecordingContext* context,
+ const SkImageFilter* imageFilter,
+ const SkIRect& clipBounds);
+
skiapipeline::SkiaLayer* getSkiaLayer() const { return mSkiaLayer.get(); }
/**
@@ -375,6 +385,22 @@
*/
std::unique_ptr<skiapipeline::SkiaLayer> mSkiaLayer;
+ /**
+ * SkImageFilter used to create the mSnapshotResult
+ */
+ sk_sp<SkImageFilter> mTargetImageFilter;
+
+ /**
+ * Clip bounds used to create the mSnapshotResult
+ */
+ SkIRect mImageFilterClipBounds;
+
+ /**
+ * Result of the most recent snapshot with additional metadata used to
+ * determine how to draw the contents
+ */
+ SnapshotResult mSnapshotResult;
+
struct ClippedOutlineCache {
// keys
uint32_t outlineID = 0;
diff --git a/libs/hwui/effects/StretchEffect.cpp b/libs/hwui/effects/StretchEffect.cpp
index 807fb75..43f805d 100644
--- a/libs/hwui/effects/StretchEffect.cpp
+++ b/libs/hwui/effects/StretchEffect.cpp
@@ -188,7 +188,8 @@
static const float INTERPOLATION_STRENGTH_VALUE = 0.7f;
sk_sp<SkShader> StretchEffect::getShader(float width, float height,
- const sk_sp<SkImage>& snapshotImage) const {
+ const sk_sp<SkImage>& snapshotImage,
+ const SkMatrix* matrix) const {
if (isEmpty()) {
return nullptr;
}
@@ -206,8 +207,9 @@
mBuilder = std::make_unique<SkRuntimeShaderBuilder>(getStretchEffect());
}
- mBuilder->child("uContentTexture") = snapshotImage->makeShader(
- SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(SkFilterMode::kLinear));
+ mBuilder->child("uContentTexture") =
+ snapshotImage->makeShader(SkTileMode::kClamp, SkTileMode::kClamp,
+ SkSamplingOptions(SkFilterMode::kLinear), matrix);
mBuilder->uniform("uInterpolationStrength").set(&INTERPOLATION_STRENGTH_VALUE, 1);
mBuilder->uniform("uStretchAffectedDistX").set(&width, 1);
mBuilder->uniform("uStretchAffectedDistY").set(&height, 1);
diff --git a/libs/hwui/effects/StretchEffect.h b/libs/hwui/effects/StretchEffect.h
index 64fb2bf..25777c2 100644
--- a/libs/hwui/effects/StretchEffect.h
+++ b/libs/hwui/effects/StretchEffect.h
@@ -93,8 +93,8 @@
*/
float computeStretchedPositionY(float normalizedY) const;
- sk_sp<SkShader> getShader(float width, float height,
- const sk_sp<SkImage>& snapshotImage) const;
+ sk_sp<SkShader> getShader(float width, float height, const sk_sp<SkImage>& snapshotImage,
+ const SkMatrix* matrix) const;
float maxStretchAmountX = 0;
float maxStretchAmountY = 0;
diff --git a/libs/hwui/jni/GraphicsStatsService.cpp b/libs/hwui/jni/GraphicsStatsService.cpp
index 1591ffa..e32c911 100644
--- a/libs/hwui/jni/GraphicsStatsService.cpp
+++ b/libs/hwui/jni/GraphicsStatsService.cpp
@@ -24,10 +24,10 @@
#include <service/GraphicsStatsService.h>
#include <stats_event.h>
#include <stats_pull_atom_callback.h>
-#include <statslog.h>
+#include <statslog_hwui.h>
-#include "android/graphics/jni_runtime.h"
#include "GraphicsJNI.h"
+#include "android/graphics/jni_runtime.h"
namespace android {
@@ -161,14 +161,14 @@
AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, 10); // 10 milliseconds
AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, 2 * MS_PER_SEC); // 2 seconds
- AStatsManager_setPullAtomCallback(android::util::GRAPHICS_STATS, metadata,
- &graphicsStatsPullCallback, nullptr);
+ AStatsManager_setPullAtomCallback(stats::GRAPHICS_STATS, metadata, &graphicsStatsPullCallback,
+ nullptr);
AStatsManager_PullAtomMetadata_release(metadata);
}
static void nativeDestructor(JNIEnv* env, jobject javaObject) {
- AStatsManager_clearPullAtomCallback(android::util::GRAPHICS_STATS);
+ AStatsManager_clearPullAtomCallback(stats::GRAPHICS_STATS);
env->DeleteGlobalRef(gGraphicsStatsServiceObject);
gGraphicsStatsServiceObject = nullptr;
}
diff --git a/libs/hwui/jni/Picture.h b/libs/hwui/jni/Picture.h
index 536f651..87ba397 100644
--- a/libs/hwui/jni/Picture.h
+++ b/libs/hwui/jni/Picture.h
@@ -38,6 +38,7 @@
public:
explicit Picture(const Picture* src = NULL);
explicit Picture(sk_sp<SkPicture>&& src);
+ virtual ~Picture() = default;
Canvas* beginRecording(int width, int height);
@@ -49,7 +50,7 @@
static Picture* CreateFromStream(SkStream* stream);
- void serialize(SkWStream* stream) const;
+ virtual void serialize(SkWStream* stream) const;
void draw(Canvas* canvas);
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index ee7b260..d86d9ee 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -204,10 +204,9 @@
return entry;
}
-static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSkia(
- minikin::BufferReader* reader) {
- const void* buffer = reader->data();
- size_t pos = reader->pos();
+static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader);
+
+static minikin::Font::TypefaceLoader* readMinikinFontSkia(minikin::BufferReader* reader) {
// Advance reader's position.
reader->skipString(); // fontPath
reader->skip<int>(); // fontIndex
@@ -217,60 +216,63 @@
reader->skip<uint32_t>(); // expectedFontRevision
reader->skipString(); // expectedPostScriptName
}
- return [buffer, pos]() -> std::shared_ptr<minikin::MinikinFont> {
- minikin::BufferReader fontReader(buffer, pos);
- std::string_view fontPath = fontReader.readString();
- std::string path(fontPath.data(), fontPath.size());
- ATRACE_FORMAT("Loading font %s", path.c_str());
- int fontIndex = fontReader.read<int>();
- const minikin::FontVariation* axesPtr;
- uint32_t axesCount;
- std::tie(axesPtr, axesCount) = fontReader.readArray<minikin::FontVariation>();
- bool hasVerity = static_cast<bool>(fontReader.read<int8_t>());
- uint32_t expectedFontRevision;
- std::string_view expectedPostScriptName;
- if (hasVerity) {
- expectedFontRevision = fontReader.read<uint32_t>();
- expectedPostScriptName = fontReader.readString();
- }
- sk_sp<SkData> data = makeSkDataCached(path, hasVerity);
- if (data.get() == nullptr) {
- // This may happen if:
- // 1. When the process failed to open the file (e.g. invalid path or permission).
- // 2. When the process failed to map the file (e.g. hitting max_map_count limit).
- ALOGE("Failed to make SkData from file name: %s", path.c_str());
+ return &loadMinikinFontSkia;
+}
+
+static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader reader) {
+ std::string_view fontPath = reader.readString();
+ std::string path(fontPath.data(), fontPath.size());
+ ATRACE_FORMAT("Loading font %s", path.c_str());
+ int fontIndex = reader.read<int>();
+ const minikin::FontVariation* axesPtr;
+ uint32_t axesCount;
+ std::tie(axesPtr, axesCount) = reader.readArray<minikin::FontVariation>();
+ bool hasVerity = static_cast<bool>(reader.read<int8_t>());
+ uint32_t expectedFontRevision;
+ std::string_view expectedPostScriptName;
+ if (hasVerity) {
+ expectedFontRevision = reader.read<uint32_t>();
+ expectedPostScriptName = reader.readString();
+ }
+ sk_sp<SkData> data = makeSkDataCached(path, hasVerity);
+ if (data.get() == nullptr) {
+ // This may happen if:
+ // 1. When the process failed to open the file (e.g. invalid path or permission).
+ // 2. When the process failed to map the file (e.g. hitting max_map_count limit).
+ ALOGE("Failed to make SkData from file name: %s", path.c_str());
+ return nullptr;
+ }
+ const void* fontPtr = data->data();
+ size_t fontSize = data->size();
+ if (hasVerity) {
+ // Verify font metadata if verity is enabled.
+ minikin::FontFileParser parser(fontPtr, fontSize, fontIndex);
+ std::optional<uint32_t> revision = parser.getFontRevision();
+ if (!revision.has_value() || revision.value() != expectedFontRevision) {
+ LOG_ALWAYS_FATAL("Wrong font revision: %s", path.c_str());
return nullptr;
}
- const void* fontPtr = data->data();
- size_t fontSize = data->size();
- if (hasVerity) {
- // Verify font metadata if verity is enabled.
- minikin::FontFileParser parser(fontPtr, fontSize, fontIndex);
- std::optional<uint32_t> revision = parser.getFontRevision();
- if (!revision.has_value() || revision.value() != expectedFontRevision) {
- LOG_ALWAYS_FATAL("Wrong font revision: %s", path.c_str());
- return nullptr;
- }
- std::optional<std::string> psName = parser.getPostScriptName();
- if (!psName.has_value() || psName.value() != expectedPostScriptName) {
- LOG_ALWAYS_FATAL("Wrong PostScript name: %s", path.c_str());
- return nullptr;
- }
- }
- std::vector<minikin::FontVariation> axes(axesPtr, axesPtr + axesCount);
- std::shared_ptr<minikin::MinikinFont> minikinFont =
- fonts::createMinikinFontSkia(std::move(data), fontPath, fontPtr, fontSize,
- fontIndex, axes);
- if (minikinFont == nullptr) {
- ALOGE("Failed to create MinikinFontSkia: %s", path.c_str());
+ std::optional<std::string> psName = parser.getPostScriptName();
+ if (!psName.has_value() || psName.value() != expectedPostScriptName) {
+ LOG_ALWAYS_FATAL("Wrong PostScript name: %s", path.c_str());
return nullptr;
}
- return minikinFont;
- };
+ }
+ std::vector<minikin::FontVariation> axes(axesPtr, axesPtr + axesCount);
+ std::shared_ptr<minikin::MinikinFont> minikinFont = fonts::createMinikinFontSkia(
+ std::move(data), fontPath, fontPtr, fontSize, fontIndex, axes);
+ if (minikinFont == nullptr) {
+ ALOGE("Failed to create MinikinFontSkia: %s", path.c_str());
+ return nullptr;
+ }
+ return minikinFont;
}
static void writeMinikinFontSkia(minikin::BufferWriter* writer,
const minikin::MinikinFont* typeface) {
+ // When you change the format of font metadata, please update code to parse
+ // typefaceMetadataReader() in
+ // frameworks/base/libs/hwui/jni/fonts/Font.cpp too.
const std::string& path = typeface->GetFontPath();
writer->writeString(path);
writer->write<int>(typeface->GetFontIndex());
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 4289c45..602c32a 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -23,6 +23,8 @@
#include <Picture.h>
#include <Properties.h>
#include <RootRenderNode.h>
+#include <SkImagePriv.h>
+#include <SkSerialProcs.h>
#include <dlfcn.h>
#include <gui/TraceUtils.h>
#include <inttypes.h>
@@ -35,6 +37,7 @@
#include <renderthread/RenderProxy.h>
#include <renderthread/RenderTask.h>
#include <renderthread/RenderThread.h>
+#include <src/image/SkImage_Base.h>
#include <thread/CommonPool.h>
#include <utils/Color.h>
#include <utils/RefBase.h>
@@ -497,6 +500,108 @@
jobject mObject;
};
+using TextureMap = std::unordered_map<uint32_t, sk_sp<SkImage>>;
+
+struct PictureCaptureState {
+ // Each frame we move from the active map to the previous map, essentially an LRU of 1 frame
+ // This avoids repeated readbacks of the same image, but avoids artificially extending the
+ // lifetime of any particular image.
+ TextureMap mActiveMap;
+ TextureMap mPreviousActiveMap;
+};
+
+// TODO: This & Multi-SKP & Single-SKP should all be de-duped into
+// a single "make a SkPicture serailizable-safe" utility somewhere
+class PictureWrapper : public Picture {
+public:
+ PictureWrapper(sk_sp<SkPicture>&& src, const std::shared_ptr<PictureCaptureState>& state)
+ : Picture(), mPicture(std::move(src)) {
+ ATRACE_NAME("Preparing SKP for capture");
+ // Move the active to previous active
+ state->mPreviousActiveMap = std::move(state->mActiveMap);
+ state->mActiveMap.clear();
+ SkSerialProcs tempProc;
+ tempProc.fImageCtx = state.get();
+ tempProc.fImageProc = collectNonTextureImagesProc;
+ auto ns = SkNullWStream();
+ mPicture->serialize(&ns, &tempProc);
+ state->mPreviousActiveMap.clear();
+
+ // Now snapshot a copy of the active map so this PictureWrapper becomes self-sufficient
+ mTextureMap = state->mActiveMap;
+ }
+
+ static sk_sp<SkImage> imageForCache(SkImage* img) {
+ const SkBitmap* bitmap = as_IB(img)->onPeekBitmap();
+ // This is a mutable bitmap pretending to be an immutable SkImage. As we're going to
+ // actually cross thread boundaries here, make a copy so it's immutable proper
+ if (bitmap && !bitmap->isImmutable()) {
+ ATRACE_NAME("Copying mutable bitmap");
+ return SkImage::MakeFromBitmap(*bitmap);
+ }
+ if (img->isTextureBacked()) {
+ ATRACE_NAME("Readback of texture image");
+ return img->makeNonTextureImage();
+ }
+ SkPixmap pm;
+ if (img->isLazyGenerated() && !img->peekPixels(&pm)) {
+ ATRACE_NAME("Readback of HW bitmap");
+ // This is a hardware bitmap probably
+ SkBitmap bm;
+ if (!bm.tryAllocPixels(img->imageInfo())) {
+ // Failed to allocate, just see what happens
+ return sk_ref_sp(img);
+ }
+ if (RenderProxy::copyImageInto(sk_ref_sp(img), &bm)) {
+ // Failed to readback
+ return sk_ref_sp(img);
+ }
+ bm.setImmutable();
+ return SkMakeImageFromRasterBitmap(bm, kNever_SkCopyPixelsMode);
+ }
+ return sk_ref_sp(img);
+ }
+
+ static sk_sp<SkData> collectNonTextureImagesProc(SkImage* img, void* ctx) {
+ PictureCaptureState* context = reinterpret_cast<PictureCaptureState*>(ctx);
+ const uint32_t originalId = img->uniqueID();
+ auto it = context->mActiveMap.find(originalId);
+ if (it == context->mActiveMap.end()) {
+ auto pit = context->mPreviousActiveMap.find(originalId);
+ if (pit == context->mPreviousActiveMap.end()) {
+ context->mActiveMap[originalId] = imageForCache(img);
+ } else {
+ context->mActiveMap[originalId] = pit->second;
+ }
+ }
+ return SkData::MakeEmpty();
+ }
+
+ static sk_sp<SkData> serializeImage(SkImage* img, void* ctx) {
+ PictureWrapper* context = reinterpret_cast<PictureWrapper*>(ctx);
+ const uint32_t id = img->uniqueID();
+ auto iter = context->mTextureMap.find(id);
+ if (iter != context->mTextureMap.end()) {
+ img = iter->second.get();
+ }
+ return img->encodeToData();
+ }
+
+ void serialize(SkWStream* stream) const override {
+ SkSerialProcs procs;
+ procs.fImageProc = serializeImage;
+ procs.fImageCtx = const_cast<PictureWrapper*>(this);
+ procs.fTypefaceProc = [](SkTypeface* tf, void* ctx) {
+ return tf->serialize(SkTypeface::SerializeBehavior::kDoIncludeData);
+ };
+ mPicture->serialize(stream, &procs);
+ }
+
+private:
+ sk_sp<SkPicture> mPicture;
+ TextureMap mTextureMap;
+};
+
static void android_view_ThreadedRenderer_setPictureCapturedCallbackJNI(JNIEnv* env,
jobject clazz, jlong proxyPtr, jobject pictureCallback) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -507,9 +612,11 @@
LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm,
env->NewGlobalRef(pictureCallback));
- proxy->setPictureCapturedCallback([globalCallbackRef](sk_sp<SkPicture>&& picture) {
+ auto pictureState = std::make_shared<PictureCaptureState>();
+ proxy->setPictureCapturedCallback([globalCallbackRef,
+ pictureState](sk_sp<SkPicture>&& picture) {
JNIEnv* env = getenv(globalCallbackRef->vm());
- Picture* wrapper = new Picture{std::move(picture)};
+ Picture* wrapper = new PictureWrapper{std::move(picture), pictureState};
env->CallStaticVoidMethod(gHardwareRenderer.clazz,
gHardwareRenderer.invokePictureCapturedCallback,
static_cast<jlong>(reinterpret_cast<intptr_t>(wrapper)),
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index bd3b7c9..09be630 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -192,7 +192,7 @@
// Critical Native
static jlong Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- return reinterpret_cast<jlong>(font->font->typeface().get());
+ return reinterpret_cast<jlong>(font->font.get());
}
// Critical Native
@@ -224,12 +224,21 @@
// Fast Native
static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
- const std::string& path = minikinFont->GetFontPath();
- if (path.empty()) {
- return nullptr;
+ minikin::BufferReader reader = font->font->typefaceMetadataReader();
+ if (reader.data() != nullptr) {
+ std::string path = std::string(reader.readString());
+ if (path.empty()) {
+ return nullptr;
+ }
+ return env->NewStringUTF(path.c_str());
+ } else {
+ const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+ const std::string& path = minikinFont->GetFontPath();
+ if (path.empty()) {
+ return nullptr;
+ }
+ return env->NewStringUTF(path.c_str());
}
- return env->NewStringUTF(path.c_str());
}
// Fast Native
@@ -257,22 +266,43 @@
// Critical Native
static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
- return minikinFont->GetFontIndex();
+ minikin::BufferReader reader = font->font->typefaceMetadataReader();
+ if (reader.data() != nullptr) {
+ reader.skipString(); // fontPath
+ return reader.read<int>();
+ } else {
+ const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+ return minikinFont->GetFontIndex();
+ }
}
// Critical Native
static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
- return minikinFont->GetAxes().size();
+ minikin::BufferReader reader = font->font->typefaceMetadataReader();
+ if (reader.data() != nullptr) {
+ reader.skipString(); // fontPath
+ reader.skip<int>(); // fontIndex
+ return reader.readArray<minikin::FontVariation>().second;
+ } else {
+ const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+ return minikinFont->GetAxes().size();
+ }
}
// Critical Native
static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr, jint index) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
- minikin::FontVariation var = minikinFont->GetAxes().at(index);
+ minikin::BufferReader reader = font->font->typefaceMetadataReader();
+ minikin::FontVariation var;
+ if (reader.data() != nullptr) {
+ reader.skipString(); // fontPath
+ reader.skip<int>(); // fontIndex
+ var = reader.readArray<minikin::FontVariation>().first[index];
+ } else {
+ const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+ var = minikinFont->GetAxes().at(index);
+ }
uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value);
return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary);
}
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index d7546d8..7556af9 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -171,17 +171,14 @@
displayList->mProjectedOutline = nullptr;
}
-static bool layerNeedsPaint(const sk_sp<SkImage>& snapshotImage, const LayerProperties& properties,
- float alphaMultiplier, SkPaint* paint) {
+static bool layerNeedsPaint(const LayerProperties& properties, float alphaMultiplier,
+ SkPaint* paint) {
if (alphaMultiplier < 1.0f || properties.alpha() < 255 ||
properties.xferMode() != SkBlendMode::kSrcOver || properties.getColorFilter() != nullptr ||
- properties.getImageFilter() != nullptr || properties.getStretchEffect().requiresLayer()) {
+ properties.getStretchEffect().requiresLayer()) {
paint->setAlpha(properties.alpha() * alphaMultiplier);
paint->setBlendMode(properties.xferMode());
paint->setColorFilter(sk_ref_sp(properties.getColorFilter()));
-
- sk_sp<SkImageFilter> imageFilter = sk_ref_sp(properties.getImageFilter());
- paint->setImageFilter(std::move(imageFilter));
return true;
}
return false;
@@ -223,6 +220,9 @@
// TODO should we let the bound of the drawable do this for us?
const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
bool quickRejected = properties.getClipToBounds() && canvas->quickReject(bounds);
+ auto clipBounds = canvas->getLocalClipBounds();
+ SkIRect srcBounds = SkIRect::MakeWH(bounds.width(), bounds.height());
+ SkIPoint offset = SkIPoint::Make(0.0f, 0.0f);
if (!quickRejected) {
SkiaDisplayList* displayList = renderNode->getDisplayList().asSkiaDl();
const LayerProperties& layerProperties = properties.layerProperties();
@@ -230,8 +230,19 @@
if (renderNode->getLayerSurface() && mComposeLayer) {
SkASSERT(properties.effectiveLayerType() == LayerType::RenderLayer);
SkPaint paint;
- sk_sp<SkImage> snapshotImage = renderNode->getLayerSurface()->makeImageSnapshot();
- layerNeedsPaint(snapshotImage, layerProperties, alphaMultiplier, &paint);
+ layerNeedsPaint(layerProperties, alphaMultiplier, &paint);
+ const auto snapshotResult = renderNode->updateSnapshotIfRequired(
+ canvas->recordingContext(),
+ layerProperties.getImageFilter(),
+ clipBounds.roundOut()
+ );
+ sk_sp<SkImage> snapshotImage = snapshotResult->snapshot;
+ srcBounds = snapshotResult->outSubset;
+ offset = snapshotResult->outOffset;
+ const auto dstBounds = SkIRect::MakeXYWH(offset.x(),
+ offset.y(),
+ srcBounds.width(),
+ srcBounds.height());
SkSamplingOptions sampling(SkFilterMode::kLinear);
// surfaces for layers are created on LAYER_SIZE boundaries (which are >= layer size) so
@@ -257,7 +268,8 @@
TransformCanvas transformCanvas(canvas, SkBlendMode::kClear);
displayList->draw(&transformCanvas);
}
- canvas->drawImageRect(snapshotImage, bounds, bounds, sampling, &paint,
+ canvas->drawImageRect(snapshotImage, SkRect::Make(srcBounds),
+ SkRect::Make(dstBounds), sampling, &paint,
SkCanvas::kStrict_SrcRectConstraint);
} else {
// If we do have stretch effects and have hole punches,
@@ -265,6 +277,16 @@
// get the corresponding hole punches.
// Then apply the stretch to the mask and draw the mask to
// the destination
+ // Also if the stretchy container has an ImageFilter applied
+ // to it (i.e. blur) we need to take into account the offset
+ // that will be generated with this result. Ex blurs will "grow"
+ // the source image by the blur radius so we need to translate
+ // the shader by the same amount to render in the same location
+ SkMatrix matrix;
+ matrix.setTranslate(
+ offset.x() - srcBounds.left(),
+ offset.y() - srcBounds.top()
+ );
if (renderNode->hasHolePunches()) {
GrRecordingContext* context = canvas->recordingContext();
StretchMask& stretchMask = renderNode->getStretchMask();
@@ -275,11 +297,10 @@
canvas);
}
- sk_sp<SkShader> stretchShader = stretch.getShader(bounds.width(),
- bounds.height(),
- snapshotImage);
+ sk_sp<SkShader> stretchShader =
+ stretch.getShader(bounds.width(), bounds.height(), snapshotImage, &matrix);
paint.setShader(stretchShader);
- canvas->drawRect(bounds, paint);
+ canvas->drawRect(SkRect::Make(dstBounds), paint);
}
if (!renderNode->getSkiaLayer()->hasRenderedSinceRepaint) {
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index c482fc1..e7432ac 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -31,7 +31,7 @@
// Cache size limits.
static const size_t maxKeySize = 1024;
-static const size_t maxValueSize = 512 * 1024;
+static const size_t maxValueSize = 2 * 1024 * 1024;
static const size_t maxTotalSize = 1024 * 1024;
ShaderCache::ShaderCache() {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index a78cd83..9bca4df 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -75,7 +75,9 @@
bool opaque, const LightInfo& lightInfo,
const std::vector<sp<RenderNode>>& renderNodes,
FrameInfoVisualizer* profiler) {
- mEglManager.damageFrame(frame, dirty);
+ if (!isCapturingSkp()) {
+ mEglManager.damageFrame(frame, dirty);
+ }
SkColorType colorType = getSurfaceColorType();
// setup surface for fbo0
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 039b0f9..5462623 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -420,7 +420,7 @@
procs.fTypefaceProc = [](SkTypeface* tf, void* ctx){
return tf->serialize(SkTypeface::SerializeBehavior::kDoIncludeData);
};
- auto data = picture->serialize();
+ auto data = picture->serialize(&procs);
savePictureAsync(data, mCapturedFile);
mCaptureSequence = 0;
mCaptureMode = CaptureMode::None;
@@ -470,8 +470,7 @@
const SkMatrix& preTransform) {
SkAutoCanvasRestore saver(canvas, true);
auto clipRestriction = preTransform.mapRect(clip).roundOut();
- if (CC_UNLIKELY(mCaptureMode == CaptureMode::SingleFrameSKP
- || mCaptureMode == CaptureMode::MultiFrameSKP)) {
+ if (CC_UNLIKELY(isCapturingSkp())) {
canvas->drawAnnotation(SkRect::Make(clipRestriction), "AndroidDeviceClipRestriction",
nullptr);
} else {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 4658035..bc8a565 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -80,6 +80,8 @@
SkColorType mSurfaceColorType;
sk_sp<SkColorSpace> mSurfaceColorSpace;
+ bool isCapturingSkp() const { return mCaptureMode != CaptureMode::None; }
+
private:
void renderFrameImpl(const SkRect& clip,
const std::vector<sp<RenderNode>>& nodes, bool opaque,
diff --git a/libs/hwui/pipeline/skia/StretchMask.cpp b/libs/hwui/pipeline/skia/StretchMask.cpp
index 1c58c6a..2dbeb3a 100644
--- a/libs/hwui/pipeline/skia/StretchMask.cpp
+++ b/libs/hwui/pipeline/skia/StretchMask.cpp
@@ -59,8 +59,7 @@
}
sk_sp<SkImage> maskImage = mMaskSurface->makeImageSnapshot();
- sk_sp<SkShader> maskStretchShader = stretch.getShader(
- width, height, maskImage);
+ sk_sp<SkShader> maskStretchShader = stretch.getShader(width, height, maskImage, nullptr);
SkPaint maskPaint;
maskPaint.setShader(maskStretchShader);
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index ac19a15..6fd644b 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -390,6 +390,17 @@
}
}
+int RenderProxy::copyImageInto(const sk_sp<SkImage>& image, SkBitmap* bitmap) {
+ RenderThread& thread = RenderThread::getInstance();
+ if (gettid() == thread.getTid()) {
+ // TODO: fix everything that hits this. We should never be triggering a readback ourselves.
+ return (int)thread.readback().copyImageInto(image, bitmap);
+ } else {
+ return thread.queue().runSync(
+ [&]() -> int { return (int)thread.readback().copyImageInto(image, bitmap); });
+ }
+}
+
void RenderProxy::disableVsync() {
Properties::disableVsync = true;
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 0681dc5..6d80949 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -136,6 +136,7 @@
static void prepareToDraw(Bitmap& bitmap);
static int copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap);
+ static int copyImageInto(const sk_sp<SkImage>& image, SkBitmap* bitmap);
static void disableVsync();
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 5a71833..f701491 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -425,27 +425,38 @@
semaphoreInfo.flags = 0;
VkSemaphore semaphore;
VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
- LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to create import semaphore, err: %d",
- err);
+ if (err != VK_SUCCESS) {
+ ALOGE("Failed to create import semaphore, err: %d", err);
+ close(fence_clone);
+ sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
+ } else {
+ VkImportSemaphoreFdInfoKHR importInfo;
+ importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
+ importInfo.pNext = nullptr;
+ importInfo.semaphore = semaphore;
+ importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
+ importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+ importInfo.fd = fence_clone;
- VkImportSemaphoreFdInfoKHR importInfo;
- importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
- importInfo.pNext = nullptr;
- importInfo.semaphore = semaphore;
- importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
- importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- importInfo.fd = fence_clone;
-
- err = mImportSemaphoreFdKHR(mDevice, &importInfo);
- LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to import semaphore, err: %d", err);
-
- GrBackendSemaphore backendSemaphore;
- backendSemaphore.initVulkan(semaphore);
- bufferInfo->skSurface->wait(1, &backendSemaphore);
- // The following flush blocks the GPU immediately instead of waiting for other
- // drawing ops. It seems dequeue_fence is not respected otherwise.
- // TODO: remove the flush after finding why backendSemaphore is not working.
- bufferInfo->skSurface->flushAndSubmit();
+ err = mImportSemaphoreFdKHR(mDevice, &importInfo);
+ if (err != VK_SUCCESS) {
+ ALOGE("Failed to import semaphore, err: %d", err);
+ mDestroySemaphore(mDevice, semaphore, nullptr);
+ close(fence_clone);
+ sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
+ } else {
+ GrBackendSemaphore backendSemaphore;
+ backendSemaphore.initVulkan(semaphore);
+ // Skia will take ownership of the VkSemaphore and delete it once the wait
+ // has finished. The VkSemaphore also owns the imported fd, so it will
+ // close the fd when it is deleted.
+ bufferInfo->skSurface->wait(1, &backendSemaphore);
+ // The following flush blocks the GPU immediately instead of waiting for
+ // other drawing ops. It seems dequeue_fence is not respected otherwise.
+ // TODO: remove the flush after finding why backendSemaphore is not working.
+ bufferInfo->skSurface->flushAndSubmit();
+ }
+ }
}
}
}
@@ -621,6 +632,7 @@
VkSemaphore semaphore;
VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
if (VK_SUCCESS != err) {
+ close(fenceFd);
ALOGE("Failed to create import semaphore, err: %d", err);
return UNKNOWN_ERROR;
}
@@ -635,6 +647,7 @@
err = mImportSemaphoreFdKHR(mDevice, &importInfo);
if (VK_SUCCESS != err) {
mDestroySemaphore(mDevice, semaphore, nullptr);
+ close(fenceFd);
ALOGE("Failed to import semaphore, err: %d", err);
return UNKNOWN_ERROR;
}
@@ -642,7 +655,8 @@
GrBackendSemaphore beSemaphore;
beSemaphore.initVulkan(semaphore);
- // Skia takes ownership of the semaphore and will delete it once the wait has finished.
+ // Skia will take ownership of the VkSemaphore and delete it once the wait has finished. The
+ // VkSemaphore also owns the imported fd, so it will close the fd when it is deleted.
grContext->wait(1, &beSemaphore);
grContext->flushAndSubmit();
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 01a2ec5..fe9a30a 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -429,7 +429,9 @@
kTopLeft_GrSurfaceOrigin, mWindowInfo.colorspace, nullptr);
if (bufferInfo->skSurface.get() == nullptr) {
ALOGE("SkSurface::MakeFromAHardwareBuffer failed");
- mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd.release());
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer,
+ mNativeBuffers[idx].dequeue_fence.release());
+ mNativeBuffers[idx].dequeued = false;
return nullptr;
}
}
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index e419801..ece5905 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -16,20 +16,19 @@
#include "GraphicsStatsService.h"
+#include <android/util/ProtoOutputStream.h>
#include <errno.h>
#include <fcntl.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <inttypes.h>
#include <log/log.h>
+#include <stats_event.h>
+#include <statslog_hwui.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
-#include <android/util/ProtoOutputStream.h>
-#include <stats_event.h>
-#include <statslog.h>
-
#include "JankTracker.h"
#include "protos/graphicsstats.pb.h"
@@ -539,7 +538,7 @@
for (int stat_index = 0; stat_index < serviceDump.stats_size(); stat_index++) {
auto& stat = serviceDump.stats(stat_index);
AStatsEvent* event = AStatsEventList_addStatsEvent(data);
- AStatsEvent_setAtomId(event, android::util::GRAPHICS_STATS);
+ AStatsEvent_setAtomId(event, stats::GRAPHICS_STATS);
AStatsEvent_writeString(event, stat.package_name().c_str());
AStatsEvent_writeInt64(event, (int64_t)stat.version_code());
AStatsEvent_writeInt64(event, (int64_t)stat.stats_start());
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index cb56ee5..a3842a1 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -178,6 +178,7 @@
public static final int POWER_HIGH = 203;
private static final long IMPLICIT_MIN_UPDATE_INTERVAL = -1;
+ private static final double IMPLICIT_MIN_UPDATE_INTERVAL_FACTOR = 1D / 6D;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link "
+ "LocationManager} methods to provide the provider explicitly.")
@@ -552,7 +553,7 @@
*/
public @IntRange(from = 0) long getMinUpdateIntervalMillis() {
if (mMinUpdateIntervalMillis == IMPLICIT_MIN_UPDATE_INTERVAL) {
- return mInterval;
+ return (long) (mInterval * IMPLICIT_MIN_UPDATE_INTERVAL_FACTOR);
} else {
// the min is only necessary in case someone use a deprecated function to mess with the
// interval or min update interval
@@ -1018,7 +1019,9 @@
* Sets an explicit minimum update interval. If location updates are available faster than
* the request interval then an update will only occur if the minimum update interval has
* expired since the last location update. Defaults to no explicit minimum update interval
- * set, which means the minimum update interval is the same as the interval.
+ * set, which means some sensible default between 0 and the interval will be chosen. The
+ * exact value is not specified at the moment. If an exact known value is required, clients
+ * should set an explicit value themselves.
*
* <p class=note><strong>Note:</strong> Some allowance for jitter is already built into the
* minimum update interval, so you need not worry about updates blocked simply because they
@@ -1037,7 +1040,8 @@
/**
* Clears an explicitly set minimum update interval and reverts to an implicit minimum
- * update interval (ie, the minimum update interval is the same value as the interval).
+ * update interval (ie, the minimum update interval is some sensible default between 0 and
+ * the interval).
*/
public @NonNull Builder clearMinUpdateIntervalMillis() {
mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL;
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 5f6fc17..8012f03 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -27,6 +27,7 @@
import android.media.audiofx.AudioEffect;
import android.media.audiopolicy.AudioMix;
import android.os.Build;
+import android.os.IBinder;
import android.os.Vibrator;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -1655,6 +1656,8 @@
/** @hide */
@UnsupportedAppUsage
public static native int checkAudioFlinger();
+ /** @hide */
+ public static native void setAudioFlingerBinder(IBinder audioFlinger);
/** @hide */
public static native int listAudioPorts(ArrayList<AudioPort> ports, int[] generation);
diff --git a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
index 1755657..63c52a1 100644
--- a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
@@ -26,9 +26,9 @@
*/
oneway interface IMediaRoute2ProviderServiceCallback {
// TODO: Change it to updateRoutes?
- void updateState(in MediaRoute2ProviderInfo providerInfo);
+ void notifyProviderUpdated(in MediaRoute2ProviderInfo providerInfo);
void notifySessionCreated(long requestId, in RoutingSessionInfo sessionInfo);
- void notifySessionUpdated(in RoutingSessionInfo sessionInfo);
+ void notifySessionsUpdated(in List<RoutingSessionInfo> sessionInfo);
void notifySessionReleased(in RoutingSessionInfo sessionInfo);
void notifyRequestFailed(long requestId, int reason);
}
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 93fe06a..49e0411 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -141,6 +141,7 @@
private final Object mSessionLock = new Object();
private final Object mRequestIdsLock = new Object();
private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
+ private final AtomicBoolean mSessionUpdateScheduled = new AtomicBoolean(false);
private MediaRoute2ProviderServiceStub mStub;
private IMediaRoute2ProviderServiceCallback mRemoteCallback;
private volatile MediaRoute2ProviderInfo mProviderInfo;
@@ -287,16 +288,8 @@
Log.w(TAG, "notifySessionUpdated: Ignoring unknown session info.");
return;
}
-
- if (mRemoteCallback == null) {
- return;
- }
- try {
- mRemoteCallback.notifySessionUpdated(sessionInfo);
- } catch (RemoteException ex) {
- Log.w(TAG, "Failed to notify session info changed.");
- }
}
+ scheduleUpdateSessions();
}
/**
@@ -479,6 +472,7 @@
void setCallback(IMediaRoute2ProviderServiceCallback callback) {
mRemoteCallback = callback;
schedulePublishState();
+ scheduleUpdateSessions();
}
void schedulePublishState() {
@@ -497,12 +491,40 @@
}
try {
- mRemoteCallback.updateState(mProviderInfo);
+ mRemoteCallback.notifyProviderUpdated(mProviderInfo);
} catch (RemoteException ex) {
Log.w(TAG, "Failed to publish provider state.", ex);
}
}
+ void scheduleUpdateSessions() {
+ if (mSessionUpdateScheduled.compareAndSet(false, true)) {
+ mHandler.post(this::updateSessions);
+ }
+ }
+
+ private void updateSessions() {
+ if (!mSessionUpdateScheduled.compareAndSet(true, false)) {
+ return;
+ }
+
+ if (mRemoteCallback == null) {
+ return;
+ }
+
+ List<RoutingSessionInfo> sessions;
+ synchronized (mSessionLock) {
+ sessions = new ArrayList<>(mSessionInfo.values());
+ }
+
+ try {
+ mRemoteCallback.notifySessionsUpdated(sessions);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Failed to notify session info changed.");
+ }
+
+ }
+
/**
* Adds a requestId in the request ID list whose max size is {@link #MAX_REQUEST_IDS_SIZE}.
* When the max size is reached, the first element is removed (FIFO).
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 1a2a1ae..345d9b2 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -696,13 +696,17 @@
@Override
public void onGlobalA2dpChanged(boolean a2dpOn) {
mHandler.post(() -> {
- if (mSelectedRoute == null) {
+ if (mSelectedRoute == null || mBluetoothA2dpRoute == null) {
return;
}
if (mSelectedRoute.isDefault() && a2dpOn) {
- setSelectedRoute(mBluetoothA2dpRoute, /*explicit=*/false);
+ setSelectedRoute(mBluetoothA2dpRoute, /*explicit=*/ false);
+ dispatchRouteUnselected(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo);
+ dispatchRouteSelected(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute);
} else if (mSelectedRoute.isBluetooth() && !a2dpOn) {
- setSelectedRoute(mDefaultAudioVideo, /*explicit=*/false);
+ setSelectedRoute(mDefaultAudioVideo, /*explicit=*/ false);
+ dispatchRouteUnselected(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute);
+ dispatchRouteSelected(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo);
}
});
}
@@ -1363,6 +1367,9 @@
}
static void dispatchRouteSelected(int type, RouteInfo info) {
+ if (DEBUG) {
+ Log.d(TAG, "Dispatching route selected: " + info);
+ }
for (CallbackInfo cbi : sStatic.mCallbacks) {
if (cbi.filterRouteEvent(info)) {
cbi.cb.onRouteSelected(cbi.router, type, info);
@@ -1371,6 +1378,9 @@
}
static void dispatchRouteUnselected(int type, RouteInfo info) {
+ if (DEBUG) {
+ Log.d(TAG, "Dispatching route unselected: " + info);
+ }
for (CallbackInfo cbi : sStatic.mCallbacks) {
if (cbi.filterRouteEvent(info)) {
cbi.cb.onRouteUnselected(cbi.router, type, info);
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index e2e13b0..be6ff1b 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -521,12 +521,12 @@
public int getRingtonePosition(Uri ringtoneUri) {
try {
if (ringtoneUri == null) return -1;
- final long ringtoneId = ContentUris.parseId(ringtoneUri);
final Cursor cursor = getCursor();
cursor.moveToPosition(-1);
while (cursor.moveToNext()) {
- if (ringtoneId == cursor.getLong(ID_COLUMN_INDEX)) {
+ Uri uriFromCursor = getUriFromCursor(mContext, cursor);
+ if (ringtoneUri.equals(uriFromCursor)) {
return cursor.getPosition();
}
}
diff --git a/media/jni/soundpool/Sound.cpp b/media/jni/soundpool/Sound.cpp
index 50e0d33..6ef0740 100644
--- a/media/jni/soundpool/Sound.cpp
+++ b/media/jni/soundpool/Sound.cpp
@@ -214,7 +214,7 @@
} else if (sampleRate > kMaxSampleRate) {
ALOGE("%s: sample rate (%u) out of range", __func__, sampleRate);
status = BAD_VALUE;
- } else if (channelCount < 1 || channelCount > FCC_8) {
+ } else if (channelCount < 1 || channelCount > FCC_LIMIT) {
ALOGE("%s: sample channel count (%d) out of range", __func__, channelCount);
status = BAD_VALUE;
} else {
diff --git a/packages/DynamicSystemInstallationService/res/values-uz/strings.xml b/packages/DynamicSystemInstallationService/res/values-uz/strings.xml
index 5597fb5..a34ac00 100644
--- a/packages/DynamicSystemInstallationService/res/values-uz/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-uz/strings.xml
@@ -8,7 +8,7 @@
<string name="notification_image_validation_failed" msgid="2720357826403917016">"Disk tasviri tekshiruvi amalga oshmadi. Oʻrnatishni bekor qiling."</string>
<string name="notification_dynsystem_in_use" msgid="1053194595682188396">"Hozirda dinamik tizim ishga tushirilgan. Asl Android versiyasidan foydlanish uchun qayta ishga tushiring."</string>
<string name="notification_action_cancel" msgid="5929299408545961077">"Bekor qilish"</string>
- <string name="notification_action_discard" msgid="1817481003134947493">"Bekor qilish"</string>
+ <string name="notification_action_discard" msgid="1817481003134947493">"Rad etish"</string>
<string name="notification_action_reboot_to_dynsystem" msgid="4015817159115912479">"Boshidan"</string>
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Boshidan"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamik tizim bekor qilindi"</string>
diff --git a/packages/PackageInstaller/res/values-bs/strings.xml b/packages/PackageInstaller/res/values-bs/strings.xml
index 66d57e3..dc07c02 100644
--- a/packages/PackageInstaller/res/values-bs/strings.xml
+++ b/packages/PackageInstaller/res/values-bs/strings.xml
@@ -83,9 +83,9 @@
<string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Radi vaše sigurnosti, tabletu trenutno nije dozvoljeno da instalira nepoznate aplikacije iz ovog izvora. Ovo možete promijeniti u Postavkama."</string>
<string name="untrusted_external_source_warning" product="tv" msgid="7057271609532508035">"Radi vaše sigurnosti, TV-u trenutno nije dozvoljeno da instalira nepoznate aplikacije iz ovog izvora. Ovo možete promijeniti u Postavkama."</string>
<string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"Radi vaše sigurnosti, telefonu trenutno nije dozvoljeno da instalira nepoznate aplikacije iz ovog izvora. Ovo možete promijeniti u Postavkama."</string>
- <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Vaši podaci na telefonu i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, saglasni ste da ste vi odgovorni za bilo kakvu štetu na telefonu ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
- <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Vaši podaci na tabletu i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, saglasni ste da ste vi odgovorni za bilo kakvu štetu na tabletu ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
- <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Vaši podaci na TV-u i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, saglasni ste da ste vi odgovorni za bilo kakvu štetu na TV-u ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
+ <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Vaši podaci na telefonu i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, prihvatate odgovornost za bilo kakvu štetu na telefonu ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
+ <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Vaši podaci na tabletu i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, prihvatate odgovornost za bilo kakvu štetu na tabletu ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
+ <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Vaši podaci na TV-u i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, prihvatate odgovornost za bilo kakvu štetu na TV-u ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
<string name="anonymous_source_continue" msgid="4375745439457209366">"Nastavi"</string>
<string name="external_sources_settings" msgid="4046964413071713807">"Postavke"</string>
<string name="wear_app_channel" msgid="1960809674709107850">"Instaliranje/deinstaliranje Wear aplik."</string>
diff --git a/packages/PackageInstaller/res/values-eu/strings.xml b/packages/PackageInstaller/res/values-eu/strings.xml
index 9922fe1..f5ad2be 100644
--- a/packages/PackageInstaller/res/values-eu/strings.xml
+++ b/packages/PackageInstaller/res/values-eu/strings.xml
@@ -46,7 +46,7 @@
<string name="out_of_space_dlg_text" msgid="8727714096031856231">"Ezin izan da instalatu <xliff:g id="APP_NAME">%1$s</xliff:g>. Egin toki pixka bat eta saiatu berriro."</string>
<string name="app_not_found_dlg_title" msgid="5107924008597470285">"Ez da aurkitu aplikazioa"</string>
<string name="app_not_found_dlg_text" msgid="5219983779377811611">"Ez da aurkitu aplikazioa instalatutako aplikazioen zerrendan."</string>
- <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Ez du baimenik"</string>
+ <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Baimendu gabe"</string>
<string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"Erabiltzaile honek ez dauka desinstalatzeko baimenik."</string>
<string name="generic_error_dlg_title" msgid="5863195085927067752">"Errorea"</string>
<string name="generic_error_dlg_text" msgid="5287861443265795232">"Ezin izan da desinstalatu aplikazioa."</string>
diff --git a/packages/PackageInstaller/res/values-gl/strings.xml b/packages/PackageInstaller/res/values-gl/strings.xml
index 637e15a..ac1f6ac 100644
--- a/packages/PackageInstaller/res/values-gl/strings.xml
+++ b/packages/PackageInstaller/res/values-gl/strings.xml
@@ -46,7 +46,7 @@
<string name="out_of_space_dlg_text" msgid="8727714096031856231">"Non se puido instalar a aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>. Libera espazo e téntao de novo."</string>
<string name="app_not_found_dlg_title" msgid="5107924008597470285">"Non se atopou a aplicación"</string>
<string name="app_not_found_dlg_text" msgid="5219983779377811611">"Non se atopou a aplicación na lista de aplicacións instaladas."</string>
- <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Sen permiso"</string>
+ <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Permiso non concedido"</string>
<string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"O usuario actual non pode realizar esta desinstalación."</string>
<string name="generic_error_dlg_title" msgid="5863195085927067752">"Erro"</string>
<string name="generic_error_dlg_text" msgid="5287861443265795232">"Non se puido desinstalar a aplicación."</string>
diff --git a/packages/PrintSpooler/res/values-az/strings.xml b/packages/PrintSpooler/res/values-az/strings.xml
index 887434b..fae4736 100644
--- a/packages/PrintSpooler/res/values-az/strings.xml
+++ b/packages/PrintSpooler/res/values-az/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4469836075319831821">"Çap Spuler"</string>
- <string name="more_options_button" msgid="2243228396432556771">"Digər variantlar"</string>
+ <string name="more_options_button" msgid="2243228396432556771">"Digər seçimlər"</string>
<string name="label_destination" msgid="9132510997381599275">"Hədəf"</string>
<string name="label_copies" msgid="3634531042822968308">"Surətlər"</string>
<string name="label_copies_summary" msgid="3861966063536529540">"Nüsxələr:"</string>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-v31/styles.xml b/packages/SettingsLib/BannerMessagePreference/res/values-v31/styles.xml
index a39e779..e74ac44 100644
--- a/packages/SettingsLib/BannerMessagePreference/res/values-v31/styles.xml
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-v31/styles.xml
@@ -33,7 +33,7 @@
<style name="Banner.Title.SettingsLib"
parent="@android:style/TextAppearance.Material.Subhead">
<item name="android:textSize">20sp</item>
- <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
diff --git a/packages/SettingsLib/IllustrationPreference/res/drawable/ic_gesture_play_button.xml b/packages/SettingsLib/IllustrationPreference/res/drawable/ic_gesture_play_button.xml
deleted file mode 100644
index 55b3115..0000000
--- a/packages/SettingsLib/IllustrationPreference/res/drawable/ic_gesture_play_button.xml
+++ /dev/null
@@ -1,24 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:fillColor="#FFFFFF" android:pathData="M24,24m-19,0a19,19 0,1 1,38 0a19,19 0,1 1,-38 0"/>
- <path android:fillColor="#1A73E8" android:pathData="M20,33l12,-9l-12,-9z"/>
- <path android:fillColor="#1A73E8" android:pathData="M24,4C12.96,4 4,12.96 4,24s8.96,20 20,20s20,-8.96 20,-20S35.04,4 24,4zM24,40c-8.82,0 -16,-7.18 -16,-16S15.18,8 24,8s16,7.18 16,16S32.82,40 24,40z"/>
-</vector>
diff --git a/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml b/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml
index 54731f5..3f8439c 100644
--- a/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml
+++ b/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml
@@ -25,7 +25,7 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="300dp"
+ android:layout_height="@dimen/settingslib_illustration_height"
android:layout_gravity="center"
android:gravity="center_vertical"
android:padding="@dimen/settingslib_illustration_padding"
@@ -33,7 +33,7 @@
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottie_view"
android:adjustViewBounds="true"
- android:maxWidth="412dp"
+ android:maxWidth="@dimen/settingslib_illustration_width"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
@@ -44,20 +44,11 @@
<FrameLayout
android:id="@+id/middleground_layout"
- android:layout_width="412dp"
- android:layout_height="300dp"
+ android:layout_width="@dimen/settingslib_illustration_width"
+ android:layout_height="@dimen/settingslib_illustration_height"
android:padding="@dimen/settingslib_illustration_padding"
android:background="@android:color/transparent"
android:layout_gravity="center"
android:visibility="gone"/>
-
- <ImageView
- android:id="@+id/video_play_button"
- android:layout_width="36dp"
- android:layout_height="36dp"
- android:layout_gravity="center"
- android:visibility="gone"
- android:src="@drawable/ic_gesture_play_button"/>
-
</FrameLayout>
diff --git a/packages/SettingsLib/IllustrationPreference/res/values/dimens.xml b/packages/SettingsLib/IllustrationPreference/res/values/dimens.xml
index 5e540d3..3f38769 100644
--- a/packages/SettingsLib/IllustrationPreference/res/values/dimens.xml
+++ b/packages/SettingsLib/IllustrationPreference/res/values/dimens.xml
@@ -18,4 +18,7 @@
<resources>
<!-- Padding of illustration -->
<dimen name="settingslib_illustration_padding">12dp</dimen>
+
+ <dimen name="settingslib_illustration_width">412dp</dimen>
+ <dimen name="settingslib_illustration_height">300dp</dimen>
</resources>
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
index 7b2a0af..1370eef 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
@@ -18,8 +18,6 @@
import android.content.Context;
import android.content.res.TypedArray;
-import android.os.Parcel;
-import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -28,7 +26,6 @@
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceViewHolder;
import com.airbnb.lottie.LottieAnimationView;
@@ -36,14 +33,12 @@
/**
* IllustrationPreference is a preference that can play lottie format animation
*/
-public class IllustrationPreference extends Preference implements OnPreferenceClickListener {
+public class IllustrationPreference extends Preference {
static final String TAG = "IllustrationPreference";
private int mAnimationId;
- private boolean mIsAnimating;
private boolean mIsAutoScale;
- private ImageView mPlayButton;
private LottieAnimationView mIllustrationView;
private View mMiddleGroundView;
private FrameLayout mMiddleGroundLayout;
@@ -72,13 +67,11 @@
return;
}
mMiddleGroundLayout = (FrameLayout) holder.findViewById(R.id.middleground_layout);
- mPlayButton = (ImageView) holder.findViewById(R.id.video_play_button);
mIllustrationView = (LottieAnimationView) holder.findViewById(R.id.lottie_view);
mIllustrationView.setAnimation(mAnimationId);
mIllustrationView.loop(true);
ColorUtils.applyDynamicColors(getContext(), mIllustrationView);
mIllustrationView.playAnimation();
- updateAnimationStatus(mIsAnimating);
if (mIsAutoScale) {
enableAnimationAutoScale(mIsAutoScale);
}
@@ -87,28 +80,6 @@
}
}
- @Override
- public boolean onPreferenceClick(Preference preference) {
- mIsAnimating = !isAnimating();
- updateAnimationStatus(mIsAnimating);
- return true;
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
- SavedState ss = new SavedState(superState);
- ss.mIsAnimating = mIsAnimating;
- return ss;
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- super.onRestoreInstanceState(ss.getSuperState());
- mIsAnimating = ss.mIsAnimating;
- }
-
@VisibleForTesting
boolean isAnimating() {
return mIllustrationView.isAnimating();
@@ -158,7 +129,6 @@
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.illustration_preference);
- mIsAnimating = true;
mIsAutoScale = false;
if (attrs != null) {
final TypedArray a = context.obtainStyledAttributes(attrs,
@@ -166,56 +136,5 @@
mAnimationId = a.getResourceId(R.styleable.LottieAnimationView_lottie_rawRes, 0);
a.recycle();
}
- setOnPreferenceClickListener(this);
- }
-
- private void updateAnimationStatus(boolean playAnimation) {
- if (playAnimation) {
- mIllustrationView.resumeAnimation();
- mPlayButton.setVisibility(View.INVISIBLE);
- } else {
- mIllustrationView.pauseAnimation();
- mPlayButton.setVisibility(View.VISIBLE);
- }
- }
-
- static class SavedState extends BaseSavedState {
- boolean mIsAnimating;
-
- SavedState(Parcelable superState) {
- super(superState);
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- mIsAnimating = (Boolean) in.readValue(null);
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeValue(mIsAnimating);
- }
-
- @Override
- public String toString() {
- return "IllustrationPreference.SavedState{"
- + Integer.toHexString(System.identityHashCode(this))
- + " mIsAnimating=" + mIsAnimating + "}";
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
}
}
diff --git a/packages/SettingsLib/SearchWidget/res/values-kk/strings.xml b/packages/SettingsLib/SearchWidget/res/values-kk/strings.xml
index 92c45ba..323fa67 100644
--- a/packages/SettingsLib/SearchWidget/res/values-kk/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-kk/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="search_menu" msgid="1914043873178389845">"Параметрлерді іздеу"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Параметр іздеу"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-ne/strings.xml b/packages/SettingsLib/SearchWidget/res/values-ne/strings.xml
index 100acd2..f13f4cd 100644
--- a/packages/SettingsLib/SearchWidget/res/values-ne/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-ne/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="search_menu" msgid="1914043873178389845">"खोजसम्बन्धी सेटिङहरू"</string>
+ <string name="search_menu" msgid="1914043873178389845">"सेटिङमा खोज्नुहोस्"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-pt-rBR/strings.xml b/packages/SettingsLib/SearchWidget/res/values-pt-rBR/strings.xml
index 5683b6a..0fa4bd3 100644
--- a/packages/SettingsLib/SearchWidget/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-pt-rBR/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="search_menu" msgid="1914043873178389845">"Pesquisar em Configurações"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Pesquisar nas Configurações"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-pt/strings.xml b/packages/SettingsLib/SearchWidget/res/values-pt/strings.xml
index 5683b6a..0fa4bd3 100644
--- a/packages/SettingsLib/SearchWidget/res/values-pt/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-pt/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="search_menu" msgid="1914043873178389845">"Pesquisar em Configurações"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Pesquisar nas Configurações"</string>
</resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_progress_horizontal.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_progress_horizontal.xml
new file mode 100644
index 0000000..a4c780b
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_progress_horizontal.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@android:id/background">
+ <shape>
+ <corners android:radius="8dp" />
+ <solid android:color="@color/settingslib_colorSurfaceVariant" />
+ </shape>
+ </item>
+
+ <item
+ android:id="@android:id/progress">
+ <clip>
+ <shape>
+ <corners android:radius="8dp" />
+ <solid android:color="?android:attr/textColorPrimary" />
+ </shape>
+ </clip>
+ </item>
+</layer-list>
diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v31/settingslib_preference.xml b/packages/SettingsLib/SettingsTheme/res/layout-v31/settingslib_preference.xml
index 579abbd5..23aa993 100644
--- a/packages/SettingsLib/SettingsTheme/res/layout-v31/settingslib_preference.xml
+++ b/packages/SettingsLib/SettingsTheme/res/layout-v31/settingslib_preference.xml
@@ -42,7 +42,7 @@
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:singleLine="true"
+ android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee"/>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
index 426a2ba..69975cd 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
@@ -31,4 +31,6 @@
<color name="settingslib_dialog_background">@android:color/system_neutral1_800</color>
<!-- Dialog error color. -->
<color name="settingslib_dialog_colorError">#f28b82</color> <!-- Red 300 -->
+
+ <color name="settingslib_colorSurfaceVariant">@android:color/system_neutral1_700</color>
</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
index fcba6bd..aed6338 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
@@ -37,4 +37,6 @@
<color name="settingslib_dialog_background">@android:color/system_neutral1_800</color>
<!-- Dialog error color. -->
<color name="settingslib_dialog_colorError">#d93025</color> <!-- Red 600 -->
+
+ <color name="settingslib_colorSurfaceVariant">@android:color/system_neutral2_100</color>
</resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
index e3a0239..9610c94 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
@@ -28,4 +28,10 @@
<item name="android:track">@drawable/settingslib_switch_track</item>
<item name="android:thumb">@drawable/settingslib_switch_thumb</item>
</style>
+
+ <style name="HorizontalProgressBar.SettingsLib"
+ parent="android:style/Widget.Material.ProgressBar.Horizontal">
+ <item name="android:progressDrawable">@drawable/settingslib_progress_horizontal</item>
+ <item name="android:scaleY">0.5</item>
+ </style>
</resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml
index b3378b20..6b18f28 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml
@@ -20,9 +20,12 @@
<style name="Theme.SettingsBase" parent="@android:style/Theme.DeviceDefault.Settings" >
<item name="android:textAppearanceListItem">@style/TextAppearance.PreferenceTitle.SettingsLib</item>
<item name="android:listPreferredItemPaddingStart">24dp</item>
+ <item name="android:listPreferredItemPaddingLeft">24dp</item>
<item name="android:listPreferredItemPaddingEnd">16dp</item>
+ <item name="android:listPreferredItemPaddingRight">16dp</item>
<item name="preferenceTheme">@style/PreferenceTheme.SettingsLib</item>
<item name="android:switchStyle">@style/Switch.SettingsLib</item>
+ <item name="android:progressBarStyleHorizontal">@style/HorizontalProgressBar.SettingsLib</item>
</style>
<!-- Using in SubSettings page including injected settings page -->
diff --git a/packages/SettingsLib/TwoTargetPreference/res/layout-v31/preference_two_target.xml b/packages/SettingsLib/TwoTargetPreference/res/layout-v31/preference_two_target.xml
index 2c2756b..2c35772 100644
--- a/packages/SettingsLib/TwoTargetPreference/res/layout-v31/preference_two_target.xml
+++ b/packages/SettingsLib/TwoTargetPreference/res/layout-v31/preference_two_target.xml
@@ -40,7 +40,7 @@
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:singleLine="true"
+ android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee"/>
diff --git a/packages/SettingsLib/res/layout/preference_access_point.xml b/packages/SettingsLib/res/layout/preference_access_point.xml
index f3f43ac..802d604 100644
--- a/packages/SettingsLib/res/layout/preference_access_point.xml
+++ b/packages/SettingsLib/res/layout/preference_access_point.xml
@@ -64,7 +64,7 @@
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:singleLine="true"
+ android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee" />
diff --git a/packages/SettingsLib/res/layout/preference_checkable_two_target.xml b/packages/SettingsLib/res/layout/preference_checkable_two_target.xml
index e4f7242..f512f9b 100644
--- a/packages/SettingsLib/res/layout/preference_checkable_two_target.xml
+++ b/packages/SettingsLib/res/layout/preference_checkable_two_target.xml
@@ -61,7 +61,7 @@
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:singleLine="true"
+ android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee" />
diff --git a/packages/SettingsLib/res/layout/restricted_switch_preference.xml b/packages/SettingsLib/res/layout/restricted_switch_preference.xml
index d9f91de..169ae97 100644
--- a/packages/SettingsLib/res/layout/restricted_switch_preference.xml
+++ b/packages/SettingsLib/res/layout/restricted_switch_preference.xml
@@ -51,7 +51,7 @@
<TextView android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:singleLine="true"
+ android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee" />
diff --git a/packages/SettingsLib/res/layout/restricted_switch_widget.xml b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
index 5dbcb79..1520ac8 100644
--- a/packages/SettingsLib/res/layout/restricted_switch_widget.xml
+++ b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
@@ -16,11 +16,11 @@
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/restricted_icon"
- android:layout_width="@*android:dimen/config_restrictedIconSize"
+ android:layout_width="@dimen/two_target_min_width"
android:layout_height="@*android:dimen/config_restrictedIconSize"
android:tint="?android:attr/colorAccent"
android:src="@*android:drawable/ic_info"
- android:gravity="end|center_vertical" />
+ android:gravity="center" />
<!-- Based off frameworks/base/core/res/res/layout/preference_widget_switch.xml -->
<Switch xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/switch_widget"
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 6b16a29..366cb06 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Wys snitgrense, kantlyne, ens."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Dwing RTL-uitlegrigting"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Dwing skermuitlegrigting na RTL vir alle locales"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Laat venstervlakwasighede toe"</string>
<string name="force_msaa" msgid="4081288296137775550">"Dwing 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Aktiveer 4x MSAA in OpenGL ES 2.0-programme"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Ontfout nie-reghoekige knipbedrywighede"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en onthounotas"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Laat toe dat wekkers en onthounotas gestel word"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en onthounotas"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Laat hierdie program toe om wekkers te stel en ander handelinge te skeduleer. Hierdie program kan gebruik word wanneer jy nie jou foon gebruik nie, en kan dalk meer batterykrag gebruik. As hierdie toestemming af is, sal hierdie program dalk nie normaal funksioneer en sy wekkers nie werk soos geskeduleer nie."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Laat hierdie program toe om wekkers te stel en ander handelinge te skeduleer. Hierdie program kan gebruik word wanneer jy nie jou tablet gebruik nie, en kan dalk meer batterykrag gebruik. As hierdie toestemming af is, sal hierdie program dalk nie normaal funksioneer en sy wekkers nie werk soos geskeduleer nie."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Laat hierdie program toe om wekkers te stel en ander handelinge te skeduleer. Hierdie program kan gebruik word wanneer jy nie jou toestel gebruik nie, en kan dalk meer batterykrag gebruik. As hierdie toestemming af is, sal hierdie program dalk nie normaal funksioneer en sy wekkers nie werk soos geskeduleer nie."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie program toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die program op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie program geskeduleer is, nie werk nie."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"skedule, wekker, onthounota, horlosie"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Skakel aan"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Skakel Moenie steur nie aan"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 9943bbb..8a5da97 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"የቅንጥብ ገደቦች፣ ጠርዞች፣ ወዘተ አሳይ"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"የቀኝ-ወደ-ግራ አቀማመጥ አቅጣጫ አስገድድ"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"ለሁሉም አካባቢዎች የማያ ገጽ አቀማመጥ ከቀኝ-ወደ-ግራ እንዲሆን አስገድድ"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"የመስኮት ደረጃ ብዥታዎችን ፍቀድ"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA አስገድድ"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"4x MSAA በ OpenGL ES 2.0 መተግበሪያዎች ውስጥ ያንቁ"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"አራት ማእዘን ያልሆኑ የቅንጥብ ክዋኔዎችን ስህተት አርም"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"ይህ መተግበሪያ ማንቂያዎችን እንዲያቀናብር እና ለሌሎች እርምጃዎች የጊዜ መርሐግብር እንዲያዘጋጅ ይፍቀዱለት። ይህ መተግበሪያ መሣሪያዎን በማይጠቀሙበት ጊዜ ጥቅም ላይ ሊውል ይችላል፤ ይኽም ተጨማሪ ባትሪ ሊጠቀም ይችላል። ይህ ፈቃድ ከጠፋ ይህ መተግበሪያ መደበኛ ሥራውን ላይሰራ ይችላል፣ እንዲሁም ማንቂያዎቹ በጊዜ መርሐግብራቸው መሰረት አይሰሩም።"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"ይህ መተግበሪያ ማንቂያዎችን እንዲያቀናብር እና ለሌሎች እርምጃዎች የጊዜ መርሐግብር እንዲያዘጋጅ ይፍቀዱለት። ይህ መተግበሪያ መሣሪያዎን በማይጠቀሙበት ጊዜ ጥቅም ላይ ሊውል ይችላል፤ ይኽም ተጨማሪ ባትሪ ሊጠቀም ይችላል። ይህ ፈቃድ ከጠፋ ይህ መተግበሪያ መደበኛ ሥራውን ላይሰራ ይችላል፣ እንዲሁም ማንቂያዎቹ በጊዜ መርሐግብራቸው መሰረት አይሰሩም።"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"ይህ መተግበሪያ ማንቂያዎችን እንዲያቀናብር እና ለሌሎች እርምጃዎች የጊዜ መርሐግብር እንዲያዘጋጅ ይፍቀዱለት። ይህ መተግበሪያ መሣሪያዎን በማይጠቀሙበት ጊዜ ጥቅም ላይ ሊውል ይችላል፤ ይኽም ተጨማሪ ባትሪ ሊጠቀም ይችላል። ይህ ፈቃድ ከጠፋ ይህ መተግበሪያ መደበኛ ሥራውን ላይሰራ ይችላል፣ እንዲሁም ማንቂያዎቹ በጊዜ መርሐግብራቸው መሰረት አይሰሩም።"</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 8f146e0..0eef43b 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"عرض حدود وهوامش المقطع وما إلى ذلك"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"فرض اتجاه التنسيق ليكون من اليمين إلى اليسار"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"فرض اتجاه تنسيق الشاشة ليكون من اليمين إلى اليسار لجميع اللغات"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"السماح بعمليات التعتيم على مستوى النافذة"</string>
<string name="force_msaa" msgid="4081288296137775550">"فرض 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"تفعيل 4x MSAA في تطبيقات OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"تصحيح أخطاء عمليات القصاصات غير المستطيلة"</string>
@@ -512,9 +511,8 @@
<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" product="default" msgid="1122213569699233612">"يمكنك السماح لهذا التطبيق بضبط المنبّهات وجدولة الإجراءات الأخرى. قد يتم استخدام هذا التطبيق عند عدم استخدامك للهاتف، مما قد يستهلك المزيد من شحن البطارية. إذا كان هذا الإذن غير مفعّل، قد لا يعمل هذا التطبيق بشكل طبيعي ولن تعمل المنبّهات فيه كما هو مقرر."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"يمكنك السماح لهذا التطبيق بضبط المنبّهات وجدولة الإجراءات الأخرى. قد يتم استخدام هذا التطبيق عند عدم استخدامك للجهاز اللوحي، مما قد يستهلك المزيد من شحن البطارية. إذا كان هذا الإذن غير مفعّل، قد لا يعمل هذا التطبيق بشكل طبيعي ولن تعمل المنبّهات فيه كما هو مقرر."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"يمكنك السماح لهذا التطبيق بضبط المنبّهات وجدولة الإجراءات الأخرى. قد يتم استخدام هذا التطبيق عند عدم استخدامك للجهاز، مما قد يستهلك المزيد من شحن البطارية. إذا كان هذا الإذن غير مفعّل، قد لا يعمل هذا التطبيق بشكل طبيعي ولن تعمل المنبّهات فيه كما هو مقرر."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index de942a3..b8796fe 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"ক্লিপ বাউণ্ড, মাৰ্জিন আদিসমূহ দেখুৱাওক"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"আৰটিএল চানেকিৰ দিশ বলেৰে সলনি কৰক"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"সকলো ভাষাৰ বাবে স্ক্ৰীণৰ চানেকিৰ দিশ RTLলৈ বলেৰে সলনি কৰক"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"ৱিণ্ড’ স্তৰত অস্পষ্ট কৰাৰ অনুমতি দিয়ক"</string>
<string name="force_msaa" msgid="4081288296137775550">"বল ৪গুণ MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 এপত ৪গুণ MSAA সক্ষম কৰক"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"আয়তাকৃতিৰ নোহোৱা ক্লিপ প্ৰক্ৰিয়াসমূহ ডিবাগ কৰক"</string>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"এই এপ্টোক এলাৰ্ম ছেট কৰিবলৈ আৰু অন্য কাৰ্যৰ সময়সূচী নিৰ্ধাৰণ কৰিবলৈ দিয়ক। এই এপ্টো আপুনি নিজৰ ফ’নটো ব্যৱহাৰ কৰি নথকাৰ সময়ত ব্যৱহাৰ কৰা হ’ব পাৰে, যি অধিক বেটাৰী খৰচ কৰিব পাৰে। যদি এই অনুমতিটো অফ কৰি ৰখা হয়, এই এপ্টোৱে স্বাভাৱিকভাৱে কাম নকৰিব পাৰে আৰু ইয়াৰ এলাৰ্মসমূহে নিৰ্ধাৰিত সময়সূচী অনুযায়ী কাম নকৰিব।"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"এই এপ্টোক এলাৰ্ম ছেট কৰিবলৈ আৰু অন্য কাৰ্যৰ সময়সূচী নিৰ্ধাৰণ কৰিবলৈ দিয়ক। এই এপ্টো আপুনি নিজৰ টেবলেটটো ব্যৱহাৰ কৰি নথকাৰ সময়ত ব্যৱহাৰ কৰা হ’ব পাৰে, যি অধিক বেটাৰী খৰচ কৰিব পাৰে। যদি এই অনুমতিটো অফ কৰি ৰখা হয়, এই এপ্টোৱে স্বাভাৱিকভাৱে কাম নকৰিব পাৰে আৰু ইয়াৰ এলাৰ্মসমূহে নিৰ্ধাৰিত সময়সূচী অনুযায়ী কাম নকৰিব।"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"এই এপ্টোক এলাৰ্ম ছেট কৰিবলৈ আৰু অন্য কাৰ্যৰ সময়সূচী নিৰ্ধাৰণ কৰিবলৈ দিয়ক। এই এপ্টো আপুনি নিজৰ ডিভাইচটো ব্যৱহাৰ কৰি নথকাৰ সময়ত ব্যৱহাৰ কৰা হ’ব পাৰে, যি অধিক বেটাৰী খৰচ কৰিব পাৰে। যদি এই অনুমতিটো অফ কৰি ৰখা হয়, এই এপ্টোৱে স্বাভাৱিকভাৱে কাম নকৰিব পাৰে আৰু ইয়াৰ এলাৰ্মসমূহে নিৰ্ধাৰিত সময়সূচী অনুযায়ী কাম নকৰিব।"</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 6eeef0a..4224e5a 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -54,9 +54,9 @@
<item msgid="9048424957228926377">"Həmişə yoxlayın"</item>
</string-array>
<string-array name="hdcp_checking_summaries">
- <item msgid="4045840870658484038">"Heç vaxt HDCP yoxlama istifadə etməyin"</item>
- <item msgid="8254225038262324761">"Yalnız DRM məzmun oxumaq üçün HDCP istifadə edin"</item>
- <item msgid="6421717003037072581">"Həmişə HDCP yoxlama istifadə edin"</item>
+ <item msgid="4045840870658484038">"HDCP yoxlanılmasın"</item>
+ <item msgid="8254225038262324761">"Yalnız DRM kontenti oxumaq üçün HDCP istifadə edilsin"</item>
+ <item msgid="6421717003037072581">"HDCP yoxlanılsın"</item>
</string-array>
<string-array name="bt_hci_snoop_log_entries">
<item msgid="695678520785580527">"Deaktivdir"</item>
@@ -171,11 +171,11 @@
</string-array>
<string-array name="select_logd_size_summaries">
<item msgid="409235464399258501">"Deaktiv"</item>
- <item msgid="4195153527464162486">"hər jurnal buferinə 64K"</item>
- <item msgid="7464037639415220106">"hər jurnal buferinə 256K"</item>
- <item msgid="8539423820514360724">"hər jurnal buferinə 1M"</item>
- <item msgid="1984761927103140651">"hər jurnal buferinə 4M"</item>
- <item msgid="2983219471251787208">"hər jurnal buferinə 8M"</item>
+ <item msgid="4195153527464162486">"Bufer. Maks: 64K"</item>
+ <item msgid="7464037639415220106">"Bufer. Maks: 256K"</item>
+ <item msgid="8539423820514360724">"Bufer. Maks: 1M"</item>
+ <item msgid="1984761927103140651">"Bufer. Maks: 4M"</item>
+ <item msgid="2983219471251787208">"Bufer. Maks: 8M"</item>
</string-array>
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Deaktiv"</item>
@@ -185,9 +185,9 @@
</string-array>
<string-array name="select_logpersist_summaries">
<item msgid="97587758561106269">"Qeyri-aktiv"</item>
- <item msgid="7126170197336963369">"Bütün loq buferləri"</item>
- <item msgid="7167543126036181392">"Radio loq buferlərindən başqa hamısı"</item>
- <item msgid="5135340178556563979">"yalnız kernel loq bufferi"</item>
+ <item msgid="7126170197336963369">"Bütün jurnal buferləri"</item>
+ <item msgid="7167543126036181392">"Sistem jurnalı buferindən başqa hamısı"</item>
+ <item msgid="5135340178556563979">"yalnız nüvə jurnalı buferi"</item>
</string-array>
<string-array name="window_animation_scale_entries">
<item msgid="2675263395797191850">"Animasiya deaktiv"</item>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index aaa8753b..a5a3321 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -68,7 +68,7 @@
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ayrılır..."</string>
<string name="bluetooth_connecting" msgid="5871702668260192755">"Qoşulur..."</string>
<string name="bluetooth_connected" msgid="8065345572198502293">"Qoşuludur<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
- <string name="bluetooth_pairing" msgid="4269046942588193600">"Cütləşdirmə"</string>
+ <string name="bluetooth_pairing" msgid="4269046942588193600">"Birləşdirilir..."</string>
<string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Qoşuludur (telefon yoxdur)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Qoşuludur (media yoxdur)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_map" msgid="3381860077002724689">"Qoşuludur (mesaj girişi yoxdur)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -94,7 +94,7 @@
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-karta giriş"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Eşitmə Aparatı"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Eşitmə cihazları"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Eşitmə Aparatlarına qoşuldu"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Media audioya birləşdirilib"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Telefon audiosuna qoşulu"</string>
@@ -120,7 +120,7 @@
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ilə birləşdirmək alınmadı."</string>
<string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Yanlış PIN və ya parola görə <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazına qoşulmaq olmur."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ilə ünsiyyət qurula bilmir."</string>
- <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Cütləşdirmə <xliff:g id="DEVICE_NAME">%1$s</xliff:g> tərəfindən rədd edildi."</string>
+ <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> birləşmir."</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Kompüter"</string>
<string name="bluetooth_talkback_headset" msgid="3406852564400882682">"Qulaqlıq"</string>
<string name="bluetooth_talkback_phone" msgid="868393783858123880">"Telefon"</string>
@@ -156,18 +156,18 @@
<string name="launch_defaults_some" msgid="3631650616557252926">"Bəzi susmaya görələr təyin edilib"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"Defolt ayarlanmayıb"</string>
<string name="tts_settings" msgid="8130616705989351312">"Mətndən-danışığa parametrləri"</string>
- <string name="tts_settings_title" msgid="7602210956640483039">"Mətndən-nitqə daxiletmə"</string>
+ <string name="tts_settings_title" msgid="7602210956640483039">"Mətnin səsləndirilməsi"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"Nitq diapazonu"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"Mətnin səsləndirilmə sürəti"</string>
- <string name="tts_default_pitch_title" msgid="6988592215554485479">"Pitç"</string>
+ <string name="tts_default_pitch_title" msgid="6988592215554485479">"Ton"</string>
<string name="tts_default_pitch_summary" msgid="9132719475281551884">"Sintez olunmuş nitqin tonuna təsir edir"</string>
<string name="tts_default_lang_title" msgid="4698933575028098940">"Dil"</string>
- <string name="tts_lang_use_system" msgid="6312945299804012406">"Sistem dili işlədin"</string>
+ <string name="tts_lang_use_system" msgid="6312945299804012406">"Sistem dili"</string>
<string name="tts_lang_not_selected" msgid="7927823081096056147">"Dil seçilməyib"</string>
<string name="tts_default_lang_summary" msgid="9042620014800063470">"Danışılan oxunulan mətnə dil üçün spesifik səs ayarlayır"</string>
<string name="tts_play_example_title" msgid="1599468547216481684">"Nümunə dinləyin"</string>
<string name="tts_play_example_summary" msgid="634044730710636383">"Nitq sintezindən nümunə göstərin"</string>
- <string name="tts_install_data_title" msgid="1829942496472751703">"Səs datasını quraşdırın"</string>
+ <string name="tts_install_data_title" msgid="1829942496472751703">"Səs datasının quraşdırılması"</string>
<string name="tts_install_data_summary" msgid="3608874324992243851">"Nitq sintezi üçün səs datası quraşdırın"</string>
<string name="tts_engine_security_warning" msgid="3372432853837988146">"Bu nitq sitnez mühərriki danışılan bütün mətni, həmçinin parollarınızı və kredir kart nömrələrinizi toplaya bilər. <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> mühərrikindən gəlir. Nitq sintez mühərriki istifadə olunsun?"</string>
<string name="tts_engine_network_required" msgid="8722087649733906851">"Bu dil mətnin nitqə çıxışı üçün şəbəkə bağlantısı tələb edir."</string>
@@ -179,7 +179,7 @@
<string name="tts_status_checking" msgid="8026559918948285013">"Yoxlanılır..."</string>
<string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> üçün ayarlar"</string>
<string name="tts_engine_settings_button" msgid="477155276199968948">"Mühərrik parametrlərini başladın"</string>
- <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"Tərcih olunmuş mühərrik"</string>
+ <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"Defolt nitq sintezatoru"</string>
<string name="tts_general_section_title" msgid="8919671529502364567">"Ümumi"</string>
<string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"Nitq tembrini sıfırlayın"</string>
<string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"Mətnin defolt səsləndirilmə tembrini sıfırlayın."</string>
@@ -205,18 +205,18 @@
<string name="tethering_settings_not_available" msgid="266821736434699780">"Modem ayarları bu istifadəçiyə qapalıdır"</string>
<string name="apn_settings_not_available" msgid="1147111671403342300">"Giriş Nöqtəsi Ad Ayarları bu istifadəçi üçün əlçatmazdır"</string>
<string name="enable_adb" msgid="8072776357237289039">"USB debaq prosesi"</string>
- <string name="enable_adb_summary" msgid="3711526030096574316">"USB qoşulu olan zaman debaq rejimi"</string>
- <string name="clear_adb_keys" msgid="3010148733140369917">"USB debaq avtorizasiyasını ləğv edin"</string>
+ <string name="enable_adb_summary" msgid="3711526030096574316">"USB qoşulanda sazlama"</string>
+ <string name="clear_adb_keys" msgid="3010148733140369917">"USB ilə sazlama icazəsi ləğv edilsin"</string>
<string name="enable_adb_wireless" msgid="6973226350963971018">"Wi-Fi vasitəsilə sazlama"</string>
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi qoşulduqda sazlama rejimi"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Xəta"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Wi-Fi vasitəsilə sazlama"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Cihazları görmək və istifadə etmək üçün WiFi vasitəsilə sazlamanı işə salın"</string>
- <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR kodu ilə cihazı cütləşdirin"</string>
+ <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR kodu ilə cihazı birləşdirin"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"QR kod skanerindən istifadə etməklə yeni cihazları birləşdirin"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"Qoşulma kodu ilə cihazı əlavə edin"</string>
- <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Altı rəqəmli koddan istifadə etməklə yeni cihazları cütləşdirin"</string>
- <string name="adb_paired_devices_title" msgid="5268997341526217362">"Cütləşdirilmiş cihazlar"</string>
+ <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Altı rəqəmli kod istifadə etməklə yeni cihazları birləşdirin"</string>
+ <string name="adb_paired_devices_title" msgid="5268997341526217362">"Birləşdirilmiş cihazlar"</string>
<string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Hazırda qoşulub"</string>
<string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Cihaz detalları"</string>
<string name="adb_device_forget" msgid="193072400783068417">"Unudun"</string>
@@ -227,7 +227,7 @@
<string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi qoşulma kodu"</string>
<string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Qoşula bilmir"</string>
<string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Eyni şəbəkəyə qoşulduğunu dəqiqləşdirin."</string>
- <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR kodu skanlamaqla cihazı Wi‑Fi vasitəsilə cütləşdirin"</string>
+ <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR kodunu skan edib cihazı Wi‑Fi ilə birləşdirin"</string>
<string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Cihaz cütləşdirilir…"</string>
<string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Cihazı cütləşdirmək alınmadı. Ya QR kodu yanlış idi, ya da cihaz eyni şəbəkəyə qoşulmayıb."</string>
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ünvanı və Port"</string>
@@ -235,11 +235,11 @@
<string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"QR kodu skanlamaqla cihazı Wi‑Fi vasitəsilə birləşdirin"</string>
<string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi şəbəkəsinə qoşulun"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
- <string name="bugreport_in_power" msgid="8664089072534638709">"Baq raportu qısa yolu"</string>
- <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Baq raportunu götürmək üçün qidalanma menyusunda düyməni göstərin"</string>
+ <string name="bugreport_in_power" msgid="8664089072534638709">"Xəta hesabatı"</string>
+ <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Qidalanma düyməsi menyusunda xəta hesabatının göndərilməsi punktu göstərilsin"</string>
<string name="keep_screen_on" msgid="1187161672348797558">"Oyaq qal"</string>
<string name="keep_screen_on_summary" msgid="1510731514101925829">"Enereji doldurularkən ekran heç vaxt yuxu rejimində olmur"</string>
- <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Bluetooth HCI izləmə jurnalını aktivləşdir"</string>
+ <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Bluetooth HCI jurnalı aktivləşdirilsin"</string>
<string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"Bluetooth paketləri əldə edin. (Bu ayarı dəyişdikdən sonra Bluetooth\'u aktiv/deaktiv edin)"</string>
<string name="oem_unlock_enable" msgid="5334869171871566731">"OEM kilidinin açılması"</string>
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Əməliyyat sistemi yükləyicisinin kilidinin açılmasına icazə ver"</string>
@@ -249,25 +249,25 @@
<string name="mock_location_app_not_set" msgid="6972032787262831155">"Ayarlanmış saxta məkan tətbiqi yoxdur"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"Saxta məkan tətbiqi: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Şəbəkələşmə"</string>
- <string name="wifi_display_certification" msgid="1805579519992520381">"Simsiz displey sertifikatlaşması"</string>
+ <string name="wifi_display_certification" msgid="1805579519992520381">"Simsiz monitor sertifikatlaşması"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi‑Fi Çoxsözlü Girişə icazə verin"</string>
- <string name="wifi_scan_throttling" msgid="2985624788509913617">"Wi‑Fi skanlamasının tənzimlənməsi"</string>
+ <string name="wifi_scan_throttling" msgid="2985624788509913617">"Wi‑Fi axtarışının məhdudlaşdırılması"</string>
<string name="wifi_enhanced_mac_randomization" msgid="882650208573834301">"Wi‑Fi müvəqqəti MAC randomizasiyası"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"Mobil data həmişə aktiv"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Modem rejimində cihaz sürətləndiricisi"</string>
- <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Bluetooth cihazlarını adsız göstərin"</string>
- <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Mütləq səs həcmi deaktiv edin"</string>
- <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche\'ni aktiv edin"</string>
+ <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Bluetooth cihazları adsız göstərilsin"</string>
+ <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Mütləq səs həcmi deaktiv edilsin"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche aktiv edilsin"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP Versiya"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP Versiyasını seçin"</string>
<string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP Versiyası"</string>
<string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP Versiyasını seçin"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio Kodek"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Audio KodeK\nSeçimini aktiv edin"</string>
- <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio Nümunə Göstəricisi"</string>
- <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth Audio Kodek\nSeçimini aktiv edin: Nümunə Göstəricisi"</string>
+ <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio diskredizasiya tezliyi"</string>
+ <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth üçün audiokodek işə salınsın\nSeçim: Diskredizasiya tezliyi"</string>
<string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Boz rəng telefon və ya qulaqlıq tərəfindən dəstəklənmədiyini bildirir"</string>
- <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Hər Nümunə Üçün Bluetooth Audio Bit"</string>
+ <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth səs örnəyi üzrə bit"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth Audio Kodek\nSeçimini aktiv edin: Hər Nümunə üçün Bit"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Audio Kanal Rejimi"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"Bluetooth Audio Kodek\nSeçimini aktiv edin: Kanal Rejimi"</string>
@@ -281,24 +281,24 @@
<string name="private_dns_mode_provider" msgid="3619040641762557028">"Şəxsi DNS provayder hostunun adı"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"DNS provayder host adını daxil edin"</string>
<string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"Qoşulmaq mümkün olmadı"</string>
- <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Simsiz displey sertifikatlaşması üçün seçimləri göstərir"</string>
+ <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Simsiz monitorların sertifikasiya parametrləri göstərilsin"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi‑Fi giriş səviyyəsini qaldırın, Wi‑Fi seçəndə hər SSID RSSI üzrə göstərin"</string>
- <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Batareya istifadəsini azaldır & şəbəkə performansını yaxşılaşdırır"</string>
- <string name="wifi_enhanced_mac_randomization_summary" msgid="1210663439867489931">"Bu rejim deaktiv edildikdə, bu cihaz hər dəfə MAC randomizasiyası aktiv edilmiş şəbəkəyə qoşulanda onun MAC ünvanı dəyişə bilər."</string>
+ <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Enerji sərfiyyatını azaldır və şəbəkənin işini yaxşılaşdırır"</string>
+ <string name="wifi_enhanced_mac_randomization_summary" msgid="1210663439867489931">"Bu rejimdə şəbəkəyə hər dəfə qoşulanda cihaza təsadüfi MAC ünvanı verilə bilər."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"Tarif sayğacılı"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"Limitsiz"</string>
- <string name="select_logd_size_title" msgid="1604578195914595173">"Logger bufer ölçüləri"</string>
- <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Hər jurnal buferinı Logger ölçüsü seçin"</string>
+ <string name="select_logd_size_title" msgid="1604578195914595173">"Jurnal buferi ölçüsü"</string>
+ <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Jurnal buferi ölçüsünü seçin"</string>
<string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Loqqerin davamlı yaddaşı silinsin?"</string>
<string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Artıq davamlı loqqer ilə izləmədiyimiz zaman, cihazınızdakı loqqer data rezidentini silmək tələb olunur."</string>
- <string name="select_logpersist_title" msgid="447071974007104196">"Loqqer datasını davamlı olaraq cihazda saxlayın"</string>
+ <string name="select_logpersist_title" msgid="447071974007104196">"Jurnal məlumatları daima cihazda saxlanılsın"</string>
<string name="select_logpersist_dialog_title" msgid="7745193591195485594">"Davamlı olaraq cihazda yadda saxlamaq üçün loq buferlərini seçin"</string>
<string name="select_usb_configuration_title" msgid="6339801314922294586">"USB Sazlaması seçin"</string>
<string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"USB Sazlaması seçin"</string>
<string name="allow_mock_location" msgid="2102650981552527884">"Sınaq yerləşmələrə icazə verin"</string>
<string name="allow_mock_location_summary" msgid="179780881081354579">"Sınaq yerləşmələrə icazə verin"</string>
- <string name="debug_view_attributes" msgid="3539609843984208216">"Atribut inspeksiyasına baxışa icazə verin"</string>
- <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Hətta Wi‑Fi aktiv olanda da mobil datanı həmişə aktiv saxlayın (sürətli şəbəkək keçidi üçün)."</string>
+ <string name="debug_view_attributes" msgid="3539609843984208216">"Atributlar yoxlanılsın"</string>
+ <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Hətta Wi-Fi bağlantısı olanda da məlumatların mobil şəbəkə ilə ötürülməsi yolu açıq qalsın (şəbəkələr arasında cəld keçid üçün)"</string>
<string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"İmkan olduqda, modem rejimində cihaz sürətləndiricisi istifadə olunsun"</string>
<string name="adb_warning_title" msgid="7708653449506485728">"USB debaq funksiyasına icazə verilsin?"</string>
<string name="adb_warning_message" msgid="8145270656419669221">"USB sazlanması yalnız inkişaf məqsədlidir. Kompüteriniz və cihazınız arasında datanı kopyalamaq üçün ondan istifadə edin, bildiriş olmadan tətbiqləri cihazınıza quraşdırın və qeydiyyat datasını oxuyun."</string>
@@ -307,80 +307,79 @@
<string name="adb_keys_warning_message" msgid="2968555274488101220">"Əvvəl icazə verdiyiniz kompüterlərdən USB debaq əməliyyatına giriş ləğv olunsun?"</string>
<string name="dev_settings_warning_title" msgid="8251234890169074553">"İnkişaf ayarlarına icazə verilsin mi?"</string>
<string name="dev_settings_warning_message" msgid="37741686486073668">"Bu parametrlər yalnız inkişafetdirici istifadə üçün nəzərdə tutulub. Onlar cihaz və tətbiqlərinizin sınması və ya pis işləməsinə səbəb ola bilər."</string>
- <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB üzərindən tətbiqləri yoxlayın"</string>
+ <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Tətbiqlər quraşdırılanda yoxlanılsın"</string>
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT vasitəsi ilə quraşdırılmış tətbiqləri zərərli davranış üzrə yoxlayın."</string>
- <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Adsız Bluetooth cihazları (yalnız MAC ünvanları) göstəriləcək"</string>
- <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Uzaqdan idarə olunan cihazlarda dözülməz yüksək səs həcmi və ya nəzarət çatışmazlığı kimi səs problemləri olduqda Bluetooth mütləq səs həcmi xüsusiyyətini deaktiv edir."</string>
- <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche funksiyasını aktiv edir."</string>
+ <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth cihazları adsız (yalnız MAC ünvanları ilə) göstərilsin"</string>
+ <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Kənar cihazlarda problem olanda (yüksək səs həcmi və ya nəzarət çatışmazlığı) Bluetooth səs həcminin mütləq səviyyəsini deaktiv edir."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche funksiya toplusunu aktiv edir."</string>
<string name="enhanced_connectivity_summary" msgid="1576414159820676330">"Qabaqcıl məlumat mübadiləsini aktiv edir."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Yerli terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Yerli örtük girişini təklif edən terminal tətbiqi aktiv edin"</string>
- <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP yoxlanılır"</string>
- <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"HDCP davranış yoxlamasını ayarlayın"</string>
+ <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP yoxlanışı"</string>
+ <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"HDCP yoxlanışı qaydası ayalansın"</string>
<string name="debug_debugging_category" msgid="535341063709248842">"Sazlama"</string>
- <string name="debug_app" msgid="8903350241392391766">"Debaq tətbiqi seçin"</string>
- <string name="debug_app_not_set" msgid="1934083001283807188">"Debaq tətbiqi ayarlanmayıb"</string>
+ <string name="debug_app" msgid="8903350241392391766">"Sazlamaq üçün tətbiq seçin"</string>
+ <string name="debug_app_not_set" msgid="1934083001283807188">"Sazlamaq üçün tətbiq seçilməyib"</string>
<string name="debug_app_set" msgid="6599535090477753651">"Tətbiq debaq olunur: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="2543228890535466325">"Tətbiq seçin"</string>
<string name="no_application" msgid="9038334538870247690">"Heç nə"</string>
- <string name="wait_for_debugger" msgid="7461199843335409809">"Sazlamanı gözləyin"</string>
- <string name="wait_for_debugger_summary" msgid="6846330006113363286">"Sazlanmış tətbiq icradan əvvəl qoşulmaq üçün sazlayıcı gözləyir"</string>
+ <string name="wait_for_debugger" msgid="7461199843335409809">"Sazlayıcını gözləyin"</string>
+ <string name="wait_for_debugger_summary" msgid="6846330006113363286">"Tətbiq sazlayıcının qoşulmasını gözləyir"</string>
<string name="debug_input_category" msgid="7349460906970849771">"Daxiletmə"</string>
<string name="debug_drawing_category" msgid="5066171112313666619">"Təsvir"</string>
- <string name="debug_hw_drawing_category" msgid="5830815169336975162">"Avadanlıq qaldırma renderi"</string>
+ <string name="debug_hw_drawing_category" msgid="5830815169336975162">"Renderinq aparat sürətlənməsi"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitorinq"</string>
- <string name="strict_mode" msgid="889864762140862437">"Məhdud rejim aktivdir"</string>
- <string name="strict_mode_summary" msgid="1838248687233554654">"Əsas axında tətbiqlərin əlavə əməliyyatlar etməsi zamanı ekran işartısı olsun"</string>
+ <string name="strict_mode" msgid="889864762140862437">"Ciddi rejim"</string>
+ <string name="strict_mode_summary" msgid="1838248687233554654">"Uzun əməliyyatlar ərzində ekran işıqlandırılsın"</string>
<string name="pointer_location" msgid="7516929526199520173">"Kursor yeri"</string>
- <string name="pointer_location_summary" msgid="957120116989798464">"Cari əlaqə datasını göstərən ekran örtüyü"</string>
- <string name="show_touches" msgid="8437666942161289025">"Tıklamaları göstərin"</string>
- <string name="show_touches_summary" msgid="3692861665994502193">"Tıklamalar üçün vizual cavab rəylərini göstərin"</string>
- <string name="show_screen_updates" msgid="2078782895825535494">"Səth güncəlləşməsini göstər"</string>
- <string name="show_screen_updates_summary" msgid="2126932969682087406">"Güncəlləmədən sonra bütün ekranda işartı olsun"</string>
- <string name="show_hw_screen_updates" msgid="2021286231267747506">"Görüntü yeniliklərinə baxın"</string>
- <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"pəncərələrin daxilindəki fleş görüntüləri"</string>
- <string name="show_hw_layers_updates" msgid="5268370750002509767">"Avadanlıq düzənlərinin güncəlləşməsini göstərin"</string>
- <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Onlar güncəllənəndən sonra avadanlıq qatlarında işartı olsun"</string>
- <string name="debug_hw_overdraw" msgid="8944851091008756796">"GPU böyütməsini sazlayın"</string>
- <string name="disable_overlays" msgid="4206590799671557143">"HW overlay deaktiv edin"</string>
- <string name="disable_overlays_summary" msgid="1954852414363338166">"Həmişə ekran kompozisiyası üçün GPU istifadə edin"</string>
- <string name="simulate_color_space" msgid="1206503300335835151">"Rəng sahəsini simulyasiya edin"</string>
+ <string name="pointer_location_summary" msgid="957120116989798464">"Toxunuş və jest datası göstərilsin"</string>
+ <string name="show_touches" msgid="8437666942161289025">"Vizual reaksiya"</string>
+ <string name="show_touches_summary" msgid="3692861665994502193">"Toxunuşa vizual reaksiya verilsin"</string>
+ <string name="show_screen_updates" msgid="2078782895825535494">"Səth yenilənməsi göstərilsin"</string>
+ <string name="show_screen_updates_summary" msgid="2126932969682087406">"Pəncərə səthi təzələnəndə işıqlansın"</string>
+ <string name="show_hw_screen_updates" msgid="2021286231267747506">"Baxış yenilənməsi göstərilsin"</string>
+ <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"Çəkəndə ekran sahələri işıqlansın"</string>
+ <string name="show_hw_layers_updates" msgid="5268370750002509767">"Aparat yenilənməsi göstərilsin"</string>
+ <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Yenilənəndə aparat qatları yaşıl rənglə ayrılsın"</string>
+ <string name="debug_hw_overdraw" msgid="8944851091008756796">"GPU artıqlaması sazlansın"</string>
+ <string name="disable_overlays" msgid="4206590799671557143">"Aparat qatı deaktiv edilsin"</string>
+ <string name="disable_overlays_summary" msgid="1954852414363338166">"Ekran kompozisiyası üçün GPU istifadə edilsin"</string>
+ <string name="simulate_color_space" msgid="1206503300335835151">"Anomaliya simulyasiyası"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL izlərini aktivləşdirin"</string>
- <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB audio marşrutu deaktiv edin"</string>
- <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB audio periferiyalara avtomatik marşrutu deaktiv edin"</string>
- <string name="debug_layout" msgid="1659216803043339741">"Düzən həddini göstər"</string>
- <string name="debug_layout_summary" msgid="8825829038287321978">"Klip sərhədləri, boşluqları və s. göstər"</string>
+ <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB audiomarşrut deaktiv edilsin"</string>
+ <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Xarici USB-yə avto-marşrutizasiya deaktiv edilsin"</string>
+ <string name="debug_layout" msgid="1659216803043339741">"Element sərhəddi göstərilsin"</string>
+ <string name="debug_layout_summary" msgid="8825829038287321978">"Kəsim sərhəddi, sahəsi və digər şeyləri göstərilsin"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL düzən istiqamətinə məcbur edin"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Ekran düzən istiqamətini RTL üzərinə bütün yerli variantlar üçün məcbur edin"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
- <string name="force_msaa" msgid="4081288296137775550">"4x MSAA məcbur edin"</string>
- <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 tətbiqlərində 4x MSAA aktiv et"</string>
- <string name="show_non_rect_clip" msgid="7499758654867881817">"Qeyri-düzbucaqlı klip əməliyyatlarını debaq edin"</string>
- <string name="track_frame_time" msgid="522674651937771106">"Profil HWUI bərpası"</string>
- <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"GPU debaq təbəqələrini aktiv edin"</string>
- <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"GPU debaq təbəqələrinin yüklənməsinə icazə verin"</string>
- <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Detallı təchizatçı qeydini aktiv edin"</string>
- <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Xəta hesabatlarına cihaza xas əlavə təchizatçı jurnallarını daxil edin, lakin nəzərə alın ki, onlar şəxsi məlumatları ehtiva edə, daha çox batareya istifadə edə və/və ya daha çox yaddaş istifadə edə bilər."</string>
- <string name="window_animation_scale_title" msgid="5236381298376812508">"Pəncərə animasiya miqyası"</string>
- <string name="transition_animation_scale_title" msgid="1278477690695439337">"Animasiya keçid miqyası"</string>
- <string name="animator_duration_scale_title" msgid="7082913931326085176">"Animator müddət şkalası"</string>
+ <string name="window_blurs" msgid="6831008984828425106">"Pəncərə səviyyəsində bulanıqlığa icazə verin"</string>
+ <string name="force_msaa" msgid="4081288296137775550">"4x MSAA aktiv edilsin"</string>
+ <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 tətbiqlərində 4x MSAA aktiv edilsin"</string>
+ <string name="show_non_rect_clip" msgid="7499758654867881817">"Mürəkkəb formaların kəsilməsi əməliyyatı sazlansın"</string>
+ <string name="track_frame_time" msgid="522674651937771106">"HWUI iş vaxtı uçotu"</string>
+ <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Qrafik prosessor sazlanması"</string>
+ <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Qrafik prosessor qatları sazlanmasının yüklənməsinə icazə verilsin"</string>
+ <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Təfsilatlı təchizatçı jurnalı"</string>
+ <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Xəta hesabatına təchizatçının cihaz haqqında əlavə qeydləri daxil edilsin. Qeydlərdə şəxsi məlumatlar ola, onlar artıq yer tuta və enerji sərfiyyatını artıra bilər."</string>
+ <string name="window_animation_scale_title" msgid="5236381298376812508">"Pəncərə animasiyası"</string>
+ <string name="transition_animation_scale_title" msgid="1278477690695439337">"Keçid animasiyası"</string>
+ <string name="animator_duration_scale_title" msgid="7082913931326085176">"Animasiya müddəti"</string>
<string name="overlay_display_devices_title" msgid="5411894622334469607">"İkincili displeyi imitasiya edin"</string>
<string name="debug_applications_category" msgid="5394089406638954196">"Tətbiqlər"</string>
- <string name="immediately_destroy_activities" msgid="1826287490705167403">"Fəaliyyətləri saxlamayın"</string>
- <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"İstifadəçinin tərk etdiyi hər fəaliyyəti dərhal məhv et"</string>
+ <string name="immediately_destroy_activities" msgid="1826287490705167403">"Fəaliyyətlər saxlanmasın"</string>
+ <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"İstifadəçi çıxan kimi fəaliyyət silinsin"</string>
<string name="app_process_limit_title" msgid="8361367869453043007">"Fon prosesi limiti"</string>
- <string name="show_all_anrs" msgid="9160563836616468726">"Arxa fon ANR-lərini göstərin"</string>
- <string name="show_all_anrs_summary" msgid="8562788834431971392">"Arxa fon tətbiqləri üçün Tətbiq Cavab Vermir dialoqunu göstərin"</string>
+ <string name="show_all_anrs" msgid="9160563836616468726">"Fonda ANR"</string>
+ <string name="show_all_anrs_summary" msgid="8562788834431971392">"Fondakı tətbiq cavab verməyəndə bildirilsin"</string>
<string name="show_notification_channel_warnings" msgid="3448282400127597331">"Xəbərdarlıqları göstərin"</string>
<string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"Bildiriş paylaşıldıqda xəbərdarlıq göstərir"</string>
- <string name="force_allow_on_external" msgid="9187902444231637880">"Tətbiqlərə xaricdən məcburi icazə"</string>
- <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Seçilmiş hər hansı tətbiqi bəyannamə dəyərlərindən aslı olmayaraq xarici yaddaşa yazılabilən edir."</string>
- <string name="force_resizable_activities" msgid="7143612144399959606">"Ölçü dəyişdirmək üçün məcburi fəaliyyətlər"</string>
- <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Bəyannamə dəyərlərindən aslı olmayaraq, bütün fəaliyyətləri çoxsaylı pəncərə üçün dəyişkən ölçülü edin."</string>
- <string name="enable_freeform_support" msgid="7599125687603914253">"Freeform windows aktiv edin"</string>
- <string name="enable_freeform_support_summary" msgid="1822862728719276331">"Sınaq üçün freeform windows aktiv edilir."</string>
+ <string name="force_allow_on_external" msgid="9187902444231637880">"Xarici daşıyıcılarda saxlanmaya icazə verilsin"</string>
+ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Manifest dəyərindən asılı olmayaraq tətbiqlərin xarici daşıyıcılarda saxlanmasına icazə verilsin"</string>
+ <string name="force_resizable_activities" msgid="7143612144399959606">"Çoxpəncərəli rejimdə ölçü dəyişdirilməsi"</string>
+ <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Manifest dəyərindən asılı olmayaraq çoxpəncərəli rejimdə pəncərə ölçüsünün dəyişdirilməsinə icazə verilsin"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"İxtiyari formada pəncərə yaradılsın"</string>
+ <string name="enable_freeform_support_summary" msgid="1822862728719276331">"Eksperimental olaraq ixtiyari formada pəncərə yaradılsın"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Masaüstü rezerv parolu"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Masaüstü tam rezervlər hazırda qorunmayıblar."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Masaüstünün tam rezerv kopyalanması üçün parolu dəyişmək və ya silmək üçün basın"</string>
@@ -398,20 +397,20 @@
<item msgid="4548987861791236754">"Gözlə göründüyü kimi təbii rənglər"</item>
<item msgid="1282170165150762976">"Rəqəmsal məzmun üçün optimallaşdırılan rənglər"</item>
</string-array>
- <string name="inactive_apps_title" msgid="5372523625297212320">"Arxa fonda məhdudlaşdırılan tətbiq"</string>
+ <string name="inactive_apps_title" msgid="5372523625297212320">"Gözləmə rejimində tətbiqlər"</string>
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Deaktivdir. Keçid etmək üçün basın."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivdir. Keçid etmək üçün basın."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Tətbiqin gözləmə rejimi:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="2581975870429850549">"Media yenidən kodlaşdırma ayarları"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Media kodçevirmə ayarları"</string>
<string name="transcode_user_control" msgid="6176368544817731314">"Yenidən kodlaşdırma defoltlarını əvəzləyin"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Yenidən kodlaşdırmanı aktiv edin"</string>
<string name="transcode_default" msgid="3784803084573509491">"Tətbiqlərin müasir formatları dəstəklədiyini qəbul edin"</string>
<string name="transcode_notification" msgid="5560515979793436168">"Kod dəyişmə bildirişlərini göstərin"</string>
<string name="transcode_disable_cache" msgid="3160069309377467045">"Keşin kodlaşdırılmasını deaktiv edin"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"İşləyən xidmətlər"</string>
- <string name="runningservices_settings_summary" msgid="1046080643262665743">"Hazırda prosesdə olan xidmətləri görüntüləyin və onlara nəzarət edin"</string>
- <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView icrası"</string>
- <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView icrasını ayarlayın"</string>
+ <string name="runningservices_settings_summary" msgid="1046080643262665743">"İşlək xidmətlərə baxış və onların idarəedilməsi"</string>
+ <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView servisi"</string>
+ <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView servisini ayarlayın"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Bu seçim artıq etibarlı deyil. Yenidən cəhd edin."</string>
<string name="convert_to_file_encryption" msgid="2828976934129751818">"Fayl şifrələnməsinə çevirin"</string>
<string name="convert_to_file_encryption_enabled" msgid="840757431284311754">"Çevirin..."</string>
@@ -426,8 +425,8 @@
<string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"Deuteranomaliya (qırmızı-yaşıl)"</string>
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qırmızı-yaşıl)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (göy-sarı)"</string>
- <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rəng düzəlişi"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Cihazınızda rənglərin necə göstərilməsini tənzimləyin. Bu, aşağıdakıları etmək istədikdə faydalı ola bilər:<br/><br/> <ol> <li>&nbsp;Rəngləri daha dəqiq görmək</li> <li>&nbsp;Fokuslanmaq üçün rəngləri ləğv etmək</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rəng korreksiyası"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ekranda rəngi korreksiya edə bilərsiniz. Mümkün olanlar:<br/><br/> <ol> <li>&nbsp;rəng ötürülməsinin yaxşılaşdırılması;</li> <li>&nbsp;rahat fokuslanmaq üçün ağ-qara rejimə keçid.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Siqnallar və xatırladıcılar"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Siqnallar və xatırlatmaları ayarlamağa icazə verin"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Siqnallar və xatırlatmalar"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Bu tətbiqə zəngli saat və bildiriş hazırlamaq icazəsi verdiyiniz halda tətbiq cihaz istifadə edilmədiyi zaman da işləyəcək, enerji daha tez qurtaracaq. Bu ayar deaktiv ediləndən sonra tətbiqin işində kəsintilər ola, zəngli saatlar vaxtında işləməyə bilər."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Bu tətbiqə zəngli saat və bildiriş hazırlamaq icazəsi verdiyiniz halda tətbiq cihaz istifadə edilmədiyi zaman da işləyəcək, enerji daha tez qurtaracaq. Bu ayar deaktiv ediləndən sonra tətbiqin işində kəsintilər ola, zəngli saatlar vaxtında işləməyə bilər."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Bu tətbiqə zəngli saat və bildiriş hazırlamaq icazəsi verdiyiniz halda tətbiq cihaz istifadə edilmədiyi zaman da işləyəcək, enerji daha tez qurtaracaq. Bu ayar deaktiv ediləndən sonra tətbiqin işində kəsintilər ola, zəngli saatlar vaxtında işləməyə bilər."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu tətbiqə siqnallar ayarlamağa və vaxta əsaslanan əməliyyatları planlaşdırmağa icazə verin. Bu, tətbiqin arxa fonda işləməsinə imkan verir ki, nəticədə daha çox enerji istifadə edilə bilər.\n\nBu icazə deaktiv olsa, bu tətbiq tərəfindən planlaşdırılan mövcud siqnallar və vaxta əsaslanan tədbirlər işləməyəcəkdir."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"cədvəl, siqnal, xatırlatma, saat"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktiv edin"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\"Narahat Etməyin\" rejimini aktiv edin"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 1edd95e..7903230 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -236,7 +236,7 @@
<string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Povežite se na WiFi mrežu"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, otklanjanje grešaka, programer"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Prečica za izveštaj o greškama"</string>
- <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikazuje dugme u meniju napajanja za pravljenje izveštaja o greškama"</string>
+ <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikazuje dugme u meniju dugmeta za uključivanje za pravljenje izveštaja o greškama"</string>
<string name="keep_screen_on" msgid="1187161672348797558">"Ne zaključavaj"</string>
<string name="keep_screen_on_summary" msgid="1510731514101925829">"Ekran neće biti u režimu spavanja tokom punjenja"</string>
<string name="bt_hci_snoop_log" msgid="7291287955649081448">"Omogući snoop evid. za Bluetooth HCI"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Prikazuje granice klipa, margine itd."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Nametni smer rasporeda zdesna nalevo"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Nameće smer rasporeda ekrana zdesna nalevo za sve lokalitete"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Dozvoli zamagljenja prozora"</string>
<string name="force_msaa" msgid="4081288296137775550">"Nametni 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Omogućava 4x MSAA u OpenGL ES 2.0 aplikacijama"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Otkloni greške isecanja oblasti nepravougaonog oblika"</string>
@@ -509,9 +508,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsetnici"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Omogući podešavanje alarma i podsetnika"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsetnici"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Omogućite ovoj aplikaciji da podešava alarme i zakazuje druge radnje. Ova aplikacija može da se koristi kada ne koristite telefon, što može da dodatno troši bateriju. Ako je ova dozvola isključena, ova aplikacija možda neće raditi normalno i njeni alarmi neće raditi po rasporedu."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Omogućite ovoj aplikaciji da podešava alarme i zakazuje druge radnje. Ova aplikacija može da se koristi kada ne koristite tablet, što može da dodatno troši bateriju. Ako je ova dozvola isključena, ova aplikacija možda neće raditi normalno i njeni alarmi neće raditi po rasporedu."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Omogućite ovoj aplikaciji da podešava alarme i zakazuje druge radnje. Ova aplikacija može da se koristi kada ne koristite uređaj, što može da dodatno troši bateriju. Ako je ova dozvola isključena, ova aplikacija možda neće raditi normalno i njeni alarmi neće raditi po rasporedu."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Omogućite ovoj aplikaciji da podešava alarme i zakazuje vremenski osetljive radnje. To omogućava da aplikacija bude pokrenuta u pozadini, što može da troši više baterije.\n\nAko je ova dozvola isključena, postojeći alarmi i događaji zasnovani na vremenu zakazani pomoću ove aplikacije neće raditi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"zakazati, alarm, podsetnik, sat"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključite režim Ne uznemiravaj"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index d20e5da..0fb7178 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Паказаць межы абрэзкі, палі і г. д."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Прымусовая раскладка справа налева"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Прымусовая раскладка экрана справа налева для ўсіх рэгіянальных налад"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Размываць на ўзроўні акна"</string>
<string name="force_msaa" msgid="4081288296137775550">"Прымусовае выкананне 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Уключыць 4x MSAA у праграмах з OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Адладка аперацый непрамавугольнага кліпа"</string>
@@ -510,9 +509,8 @@
<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" product="default" msgid="1122213569699233612">"Дазвольце гэтай праграме ўсталёўваць будзільнікі і задаваць расклад для дзеянняў. Праграма можа працаваць, калі вы не выкарыстоўваеце тэлефон, і ў выніку хутчэй разраджаць акумулятар. Калі гэты дазвол выключаны, праграма можа не працаваць належым чынам, а яе будзільнікі – не спрацоўваць як запланавана."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Дазвольце гэтай праграме ўсталёўваць будзільнікі і задаваць расклад для дзеянняў. Праграма можа працаваць, калі вы не выкарыстоўваеце планшэт, і ў выніку хутчэй разраджаць акумулятар. Калі гэты дазвол выключаны, праграма можа не працаваць належым чынам, а яе будзільнікі – не спрацоўваць як запланавана."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Дазвольце гэтай праграме ўсталёўваць будзільнікі і задаваць расклад для дзеянняў. Праграма можа працаваць, калі вы не выкарыстоўваеце прыладу, і ў выніку хутчэй разраджаць акумулятар. Калі гэты дазвол выключаны, праграма можа не працаваць належым чынам, а яе будзільнікі – не спрацоўваць як запланавана."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index d92256d..4d92282 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Показв. на границите на изрязване, полетата и др."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Принуд. оформл. от дясно наляво"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Принудително оформление на екрана от дясно наляво за всички локали"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Замъгл. на ниво прозорец"</string>
<string name="force_msaa" msgid="4081288296137775550">"Задаване на 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Активиране на 4x MSAA в прилож. с OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Отстр. на грешки при неправоъг. изрязване"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"Разрешете на това приложение да задава будилници и да насрочва други действия. То може да работи, когато не използвате телефона си, и затова да изразходва повече енергия. Ако това разрешение е изключено, приложението може да не функционира нормално, а зададените будилници няма да работят."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Разрешете на това приложение да задава будилници и да насрочва други действия. То може да работи, когато не използвате таблета си, и затова да изразходва повече енергия. Ако това разрешение е изключено, приложението може да не функционира нормално, а зададените будилници няма да работят."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Разрешете на това приложение да задава будилници и да насрочва други действия. То може да работи, когато не използвате устройството си, и затова да изразходва повече енергия. Ако това разрешение е изключено, приложението може да не функционира нормално, а зададените будилници няма да работят."</string>
+ <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>
@@ -563,7 +560,7 @@
<string name="profile_info_settings_title" msgid="105699672534365099">"Инф. за потр. профил"</string>
<string name="user_need_lock_message" msgid="4311424336209509301">"Преди да можете да създадете потребителски профил с ограничена функционалност, трябва да настроите заключения екран, за да защитите приложенията и личните си данни."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Задаване на заключване"</string>
- <string name="user_switch_to_user" msgid="6975428297154968543">"Превключване към <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <string name="user_switch_to_user" msgid="6975428297154968543">"Превключване към: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Създава се нов потребител…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Неуспешно създаване на нов потребител"</string>
<string name="user_nickname" msgid="262624187455825083">"Псевдоним"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 9c8eff4..b7fdef2 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"ক্লিপ বাউন্ড, মার্জিন ইত্যাদি দেখান"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL লেআউট দিকনির্দেশ জোর দিন"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"সমস্ত স্থানের জন্য RTL এ স্ক্রিন লেআউট দিকনির্দেশে জোর দেয়"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"উইন্ডো-লেভেল অস্পষ্ট করার সুবিধা চালু করুন"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA-এ জোর দিন"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 অ্যাপের মধ্যে 4x MSAA চালু করুন"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"অ-আয়তক্ষেত্রাকার ক্লিপ অ্যাক্টিভিটি ডিবাগ করুন"</string>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"অন্যান্য অ্যাকশন শিডিউল করতে এবং অ্যালার্ম সেট করার জন্য এই অ্যাপকে অনুমতি দিন। আপনি ফোন ব্যবহার না করার সময় এই অ্যাপ ব্যবহার করা হতে পারে, যার ফলে আরও ব্যাটারির চার্জ খরচ হতে পারে। অনুমতি দেওয়া না থাকলে, এই অ্যাপ সঠিকভাবে কাজ নাও করতে পারে এবং অ্যালার্মও শিডিউল অনুযায়ী বাজবে না।"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"অন্যান্য অ্যাকশন শিডিউল করতে এবং অ্যালার্ম সেট করার জন্য এই অ্যাপকে অনুমতি দিন। আপনি ট্যাবলেট ব্যবহার না করার সময় এই অ্যাপ ব্যবহার করা হতে পারে, যার ফলে আরও ব্যাটারির চার্জ খরচ হতে পারে। অনুমতি দেওয়া না থাকলে, এই অ্যাপ সঠিকভাবে কাজ নাও করতে পারে এবং অ্যালার্মও শিডিউল অনুযায়ী বাজবে না।"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"অন্যান্য অ্যাকশন শিডিউল করতে এবং অ্যালার্ম সেট করার জন্য এই অ্যাপকে অনুমতি দিন। আপনি ডিভাইস ব্যবহার না করার সময় এই অ্যাপ ব্যবহার করা হতে পারে, যার ফলে আরও ব্যাটারির চার্জ খরচ হতে পারে। অনুমতি দেওয়া না থাকলে, এই অ্যাপ সঠিকভাবে কাজ নাও করতে পারে এবং অ্যালার্মও শিডিউল অনুযায়ী বাজবে না।"</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 46921a4..d3049b1 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -180,7 +180,7 @@
<string name="tts_engine_settings_title" msgid="7849477533103566291">"Postavke za <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
<string name="tts_engine_settings_button" msgid="477155276199968948">"Pokreni postavke programa"</string>
<string name="tts_engine_preference_section_title" msgid="3861562305498624904">"Željeni alat"</string>
- <string name="tts_general_section_title" msgid="8919671529502364567">"Opće postavke"</string>
+ <string name="tts_general_section_title" msgid="8919671529502364567">"Opće"</string>
<string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"Postavite visinu glasa"</string>
<string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"Visinu glasa koji izgovara tekst postavite na podrazumjevanu."</string>
<string-array name="tts_rate_entries">
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Prikaz granica isječka, margina itd."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Prisilno postavi raspored s desna ulijevo"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Prisilno postavljanje rasporeda ekrana s desna ulijevo za sve regije"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Dozvoli zamućenja prozora"</string>
<string name="force_msaa" msgid="4081288296137775550">"Prinudno primijeni 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Omogućava 4x MSAA u OpenGL ES 2.0 aplikacijama"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Otkl. greške na operac. nepravoug. isjecanja"</string>
@@ -509,9 +508,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsjetnici"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dozvoli postavljanje alarma i podsjetnika"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Dozvolite ovoj aplikaciji da postavlja alarme i zakaže druge radnje. Ova aplikacija se može koristiti kada ne koristite telefon, čime se može povećati potrošnja baterije. Ako isključite ovo odobrenje, moguće je da ova aplikacija neće funkcionirati kako je namijenjeno, a njeni alarmi neće funkcionirati prema rasporedu."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Dozvolite ovoj aplikaciji da postavlja alarme i zakaže druge radnje. Ova aplikacija se može koristiti kada ne koristite tablet, čime se može povećati potrošnja baterije. Ako isključite ovo odobrenje, moguće je da ova aplikacija neće funkcionirati kako je namijenjeno, a njeni alarmi neće funkcionirati prema rasporedu."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Dozvolite ovoj aplikaciji da postavlja alarme i zakaže druge radnje. Ova aplikacija se može koristiti kada ne koristite uređaj, čime se može povećati potrošnja baterije. Ako isključite ovo odobrenje, moguće je da ova aplikacija neće funkcionirati kako je namijenjeno, a njeni alarmi neće funkcionirati prema rasporedu."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu koje je ova aplikacija zakazala neće funkcionirati."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključi način rada Ne ometaj"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 557e917..eab1cd2 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Mostra els límits de clips, els marges, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Força direcció dreta-esquerra"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Força direcció de pantalla dreta-esquerra en totes les llengües"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Permet desenfoc. finestra"</string>
<string name="force_msaa" msgid="4081288296137775550">"Força MSAA 4x"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Activa MSAA 4x en aplicacions d\'OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Depura operacions de retall no rectangulars"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes i recordatoris"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permet la configuració d\'alarmes i recordatoris"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes i recordatoris"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Permet que aquesta aplicació configuri alarmes i programi altres accions. Aquesta aplicació es pot utilitzar quan no fas servir el telèfon, que pot consumir més bateria. Si aquest permís està desactivat, pot ser que l\'aplicació no funcioni amb normalitat i que les alarmes no funcionin tal com s\'han programat."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Permet que aquesta aplicació configuri alarmes i programi altres accions. Aquesta aplicació es pot utilitzar quan no fas servir la tauleta, que pot consumir més bateria. Si aquest permís està desactivat, pot ser que l\'aplicació no funcioni amb normalitat i que les alarmes no funcionin tal com s\'han programat."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Permet que aquesta aplicació configuri alarmes i programi altres accions. Aquesta aplicació es pot utilitzar quan no fas servir el dispositiu, que pot consumir més bateria. Si aquest permís està desactivat, pot ser que l\'aplicació no funcioni amb normalitat i que les alarmes no funcionin tal com s\'han programat."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions urgents. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments urgents que ja hagi programat l\'aplicació no funcionaran."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programació, alarma, recordatori, rellotge"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activa"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activa el mode No molestis"</string>
@@ -527,7 +524,7 @@
<string name="time_unit_just_now" msgid="3006134267292728099">"Ara mateix"</string>
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altaveu del telèfon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Aquest telèfon"</string>
- <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Hi ha hagut un problema amb la connexió. Desactiva el dispositiu i torna\'l a activar."</string>
+ <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Hi ha hagut un problema amb la connexió. Apaga el dispositiu i torna\'l a encendre."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositiu d\'àudio amb cable"</string>
<string name="help_label" msgid="3528360748637781274">"Ajuda i suggeriments"</string>
<string name="storage_category" msgid="2287342585424631813">"Emmagatzematge"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 2a3b085..7376d7ee 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"U výstřižku zobrazit ohraničení, okraje atd."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Vynutit rozvržení zprava doleva"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Vynutit ve všech jazycích rozvržení obrazovky zprava doleva"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Povolit rozmazávání oken"</string>
<string name="force_msaa" msgid="4081288296137775550">"Vynutit 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Povolit 4x MSAA v aplikacích OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Ladit operace s neobdélníkovými výstřižky"</string>
@@ -510,9 +509,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Budíky a připomenutí"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Povolit nastavování budíků a připomenutí"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a připomenutí"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Umožní této aplikaci nastavovat budíky a plánovat další akce. Aplikace může být použita, i když telefon nepoužíváte, a tak může docházet k vyšší spotřebě baterie. Když je toto oprávnění vypnuté, aplikace nemusí fungovat normálně a její budíky nebudou fungovat podle plánu."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Umožní této aplikaci nastavovat budíky a plánovat další akce. Aplikace může být použita, i když tablet nepoužíváte, a tak může docházet k vyšší spotřebě baterie. Když je toto oprávnění vypnuté, aplikace nemusí fungovat normálně a její budíky nebudou fungovat podle plánu."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Umožní této aplikaci nastavovat budíky a plánovat další akce. Aplikace může být použita, i když zařízení nepoužíváte, a tak může docházet k vyšší spotřebě baterie. Když je toto oprávnění vypnuté, aplikace nemusí fungovat normálně a její budíky nebudou fungovat podle plánu."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povolte aplikaci nastavovat budíky a plánovat akce závislé na čase. Aplikace poběží na pozadí, což může vést k vyšší spotřebě baterie.\n\nPokud je toto oprávnění vypnuté, stávající budíky a události závislé na čase naplánované touto aplikací nebudou fungovat."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, připomenutí, hodiny"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnout"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapněte funkci Nerušit"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index d7c5d55..1dc2d14 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Vis grænser for klip, margener osv."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Tving læsning mod venstre"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Gennemtving højre mod venstre-layout for alle sprog"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Tillad vinduessløring"</string>
<string name="force_msaa" msgid="4081288296137775550">"Gennemtving 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Aktivér 4x MSAA i apps med OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Fejlret på ikke-rektangulære klippehandlinger"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmer og påmindelser"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Tillad indstilling af alarmer og påmindelser"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmer og påmindelser"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Tillad, at denne app indstiller alarmer og planlægger andre handlinger. Denne app kan blive brugt, når du ikke bruger din telefon, hvilket kan øge batteriforbruget. Hvis denne tilladelse deaktiveres, fungerer denne app muligvis ikke som normalt, og dens alarmer fungerer ikke på de planlagte tider."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Tillad, at denne app indstiller alarmer og planlægger andre handlinger. Denne app kan blive brugt, når du ikke bruger din tablet, hvilket kan øge batteriforbruget. Hvis denne tilladelse deaktiveres, fungerer denne app muligvis ikke som normalt, og dens alarmer fungerer ikke på de planlagte tider."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Tillad, at denne app indstiller alarmer og planlægger andre handlinger. Denne app kan blive brugt, når du ikke bruger din enhed, hvilket kan øge batteriforbruget. Hvis denne tilladelse deaktiveres, fungerer denne app muligvis ikke som normalt, og dens alarmer fungerer ikke på de planlagte tider."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Tillad, at denne app indstiller alarmer og planlægger tidsbestemte handlinger. Appen vil køre i baggrunden, hvor den muligvis bruger mere batteri.\n\nHvis denne tilladelse er deaktiveret, vil eksisterende alarmer og tidsbestemte handlinger, der er planlagt af denne app, ikke fungere."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planlæg, alarm, påmindelse, ur"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivér"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktivér Forstyr ikke"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 492c6de..f092a51 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Zuschnittbegrenzungen, Ränder usw. anzeigen"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Linksläufiges Layout erzwingen"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Für alle Sprachen wird das linksläufige Bildschirmlayout verwendet"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Weichzeichnen auf Fensterebene zulassen"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA erzwingen"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"In OpenGL ES 2.0-Apps 4x MSAA aktivieren"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Nichtrechteckige Zuschnitte debuggen"</string>
@@ -508,9 +507,8 @@
<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>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Dieser App erlauben, Wecker zu stellen und andere Aktionen zu planen. So kann die App gestartet und ausgeführt werden, auch wenn du das Gerät nicht verwendest. Dies kann den Akkuverbrauch erhöhen. Wenn diese Berechtigung deaktiviert ist, funktionieren die App und die zugehörigen Wecker möglicherweise nicht wie erwartet."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Dieser App erlauben, Wecker zu stellen und andere Aktionen zu planen. So kann die App gestartet und ausgeführt werden, auch wenn du das Gerät nicht verwendest. Dies kann den Akkuverbrauch erhöhen. Wenn diese Berechtigung deaktiviert ist, funktionieren die App und die zugehörigen Wecker möglicherweise nicht wie erwartet."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Dieser App erlauben, Wecker zu stellen und andere Aktionen zu planen. So kann die App gestartet und ausgeführt werden, auch wenn du das Gerät nicht verwendest. Dies kann den Akkuverbrauch erhöhen. Wenn diese Berechtigung deaktiviert ist, funktionieren die App und die zugehörigen Wecker möglicherweise nicht wie erwartet."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 19ccac6..5d4301c 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Εμφάνιση ορίων κλιπ, περιθωρίων, κλπ."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Επιβολή κατ. διάταξης RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Επιβολή διάταξης οθόν. RTL για όλες τις τοπ. ρυθμ."</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Θάμπωμα σε επίπεδο παραθ."</string>
<string name="force_msaa" msgid="4081288296137775550">"Αναγκαστικά 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Ενεργοποίηση 4x MSAA σε εφαρμογές OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Εντοπισμός σφαλμάτων σε λειτουργίες μη ορθογώνιας περιοχής"</string>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"Να επιτρέπεται σε αυτήν την εφαρμογή να ορίζει ξυπνητήρια και να προγραμματίζει άλλες ενέργειες. Αυτή η εφαρμογή ενδέχεται να χρησιμοποιείται όταν δεν χρησιμοποιείτε το τηλέφωνό σας, κάτι που μπορεί να οδηγήσει σε μεγαλύτερη κατανάλωση μπαταρίας. Εάν αυτή η άδεια είναι απενεργοποιημένη, η εφαρμογή ενδέχεται να μην λειτουργεί φυσιολογικά και τα ξυπνητήρια της δεν θα λειτουργούν σύμφωνα με τον προγραμματισμό τους."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Να επιτρέπεται σε αυτήν την εφαρμογή να ορίζει ξυπνητήρια και να προγραμματίζει άλλες ενέργειες. Αυτή η εφαρμογή ενδέχεται να χρησιμοποιείται όταν δεν χρησιμοποιείτε το tablet, κάτι που μπορεί να οδηγήσει σε μεγαλύτερη κατανάλωση μπαταρίας. Εάν αυτή η άδεια είναι απενεργοποιημένη, η εφαρμογή ενδέχεται να μην λειτουργεί φυσιολογικά και τα ξυπνητήρια της δεν θα λειτουργούν σύμφωνα με τον προγραμματισμό τους."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Να επιτρέπεται σε αυτήν την εφαρμογή να ορίζει ξυπνητήρια και να προγραμματίζει άλλες ενέργειες. Αυτή η εφαρμογή ενδέχεται να χρησιμοποιείται όταν δεν χρησιμοποιείτε τη συσκευή σας, κάτι που μπορεί να οδηγήσει σε μεγαλύτερη κατανάλωση μπαταρίας. Εάν αυτή η άδεια είναι απενεργοποιημένη, η εφαρμογή ενδέχεται να μην λειτουργεί φυσιολογικά και τα ξυπνητήρια της δεν θα λειτουργούν σύμφωνα με τον προγραμματισμό τους."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 2caa3f7..02317ea 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -507,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your phone, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your tablet, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your device, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index f307e16..f15db49 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -507,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your phone, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your tablet, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your device, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 2caa3f7..02317ea 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -507,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your phone, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your tablet, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your device, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 2caa3f7..02317ea 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -507,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your phone, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your tablet, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your device, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 2d2b036..ce5a6bc 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -507,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your phone, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your tablet, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Allow this app to set alarms and schedule other actions. This app may be used when you’re not using your device, which may use more battery. If this permission is off, this app may not function normally, and its alarms won’t work as scheduled."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 3ee5dab..d050ff8 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Mostrar límites de recortes, márgenes, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forzar diseño der. a izq."</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Forzar diseño de pantalla de derecha a izquierda para todos los idiomas"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Permitir difuminación en ventana"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forzar MSAA 4x"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Activar MSAA 4x en aplicaciones OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operaciones de recorte no rectangulares"</string>
@@ -508,9 +507,8 @@
<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>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Permite que esta app configure alarmas y programe otras acciones. Esta app podría ejecutarse cuando no estás usando el teléfono, lo que podría consumir más batería. Si este permiso está desactivado, es posible que la app no funcione con normalidad, y las alarmas no seguirán su programación."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Permite que esta app configure alarmas y programe otras acciones. Esta app podría ejecutarse cuando no estás usando la tablet, lo que podría consumir más batería. Si este permiso está desactivado, es posible que la app no funcione con normalidad, y las alarmas no seguirán su programación."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Permite que esta app configure alarmas y programe otras acciones. Esta app se puede usar cuando no estás usando el dispositivo, lo que podría consumir más batería. Si este permiso está desactivado, es posible que la app no funcione con normalidad, y las alarmas no seguirán su programación."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index d63ea7b..540a472 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Muestra límites de vídeo, márgenes, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forzar dirección de diseño RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Fuerza la dirección RTL para todos los idiomas"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Difuminar ventanas"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forzar MSAA 4x"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Habilita MSAA 4x en aplicaciones de OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operaciones de recorte no rectangulares"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmas y recordatorios"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir la programación de alarmas y recordatorios"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas y recordatorios"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Permite que esta aplicación programe alarmas y otras acciones. Puede que la aplicación siga funcionando aunque no estés usando el teléfono, lo que puede consumir más batería. Si este permiso está desactivado, es posible que esta aplicación no funcione correctamente y que las alarmas no se activen según estén programadas."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Permite que esta aplicación programe alarmas y otras acciones. Puede que la aplicación siga funcionando aunque no estés usando el tablet, lo que puede consumir más batería. Si este permiso está desactivado, es posible que esta aplicación no funcione correctamente y que las alarmas no se activen según estén programadas."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Permite que esta aplicación programe alarmas y otras acciones. Puede que la aplicación siga funcionando aunque no estés usando el dispositivo, lo que puede consumir más batería. Si este permiso está desactivado, es posible que esta aplicación no funcione correctamente y que las alarmas no se activen según estén programadas."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta aplicación programe alarmas y otras acciones de carácter temporal. Este permite sirve para que la aplicación siga activa en segundo plano, lo que puede usar más batería.\n\nSi este permiso está desactivados, no funcionarán las alarmas ni los eventos con carácter temporal programados por esta aplicación."</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 el modo No molestar"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index ed698e2..f740cc5 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Kuva klipi piirid, veerised jms"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Jõusta paremalt vasakule paigutus"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Jõusta kõikides lokaatides paremalt vasakule ekraanipaigutus"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Luba akna tasemel hägust."</string>
<string name="force_msaa" msgid="4081288296137775550">"Jõusta 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Luba 4x MSAA OpenGL ES 2.0 rakendustes"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Silu mittetäisnurksed kärpimistoimingud"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmid ja meeldetuletused"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Luba alarmide ja meeldetuletuste määramine"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmid ja meeldetuletused"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Lubage sellel rakendusel määrata alarme ja ajastada muid toiminguid. Seda rakendust võidakse kasutada ajal, kui te oma telefoni ei kasuta, ja see võib akukasutust suurendada. Kui see luba on välja lülitatud, ei pruugi see rakendus korralikult toimida ja selle alarmid ei tööta ajakava järgi."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Lubage sellel rakendusel määrata alarme ja ajastada muid toiminguid. Seda rakendust võidakse kasutada ajal, kui te oma tahvelarvutit ei kasuta, ja see võib akukasutust suurendada. Kui see luba on välja lülitatud, ei pruugi see rakendus korralikult toimida ja selle alarmid ei tööta ajakava järgi."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Lubage sellel rakendusel määrata alarme ja ajastada muid toiminguid. Seda rakendust võidakse kasutada ajal, kui te oma seadet ei kasuta, ja see võib akukasutust suurendada. Kui see luba on välja lülitatud, ei pruugi see rakendus korralikult toimida ja selle alarmid ei tööta ajakava järgi."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lubage sellel rakendusel määrata äratusi ja ajastada kiire tähtajaga toiminguid. See võimaldab rakendusel töötada taustal, mistõttu võib akukasutus olla suurem.\n\nKui see luba on välja lülitatud, siis olemasolevad äratused ja selle rakenduse ajastatud ajapõhised sündmused ei tööta."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ajakava, äratus, meeldetuletus, kell"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Lülita sisse"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Valiku Mitte segada sisselülitamine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index ebc62f2..06e1abd 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Erakutsi kliparen mugak, marjinak, etab."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Behartu eskuin-ezker norabidea"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Behartu pantaila-diseinuaren norabidea eskuin-ezker izatera lurraldeko ezarpen guztiekin"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Gaitu leiho-lausotzeak"</string>
<string name="force_msaa" msgid="4081288296137775550">"Behartu 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Gaitu 4x MSAA, OpenGL ES 2.0 aplikazioetan"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Araztu angeluzuzenak ez diren klip-eragiketak"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmak eta abisuak"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Eman alarmak eta abisuak ezartzeko baimena"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmak eta abisuak"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Eman alarmak ezartzeko eta beste ekintza batzuk programatzeko baimena aplikazioari. Telefonoa erabili ez arren, agian aplikazioak martxan jarraituko du, eta bateria gehiago erabiliko. Baimena desaktibatuta badago, baliteke aplikazioak zuzen ez funtzionatzea eta programatutako alarmek ez jotzea."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Eman alarmak ezartzeko eta beste ekintza batzuk programatzeko baimena aplikazioari. Tableta erabili ez arren, agian aplikazioak martxan jarraituko du, eta bateria gehiago erabiliko. Baimena desaktibatuta badago, baliteke aplikazioak zuzen ez funtzionatzea eta programatutako alarmek ez jotzea."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Eman alarmak ezartzeko eta beste ekintza batzuk programatzeko baimena aplikazioari. Gailua erabili ez arren, agian aplikazioak martxan jarraituko du, eta bateria gehiago erabiliko. Baimena desaktibatuta badago, baliteke aplikazioak zuzen ez funtzionatzea eta programatutako alarmek ez jotzea."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nEz baduzu ematen baimen hori, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programazioa, alarma, abisua, erlojua"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktibatu"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu ez molestatzeko modua"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 00a18d3..92e624d 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"نمایش مرزها، حاشیهها و ویژگیهای دیگر کلیپ."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"اجباری کردن چیدمان راستچین"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"اجباری کردن چیدمان راستچین صفحه برای همه زبانها"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"محو کردن در سطح پنجره"</string>
<string name="force_msaa" msgid="4081288296137775550">"اجبار 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"فعال کردن 4X MSAA در برنامههای OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"اشکالزدایی عملکردهای کلیپ غیرمربعی"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"به این برنامه اجازه داده میشود که زنگ ساعت تنظیم کند و کنشهای دیگر را زمانبندی کند. ممکن است از این برنامه زمانی استفاده شود که از تلفنتان استفاده نمیکنید؛ این موضوع شاید موجب مصرف شارژ بیشتری شود. اگر این اجازه خاموش باشد، ممکن است این برنامه بهدرستی کار نکند، و زنگهای ساعت آن طبق زمانبندی کار نخواهد کرد."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"به این برنامه اجازه داده میشود که زنگ ساعت تنظیم کند و کنشهای دیگر را زمانبندی کند. ممکن است از این برنامه زمانی استفاده شود که از رایانه لوحیتان استفاده نمیکنید؛ این موضوع شاید موجب مصرف شارژ بیشتری شود. اگر این اجازه خاموش باشد، ممکن است این برنامه بهدرستی کار نکند، و زنگهای ساعت آن طبق زمانبندی کار نخواهد کرد."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"به این برنامه اجازه داده میشود که زنگ ساعت تنظیم کند و کنشهای دیگر را زمانبندی کند. ممکن است از این برنامه زمانی استفاده شود که از دستگاهتان استفاده نمیکنید؛ این موضوع شاید موجب مصرف شارژ بیشتری شود. اگر این اجازه خاموش باشد، ممکن است این برنامه بهدرستی کار نکند، و زنگهای ساعت آن طبق زمانبندی کار نخواهد کرد."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index b3187a5..11bcb3a 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Näytä leikkeiden rajat, marginaalit jne."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Pakota RTL-ulkoasun suunta"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Pakota kaikkien kielten näytön ulkoasun suunnaksi RTL"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Salli ikkunoiden sumennus"</string>
<string name="force_msaa" msgid="4081288296137775550">"Pakota 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Ota käyttöön 4x MSAA OpenGL ES 2.0 -sovelluksissa"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Korjaa ei-suorakulmaisten leiketoimintojen virheet"</string>
@@ -508,9 +507,8 @@
<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>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Salli sovelluksen lisätä herätyksiä ja ajoittaa muita toimintoja. Sovellus voi olla käytössä, vaikka et käyttäisi puhelintasi, mikä voi kuluttaa enemmän virtaa. Ilman tätä lupaa sovellus ei välttämättä toimi normaalisti, eivätkä sen herätykset toimi aikataulun mukaisesti."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Salli sovelluksen lisätä herätyksiä ja ajoittaa muita toimintoja. Sovellus voi olla käytössä, vaikka et käyttäisi tablettiasi, mikä voi kuluttaa enemmän virtaa. Ilman tätä lupaa sovellus ei välttämättä toimi normaalisti, eivätkä sen herätykset toimi aikataulun mukaisesti."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Salli sovelluksen lisätä herätyksiä ja ajoittaa muita toimintoja. Sovellus voi olla käytössä, vaikka et käyttäisi laitettasi, mikä voi kuluttaa enemmän virtaa. Ilman tätä lupaa sovellus ei välttämättä toimi normaalisti, eivätkä sen herätykset toimi aikataulun mukaisesti."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
@@ -579,7 +577,7 @@
<string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Laitteesi on käynnistettävä uudelleen, jotta muutos tulee voimaan. Käynnistä uudelleen nyt tai peru."</string>
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Langalliset kuulokkeet"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Päällä"</string>
- <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Poissa päältä"</string>
+ <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Ei käytössä"</string>
<string name="carrier_network_change_mode" msgid="4257621815706644026">"Operaattorin verkko muuttuu"</string>
<string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
<string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index b785165..a622385 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Afficher les limites, les marges de clip, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forcer droite à gauche"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Forcer l\'orientation droite à gauche (toutes langues)"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Autoriser le flou au niveau des fenêtres"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forcer MSAA 4x"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Activer MSAA 4x dans les applications OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Déboguer opérations de découpage non rectangulaire"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes et rappels"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autoriser la création d\'alarmes et de rappels"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes et rappels"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Autorisez cette application à créer des alarmes et à programmer d\'autres actions. Cette application pourrait continuer de fonctionner lorsque vous n\'utilisez pas votre téléphone, ce qui pourrait solliciter davantage la pile. Si l\'autorisation est désactivée, l\'application pourrait ne pas fonctionner normalement et ses alarmes ne se déclencheront pas aux heures prévues."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Autorisez cette application à créer des alarmes et à programmer d\'autres actions. Cette application pourrait continuer de fonctionner lorsque vous n\'utilisez pas votre tablette, ce qui pourrait solliciter davantage la pile. Si l\'autorisation est désactivée, l\'application pourrait ne pas fonctionner normalement et ses alarmes ne se déclencheront pas aux heures prévues."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Autorisez cette application à créer des alarmes et à programmer d\'autres actions. Cette application pourrait continuer de fonctionner lorsque vous n\'utilisez pas votre appareil, ce qui pourrait solliciter davantage la pile. Si l\'autorisation est désactivée, l\'application pourrait ne pas fonctionner normalement et ses alarmes ne se déclencheront pas aux heures prévues."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Autorisez cette application à créer des alarmes et à programmer des actions urgentes. Cela permet à l’application de s\'exécuter en arrière-plan, ce qui peut nécessiter plus de pile.\n\nSi cette autorisation est désactivée, les alarmes existantes et les événements en temps réel programmés par cette application ne fonctionneront pas."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"horaire, alarme, rappel, horloge"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activer"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activer le mode Ne pas déranger"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 52c4ec2..c4797fc 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Afficher les limites de coupe, les marges, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forcer écriture droite à gauche"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Forcer l\'orientation du texte de droite à gauche pour toutes les langues"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Autor. floutage fenêtre"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forcer MSAA 4x"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Activer MSAA 4x dans les applications OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Déboguer découpage non rectangulaire"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes et rappels"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autoriser à définir des alarmes et des rappels"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes et rappels"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Autoriser cette appli à définir des alarmes et à programmer d\'autres actions. Cette appli peut être utilisée quand vous n\'utilisez pas votre téléphone, ce qui peut consommer davantage de batterie. Si cette autorisation est désactivée, l\'appli peut ne pas fonctionner correctement, et les alarmes définies ne se déclencheront pas comme prévu."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Autoriser cette appli à définir des alarmes et à programmer d\'autres actions. Cette appli peut être utilisée lorsque vous n\'utilisez pas votre tablette, ce qui peut consommer davantage de batterie. Si cette autorisation est désactivée, l\'appli peut ne pas fonctionner correctement, et les alarmes définies ne se déclencheront pas comme prévu."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Autoriser cette appli à définir des alarmes et à programmer d\'autres actions. Cette appli peut être utilisée quand vous n\'utilisez pas votre appareil, ce qui peut consommer davantage de batterie. Si cette autorisation est désactivée, l\'appli peut ne pas fonctionner correctement, et les alarmes définies ne se déclencheront pas comme prévu."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Autorisez cette appli à définir des alarmes et à planifier des actions soumises à un délai. Cela lui permet de s\'exécuter en arrière-plan, ce qui peut consommer plus de batterie.\n\nSi cette autorisation est désactivée, les alarmes existantes et les événements basés sur l\'heure planifiés par cette appli ne fonctionneront pas."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"définir, alarme, rappel, horloge"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activer"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activer le mode Ne pas déranger"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 037a9a9..0d009de 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -211,7 +211,7 @@
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuración de erros ao conectarse á wifi"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Produciuse un erro"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Depuración sen fíos"</string>
- <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar os dispositivos dispoñibles, activa a depuración sen fíos"</string>
+ <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar os dispositivos dispoñibles, activa a depuración sen fíos."</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Vincular o dispositivo cun código QR"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Vincula dispositivos novos mediante un escáner de códigos QR"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"Vincular o dispositivo co código de vinculación"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Mostra os límites dos clips, as marxes etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forzar dirección do deseño RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Forza a dirección de pantalla a RTL (dereita a esquerda) para todas as configuración rexionais"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Permitir desenfoque ventá"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forzar MSAA 4x"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Activa MSAA 4x en aplicacións OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar accións recorte non rectangulares"</string>
@@ -508,9 +507,8 @@
<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>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Permite que esta aplicación defina alarmas e planifique outras accións. Pode usarse cando non utilices o teléfono, o cal consome máis batería. Se este permiso está desactivado, é posible que a aplicación non funcione con normalidade e que as alarmas non se activen segundo o planificado."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Permite que esta aplicación defina alarmas e planifique outras accións. Pode usarse cando non utilices a tableta, o cal consome máis batería. Se este permiso está desactivado, é posible que a aplicación non funcione con normalidade e que as alarmas non se activen segundo o planificado."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Permite que esta aplicación defina alarmas e planifique outras accións. Pode usarse cando non utilices o dispositivo, o cal consome máis batería. Se este permiso está desactivado, é posible que a aplicación non funcione con normalidade e que as alarmas non se activen segundo o planificado."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 6aaa23e..b8d8f35 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"ક્લિપ બાઉન્ડ, હાંસિયાં વગેરે બતાવો."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL લેઆઉટ દિશા નિર્દેશની ફરજ પાડો"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"તમામ લૉકેલ માટે સ્ક્રીન લેઆઉટ દિશા નિર્દેશને RTLની ફરજ પાડો"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"વિન્ડો-લેવલને ઝાંખું કરવાની સુવિધા ચાલુ કરો"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAAને ફરજ પાડો"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ઍપમાં 4x MSAA ચાલુ કરો"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"બિન-લંબચોરસ ક્લિપ કામગીરી ડીબગ કરો"</string>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"આ ઍપને અલાર્મ સેટ કરવા અને અન્ય ક્રિયાઓ શેડ્યૂલ કરવા માટે મંજૂરી આપો. જ્યારે તમે તમારા ફોનનો ઉપયોગ ન કરતા હો, ત્યારે આ ઍપનો ઉપયોગ થઈ શકે છે, જેમાં વધારે બૅટરી વપરાઈ શકે છે. જો આ પરવાનગી બંધ હોય, તો આ ઍપ સામાન્ય રીતે કાર્ય ન પણ કરી શકે અને તેના અલાર્મ શેડ્યૂલ કર્યા મુજબ કાર્ય ન પણ કરે."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"આ ઍપને અલાર્મ સેટ કરવા અને અન્ય ક્રિયાઓ શેડ્યૂલ કરવા માટે મંજૂરી આપો. જ્યારે તમે તમારા ટૅબ્લેટનો ઉપયોગ ન કરતા હો, ત્યારે આ ઍપનો ઉપયોગ થઈ શકે છે, જેમાં વધારે બૅટરી વપરાઈ શકે છે. જો આ પરવાનગી બંધ હોય, તો આ ઍપ સામાન્ય રીતે કાર્ય ન પણ કરી શકે અને તેના અલાર્મ શેડ્યૂલ કર્યા મુજબ કાર્ય ન પણ કરે."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"આ ઍપને અલાર્મ સેટ કરવા અને અન્ય ક્રિયાઓ શેડ્યૂલ કરવા માટે મંજૂરી આપો. જ્યારે તમે તમારા ડિવાઇસનો ઉપયોગ ન કરતા હો, ત્યારે આ ઍપનો ઉપયોગ થઈ શકે છે, જેમાં વધારે બૅટરી વપરાઈ શકે છે. જો આ પરવાનગી બંધ હોય, તો આ ઍપ સામાન્ય રીતે કાર્ય ન પણ કરી શકે અને તેના અલાર્મ શેડ્યૂલ કર્યા મુજબ કાર્ય ન પણ કરે."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index b6ac959..8abbfcf 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -94,7 +94,7 @@
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"सिम ऐक्सेस"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"एचडी ऑडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"एचडी ऑडियो"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"सुनने में मदद करने वाले डिवाइस"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"कान की मशीन"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"सुनने में मदद करने वाले डिवाइस से कनेक्ट है"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"मीडिया ऑडियो से कनेक्ट किया गया"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"फ़ोन ऑडियो से कनेक्ट किया गया"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"क्लिप सीमाएं, मार्जिन वगैरह दिखाएं."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"लेआउट की दिशा दाएं से बाएं करें"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"सभी भाषाओं के लिए स्क्रीन लेआउट की दिशा दाएं से बाएं रखें"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"विंडो को धुंधला करने की सुविधा चालू करें"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA को हर हाल में चालू करें"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ऐप में 4x MSAA को चालू करें"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"उन क्लिप ऑपरेशन को डीबग करें, जो आयताकार नहीं हैं"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"इस ऐप्लिकेशन को अनुमति दें कि यह अलार्म सेट कर सके और दूसरी कार्रवाइयां शेड्यूल कर सके. इस ऐप्लिकेशन का इस्तेमाल तब भी किया जा सकता है, जब आप अपने फ़ोन का इस्तेमाल नहीं कर रहे होते. इससे बैटरी ज़्यादा खर्च हो सकती है. अगर आप यह अनुमति नहीं देते हैं, तो हो सकता है कि यह ऐप्लिकेशन ठीक तरह से काम न करे. साथ ही, इसमें शेड्यूल किए गए अलार्म भी नहीं बजेंगे."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"इस ऐप्लिकेशन को अनुमति दें कि यह अलार्म सेट कर सके और दूसरी कार्रवाइयां शेड्यूल कर सके. इस ऐप्लिकेशन का इस्तेमाल तब भी किया जा सकता है, जब आप अपने टैबलेट का इस्तेमाल नहीं कर रहे होते. इससे बैटरी ज़्यादा खर्च हो सकती है. अगर आप यह अनुमति नहीं देते हैं, तो हो सकता है कि यह ऐप्लिकेशन ठीक तरह से काम न करे. साथ ही, इसमें शेड्यूल किए गए अलार्म भी नहीं बजेंगे."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"इस ऐप्लिकेशन को अनुमति दें कि यह अलार्म सेट कर सके और दूसरी कार्रवाइयां शेड्यूल कर सके. इस ऐप्लिकेशन का इस्तेमाल तब भी किया जा सकता है, जब आप अपने डिवाइस का इस्तेमाल नहीं कर रहे होते. इससे बैटरी ज़्यादा खर्च हो सकती है. अगर आप यह अनुमति नहीं देते हैं, तो हो सकता है कि यह ऐप्लिकेशन ठीक तरह से काम न करे. साथ ही, इसमें शेड्यूल किए गए अलार्म भी नहीं बजेंगे."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index ac074b0..217ff15 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Prikazuju se obrubi, margine itd. isječaka."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Nametni zdesna ulijevo"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Nametni smjer zdesna ulijevo za sve zemlje/jezike"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Dopusti zamućenja na razini prozora"</string>
<string name="force_msaa" msgid="4081288296137775550">"Nametni 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Omogući 4x MSAA u aplikacijama OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Otkloni pogreške operacija nepravokutnog isječka"</string>
@@ -509,9 +508,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsjetnici"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dopusti postavljanje alarma i podsjetnika"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Aplikaciji omogućuje da postavlja alarme i zakazuje druge radnje. Aplikacija se može koristiti kad ne upotrebljavate telefon, što može dodatno trošiti bateriju. Ako je to dopuštenje isključeno, aplikacija možda neće funkcionirati kako treba i njezini se alarmi neće oglašavati prema rasporedu."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Aplikaciji omogućuje da postavlja alarme i zakazuje druge radnje. Aplikacija se može koristiti kad ne upotrebljavate tablet, što može dodatno trošiti bateriju. Ako je to dopuštenje isključeno, aplikacija možda neće funkcionirati kako treba i njezini se alarmi neće oglašavati prema rasporedu."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Aplikaciji omogućuje da postavlja alarme i zakazuje druge radnje. Aplikacija se može koristiti kad ne upotrebljavate uređaj, što može dodatno trošiti bateriju. Ako je to dopuštenje isključeno, aplikacija možda neće funkcionirati kako treba i njezini se alarmi neće oglašavati prema rasporedu."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Aplikaciji omogućuje da postavlja alarme i zakazuje vremenski osjetljive radnje. To aplikaciji omogućuje da se izvodi u pozadini, pa je moguće dodatno trošenje baterije.\n\nAko je to dopuštenje isključeno, postojeći alarmi i događaji temeljeni na vremenu koji su zakazani putem ove aplikacije neće funkcionirati."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključite opciju Ne uznemiravaj."</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 3377c45..e75b0dd 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Kliphatárok, margók stb. megjelenítése."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Elrendezés jobbról balra"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Elrendezés jobbról balra minden nyelvnél"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Ablakszintű homályosítás"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA kényszerítése"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"A 4x MSAA engedélyezése az OpenGL ES 2.0-nál"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Nem négyzetes kivágási műveletek hibakeresése"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Ébresztések és emlékeztetők"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Beállíthat ébresztéseket és emlékeztetőket"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ébresztések és emlékeztetők"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Engedélyezheti ennek az alkalmazásnak, hogy ébresztéseket állítson be és további műveleteket ütemezzen. Ez az alkalmazás használatban lehet, amikor nem használja a telefonját, ami jobban igénybe veheti az akkumulátort. Ha ez az engedély ki van kapcsolva, előfordulhat, hogy az alkalmazás nem működik megfelelően, és az ébresztések nem működnek az ütemezésnek megfelelően."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Engedélyezheti ennek az alkalmazásnak, hogy ébresztéseket állítson be és további műveleteket ütemezzen. Ez az alkalmazás használatban lehet, amikor nem használja a táblagépét, ami jobban igénybe veheti az akkumulátort. Ha ez az engedély ki van kapcsolva, előfordulhat, hogy az alkalmazás nem működik megfelelően, és az ébresztések nem működnek az ütemezésnek megfelelően."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Engedélyezheti ennek az alkalmazásnak, hogy ébresztéseket állítson be és további műveleteket ütemezzen. Ez az alkalmazás használatban lehet, amikor nem használja az eszközét, ami jobban igénybe veheti az akkumulátort. Ha ez az engedély ki van kapcsolva, előfordulhat, hogy az alkalmazás nem működik megfelelően, és az ébresztések nem működnek az ütemezésnek megfelelően."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lehetővé teszi ennek az alkalmazásnak, hogy ébresztéseket állítson be és időérzékeny feladatokat ütemezzen. Ezzel engedélyezi az alkalmazásnak, hogy a háttérben fusson, ami megnövekedett akkumulátorhasználattal járhat.\n\nHa ez az engedély ki van kapcsolva, az alkalmazás által beállított ébresztések és ütemezett időérzékeny események nem fognak működni."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ütemezés, ébresztés, emlékeztető, óra"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Bekapcsolás"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"A Ne zavarjanak mód bekapcsolása"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 5f6c1a2..44b322d 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -212,9 +212,9 @@
<string name="adb_wireless_error" msgid="721958772149779856">"Սխալ"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Անլար վրիպազերծում"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Հասանելի սարքերը տեսնելու և օգտագործելու համար միացրեք անլար վրիպազերծումը"</string>
- <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Զուգակցեք սարքը՝ օգտագործելով QR կոդը"</string>
+ <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Զուգակցել սարքը QR կոդով"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Զուգակցեք նոր սարքեր՝ օգտագործելով QR կոդերի սկաները"</string>
- <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Զուգակցեք սարքը՝ օգտագործելով զուգակցման կոդը"</string>
+ <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Զուգակցել սարքը զուգակցման կոդով"</string>
<string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Զուգակցեք նոր սարքեր՝ օգտագործելով վեցանիշ կոդը"</string>
<string name="adb_paired_devices_title" msgid="5268997341526217362">"Զուգակցված սարքեր"</string>
<string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Միացված է"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Ցույց տալ կտրվածքի սահմանները, լուսանցքները և այլն"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Ուղղությունը դարձնել RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Բոլոր լեզուների համար էկրանի տեքստի ուղղությունը դարձնել աջից ձախ"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Շաղում պատուհանի մակարդակում"</string>
<string name="force_msaa" msgid="4081288296137775550">"Ստիպել 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Միացնել 4x MSAA-ը OpenGL ES 2.0 հավելվածներում"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Վրիպազերծել ոչ ուղղանկյուն կտրումների գործողությունները"</string>
@@ -506,11 +505,9 @@
<string name="cancel" msgid="5665114069455378395">"Չեղարկել"</string>
<string name="okay" msgid="949938843324579502">"Եղավ"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Զարթուցիչներ և հիշեցումներ"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Թույլատրել զարթուցիչների/հիշեցումների կարգավորումը"</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" product="default" msgid="1122213569699233612">"Թույլ տվեք այս հավելվածին կարգավորել զարթուցիչներ և պլանավորել այլ գործողություններ։ Այս հավելվածը կարող է օգտագործվել այն ժամանակ, երբ դուք չեք օգտվում ձեր հեռախոսից, ինչը կարող է արագացնել մարտկոցի լիցքի սպառումը։ Եթե այս թույլտվությունն անջատված է, այս գործառույթը կարող է պատշաճ չաշխատել, իսկ զարթուցիչները պլանավորված ժամերին չեն աշխատի։"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Թույլ տվեք այս հավելվածին կարգավորել զարթուցիչներ և պլանավորել այլ գործողություններ։ Այս հավելվածը կարող է օգտագործվել այն ժամանակ, երբ դուք չեք օգտվում ձեր պլանշետից, ինչը կարող է արագացնել մարտկոցի լիցքի սպառումը։ Եթե այս թույլտվությունն անջատված է, այս գործառույթը կարող է պատշաճ չաշխատել, իսկ զարթուցիչները պլանավորված ժամերին չեն աշխատի։"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Թույլ տվեք այս հավելվածին կարգավորել զարթուցիչներ և պլանավորել այլ գործողություններ։ Այս հավելվածը կարող է օգտագործվել այն ժամանակ, երբ դուք չեք օգտվում ձեր սարքից, ինչը կարող է արագացնել մարտկոցի լիցքի սպառումը։ Եթե այս թույլտվությունն անջատված է, այս գործառույթը կարող է պատշաճ չաշխատել, իսկ զարթուցիչները պլանավորված ժամերին չեն աշխատի։"</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 9f7b1f0..4bb4724 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Tampilkan batas klip, margin, dll."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Paksa arah tata letak RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Paksa arah tata letak layar RTL untuk semua lokal"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Izinkan buram level jendela"</string>
<string name="force_msaa" msgid="4081288296137775550">"Paksa 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Aktifkan 4x MSAA dalam aplikasi OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Debug operasi klip non-kotak"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarm dan pengingat"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Izinkan menyetel alarm dan pengingat"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm & pengingat"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Izinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan lainnya. Aplikasi ini dapat digunakan saat Anda tidak menggunakan ponsel, sehingga mungkin memerlukan daya baterai lebih besar. Jika izin ini dinonaktifkan, aplikasi mungkin tidak berfungsi normal dan alarmnya tidak bekerja sesuai yang dijadwalkan."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Izinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan lainnya. Aplikasi ini dapat digunakan saat Anda tidak menggunakan tablet, sehingga mungkin memerlukan daya baterai lebih besar. Jika izin ini dinonaktifkan, aplikasi mungkin tidak berfungsi normal dan alarmnya tidak bekerja sesuai yang dijadwalkan."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Izinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan lainnya. Aplikasi ini dapat digunakan saat Anda tidak menggunakan perangkat, sehingga mungkin memerlukan daya baterai lebih besar. Jika izin ini dinonaktifkan, aplikasi mungkin tidak berfungsi normal dan alarmnya tidak bekerja sesuai yang dijadwalkan."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Izinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan berjangka waktu. Hal ini memungkinkan aplikasi berjalan di latar belakang, sehingga mungkin menggunakan lebih banyak daya baterai.\n\nJika izin ini dinonaktifkan, alarm dan acara berjangka waktu yang dijadwalkan oleh aplikasi ini tidak akan berfungsi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadwal, alarm, pengingat, jam"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktifkan"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktifkan mode Jangan Ganggu"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index c972a99..b224330 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Sýna skurðlínur, spássíur o.s.frv."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Þvinga umbrot frá hægri til vinstri"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Þvinga umbrot skjás frá hægri til vinstri fyrir alla tungumálskóða"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Leyfa að gera glugga ósk."</string>
<string name="force_msaa" msgid="4081288296137775550">"Þvinga 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Virkja 4x MSAA í OpenGL ES 2.0 forritum"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Villuleita klippt svæði sem ekki eru rétthyrnd"</string>
@@ -508,9 +507,8 @@
<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>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Leyfa þessu forriti að stilla vekjara og tímasetja aðrar aðgerðir. Mögulegt er að þetta forrit verði notað þegar þú ert ekki að nota símann og því gæti rafhlaðan tæmst hraðar. Ef slökkt er á þessari heimild er óvíst að forritið starfi sem skyldi og vekjarar munu ekki fylgja áætlun."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Leyfa þessu forriti að stilla vekjara og tímasetja aðrar aðgerðir. Mögulegt er að þetta forrit verði notað þegar þú ert ekki að nota spjaldtölvuna og því gæti rafhlaðan tæmst hraðar. Ef slökkt er á þessari heimild er óvíst að forritið starfi sem skyldi og vekjarar munu ekki fylgja áætlun."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Leyfa þessu forriti að stilla vekjara og tímasetja aðrar aðgerðir. Mögulegt er að þetta forrit verði notað þegar þú ert ekki að nota tækið og því gæti rafhlaðan tæmst hraðar. Ef slökkt er á þessari heimild er óvíst að forritið starfi sem skyldi og vekjarar munu ekki fylgja áætlun."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 17b184a..1d2295c 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -211,7 +211,7 @@
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modalità debug in caso di connessione Wi-Fi"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Errore"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Debug wireless"</string>
- <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Per trovare e utilizzare i dispositivi disponibili, attiva il debug wireless"</string>
+ <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Per trovare e utilizzare i dispositivi disponibili, attiva il debug wireless."</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Accoppia dispositivo con codice QR"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Accoppia i nuovi dispositivi utilizzando lo scanner di codici QR"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"Accoppia dispositivo con codice di accoppiamento"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Mostra limiti, margini dei clip e così via"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forza direzione layout RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Direzione layout schermo RTL per tutte le lingue"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Consenti sfocature finestre"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forza MSAA 4x"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Attiva MSAA 4x in applicazioni OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Debug operazioni ritaglio non rettangolare"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Sveglie e promemoria"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Consenti l\'impostazione di sveglie e promemoria"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Sveglie e promemoria"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Consenti a questa app di impostare sveglie e programmare altre azioni. L\'app potrebbe essere in uso quando non utilizzi il telefono, comportando un consumo maggiore della batteria. Se questa autorizzazione è disattivata, l\'app potrebbe non funzionare normalmente e le relative sveglie potrebbero non avviarsi come programmato."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Consenti a questa app di impostare sveglie e programmare altre azioni. Utilizzare quest\'app quando non stai usando il tuo tablet potrebbe consumare più batteria. Se questa autorizzazione è disattivata, l\'app potrebbe non funzionare normalmente e le relative sveglie potrebbero non avviarsi come programmato."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Consenti a questa app di impostare sveglie e programmare altre azioni. Utilizzare quest\'app quando non stai usando il tuo dispositivo potrebbe consumare più batteria. Se questa autorizzazione è disattivata, l\'app potrebbe non funzionare normalmente e le relative sveglie potrebbero non avviarsi come programmato."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Consenti a questa app di impostare sveglie e programmare azioni per le quali il fattore temporale è decisivo. L\'app potrà essere eseguita in background, comportando un consumo maggiore della batteria.\n\nSe questa autorizzazione viene disattivata, le sveglie esistenti e gli eventi basati sull\'orario programmati da questa app non funzioneranno."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programmare, sveglia, promemoria, orologio"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Attiva"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Attiva Non disturbare"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 8e5649f..5c894a1 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"הצגת גבולות אזור, שוליים וכדומה"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"אילוץ כיוון פריסה מימין לשמאל"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"אילוץ של כיוון פריסת מסך מימין לשמאל עבור כל השפות בכל המקומות"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"אישור טשטושים ברמת החלון"</string>
<string name="force_msaa" msgid="4081288296137775550">"אילוץ הפעלת 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"הפעלת 4x MSAA ביישומי OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"ניפוי באגים בפעולות באזור שאינו מלבני"</string>
@@ -510,9 +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>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"ההגדרה הזו מתירה לאפליקציה להגדיר שעון מעורר ולתזמן פעולות אחרות. ייתכן שהאפליקציה תפעל גם כשלא נעשה שימוש בטלפון שלך, ולכן תגביר את צריכת הסוללה. אם ההרשאה הזו תושבת, יכול להיות שהאפליקציה לא תפעל כראוי ושהשעונים המעוררים לא יפעלו כפי שתוזמנו."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"ההגדרה הזו מתירה לאפליקציה להגדיר שעון מעורר ולתזמן פעולות אחרות. ייתכן שהאפליקציה תפעל גם כשלא נעשה שימוש בטאבלט שלך, ולכן תגביר את צריכת הסוללה. אם ההרשאה הזו תושבת, יכול להיות שהאפליקציה לא תפעל כראוי ושהשעונים המעוררים לא יפעלו כפי שתוזמנו."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"הגדרה זו מתירה לאפליקציה להגדיר שעון מעורר ולתזמן אירועים אחרים. ייתכן שהאפליקציה תפעל גם כשלא נעשה שימוש במכשיר שלך, ולכן תגביר את צריכת הסוללה. אם ההרשאה הזו תושבת, ייתכן שהאפליקציה לא תפעל כראוי ושהשעונים המעוררים לא יפעלו כפי שתוזמנו."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 62d887d..3f23c75e 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -153,8 +153,8 @@
<string name="user_guest" msgid="6939192779649870792">"ゲスト"</string>
<string name="unknown" msgid="3544487229740637809">"不明"</string>
<string name="running_process_item_user_label" msgid="3988506293099805796">"ユーザー: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
- <string name="launch_defaults_some" msgid="3631650616557252926">"一部デフォルトで設定"</string>
- <string name="launch_defaults_none" msgid="8049374306261262709">"デフォルトの設定なし"</string>
+ <string name="launch_defaults_some" msgid="3631650616557252926">"一部のリンクをデフォルトで開くよう設定済みです"</string>
+ <string name="launch_defaults_none" msgid="8049374306261262709">"デフォルトで開く対応リンクはありません"</string>
<string name="tts_settings" msgid="8130616705989351312">"テキスト読み上げの設定"</string>
<string name="tts_settings_title" msgid="7602210956640483039">"テキスト読み上げの設定"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"音声の速度"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"クリップの境界線、マージンなどを表示"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTLレイアウト方向を使用"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"すべての言語/地域で画面レイアウト方向をRTLに設定"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"ウィンドウ レベルでのぼかしを許可"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA を適用"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 アプリで 4x MSAA を有効にする"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"非矩形クリップ操作をデバッグ"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"このアプリに、アラームの設定やその他のアクションのスケジュールを許可します。このアプリは、スマートフォンを使用していないときも使用される可能性があるため、バッテリーの使用量が増えることがあります。この権限が OFF の場合、このアプリは正常に機能しない可能性があり、アラームはスケジュールどおりに動作しません。"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"このアプリに、アラームの設定やその他のアクションのスケジュールを許可します。このアプリは、タブレットを使用していないときも使用される可能性があるため、バッテリーの使用量が増えることがあります。この権限が OFF の場合、このアプリは正常に機能しない可能性があり、アラームはスケジュールどおりに動作しません。"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"このアプリに、アラームの設定やその他のアクションのスケジュールを許可します。このアプリは、デバイスを使用していないときも使用される可能性があるため、バッテリーの使用量が増えることがあります。この権限が OFF の場合、このアプリは正常に機能しない可能性があり、アラームはスケジュールどおりに動作しません。"</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"アラームの設定や時間の制約があるアクションのスケジュールを、このアプリに許可します。これによりアプリがバックグラウンドで実行できるようになるため、バッテリーの使用量が増えることがあります。\n\nこの権限が OFF の場合、このアプリで設定された既存のアラームと時間ベースのイベントは機能しなくなります。"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"スケジュール, アラーム, リマインダー, 時計"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ON にする"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"サイレント モードを ON にする"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index f67d2b2..4723771 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"კლიპის საზღვრების, მინდვრების ჩვენება და ა.შ."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"მარჯვნიდან მარცხნივ განლაგების მიმართულების იძულება"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"ეკრანის RTL მიმართულებაზე იძულება ყველა ლოკალისათვის"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"ფანჯრის დონეზე გაბუნდოვნების დაშვება"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA-ს ჩართვა"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"4x MSAA-ის ჩართვა OpenGL ES 2.0 აპში."</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"არა-მართკუთხა კლიპ-ოპერაციების გამართვა"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"საშუალება მიეცით ამ აპს, დააყენოს მაღვიძარა და დაგეგმოს სხვა მოქმედებები. ამ აპის გამოყენება შესაძლებელია მაშინაც, როცა ტელეფონს არ იყენებთ, რადგან ის მეტ ენერგიას ხარჯავს. თუ ეს ნებართვა გამორთულია, აპმა და მაღვიძარამ შეიძლება სათანადოდ ვერ იმუშაონ."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"საშუალება მიეცით ამ აპს, დააყენოს მაღვიძარა და დაგეგმოს სხვა მოქმედებები. ამ აპის გამოყენება შესაძლებელია მაშინაც, როცა ტაბლეტს არ იყენებთ, რადგან ის მეტ ენერგიას ხარჯავს. თუ ეს ნებართვა გამორთულია, აპმა და მაღვიძარამ შეიძლება სათანადოდ ვერ იმუშაონ."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"საშუალება მიეცით ამ აპს, დააყენოს მაღვიძარა და დაგეგმოს სხვა მოქმედებები. ამ აპის გამოყენება შესაძლებელია მაშინაც, როცა მოწყობილობას არ იყენებთ, რადგან ის მეტ ენერგიას ხარჯავს. თუ ეს ნებართვა გამორთულია, აპმა და მაღვიძარამ შეიძლება სათანადოდ ვერ იმუშაონ."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index be176cb..baae75b 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Қию шегін, шеттерді, т.б. көрсету"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Оңнан солға орналастыру"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Экранның орналасу бағытын барлық тілдер үшін оңнан солға қарату"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Терезе деңгейіндегі бұлдырлар"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA қолдану"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"4x MSAA функциясын OpenGL ES 2.0 қолданбаларында іске қосу"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Тіктөртбұрыштан басқа пішінге қиюды түзету"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"Қолданбаға оятқыштарды орнатуға және басқа да әрекеттерді жоспарлауға рұқсат беру. Телефоныңыз қолданылмай тұрған кезде де бұл қолданба жұмыс істеуі және батарея шығынын арттыруы мүмкін. Егер бұл рұқсат өшірулі болса, қолданба дұрыс жұмыс істемеуі, оның оятқыштары жоспарланғандай іске қосылмауы мүмкін."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Қолданбаға оятқыштарды орнатуға және басқа да әрекеттерді жоспарлауға рұқсат беру. Планшетіңіз қолданылмай тұрған кезде де бұл қолданба жұмыс істеуі және батарея шығынын арттыруы мүмкін. Егер бұл рұқсат өшірулі болса, қолданба дұрыс жұмыс істемеуі, оның оятқыштары жоспарланғандай іске қосылмауы мүмкін."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Қолданбаға оятқыштарды орнатуға және басқа да әрекеттерді жоспарлауға рұқсат беру. Құрылғыңыз қолданылмай тұрған кезде де бұл қолданба жұмыс істеуі және батарея шығынын арттыруы мүмкін. Егер бұл рұқсат өшірулі болса, қолданба дұрыс жұмыс істемеуі, оның оятқыштары жоспарланғандай іске қосылмауы мүмкін."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 7e67b9b..fdbcba4 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -156,7 +156,7 @@
<string name="launch_defaults_some" msgid="3631650616557252926">"លំនាំដើមមួយចំនួនត្រូវបានកំណត់"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"គ្មានការកំណត់លំនាំដើម"</string>
<string name="tts_settings" msgid="8130616705989351312">"ការកំណត់អត្ថបទទៅជាកានិយាយ"</string>
- <string name="tts_settings_title" msgid="7602210956640483039">"លទ្ធផលនៃការបំប្លែងអត្ថបទទៅជាការនិយាយ"</string>
+ <string name="tts_settings_title" msgid="7602210956640483039">"ធាតុចេញនៃការបំប្លែងអត្ថបទទៅជាការនិយាយ"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"អត្រានិយាយ"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"ល្បឿនពេលអានអត្ថបទ"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"ឡើង-ចុះ"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"បង្ហាញការភ្ជាប់អត្ថបទសម្រង់ រឹម ។ល។"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"បង្ខំទិសប្លង់ RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"ប្តូរទិសប្លង់អេក្រង់ទៅជា RTL សម្រាប់គ្រប់ភាសាទាំងអស់"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"អនុញ្ញាតភាពព្រាលកម្រិតវិនដូ"</string>
<string name="force_msaa" msgid="4081288296137775550">"បង្ខំ 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"បើក 4x MSAA ក្នុងកម្មវិធី OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"កែប្រតិបត្តិការផ្នែកដកចេញដែលមិនមានរាងចតុកោណកែង"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"អនុញ្ញាតឱ្យកម្មវិធីនេះកំណត់ម៉ោងរោទ៍ និងកំណត់កាលវិភាគសកម្មភាពផ្សេងទៀត។ កម្មវិធីនេះអាចត្រូវបានប្រើ នៅពេលដែលអ្នកមិនកំពុងប្រើទូរសព្ទរបស់អ្នក។ សកម្មភាពនេះអាចនឹងប្រើប្រាស់ថ្មច្រើនជាងមុន។ ប្រសិនបើបិទការអនុញ្ញាតនេះ កម្មវិធីនេះមិនអាចដំណើរការតាមធម្មតាទេ ហើយម៉ោងរោទ៍របស់វានឹងមិនដំណើរការតាមកាលវិភាគឡើយ។"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"អនុញ្ញាតឱ្យកម្មវិធីនេះកំណត់ម៉ោងរោទ៍ និងកំណត់កាលវិភាគសកម្មភាពផ្សេងទៀត។ កម្មវិធីនេះអាចត្រូវបានប្រើ នៅពេលដែលអ្នកមិនកំពុងប្រើថេប្លេតរបស់អ្នក។ សកម្មភាពនេះអាចនឹងប្រើប្រាស់ថ្មច្រើនជាងមុន។ ប្រសិនបើបិទការអនុញ្ញាតនេះ កម្មវិធីនេះមិនអាចដំណើរការតាមធម្មតាទេ ហើយម៉ោងរោទ៍របស់វានឹងមិនដំណើរការតាមកាលវិភាគឡើយ។"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"អនុញ្ញាតឱ្យកម្មវិធីនេះកំណត់ម៉ោងរោទ៍ និងកំណត់កាលវិភាគសកម្មភាពផ្សេងទៀត។ កម្មវិធីនេះអាចត្រូវបានប្រើ នៅពេលដែលអ្នកមិនកំពុងប្រើឧបករណ៍របស់អ្នក។ សកម្មភាពនេះអាចនឹងប្រើប្រាស់ថ្មច្រើនជាងមុន។ ប្រសិនបើបិទការអនុញ្ញាតនេះ កម្មវិធីនេះមិនអាចដំណើរការតាមធម្មតាទេ ហើយម៉ោងរោទ៍របស់វានឹងមិនដំណើរការតាមកាលវិភាគឡើយ។"</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index fde4d72..21dce27 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"ಕ್ಲಿಪ್ನ ಗಡಿಗಳು, ಅಂಚುಗಳು, ಇತ್ಯಾದಿ ತೋರಿಸು."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL ಲೇಔಟ್ ಡೈರೆಕ್ಷನ್ ಫೋರ್ಸ್ ಮಾಡುವಿಕೆ"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"ಎಲ್ಲ ಭಾಷೆಗಳಿಗಾಗಿ, RTL ಗೆ ಸ್ಕ್ರೀನ್ ಲೇಔಟ್ ಡೈರೆಕ್ಷನ್ ಅನ್ನು ಫೋರ್ಸ್ ಮಾಡಿ"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"ವಿಂಡೋ-ಮಟ್ಟ ಬ್ಲರ್ ಅನುಮತಿಸಿ"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA ಫೋರ್ಸ್ ಮಾಡಿ"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ಅಪ್ಲಿಕೇಶನ್ಗಳಲ್ಲಿ 4x MSAA ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"ಆಯತಾಕಾರವಲ್ಲದ ಕ್ಲಿಪ್ ಕಾರ್ಯಾಚರಣೆ ಡೀಬಗ್"</string>
@@ -390,7 +389,7 @@
<string name="loading_injected_setting_summary" msgid="8394446285689070348">"ಲೋಡ್ ಆಗುತ್ತಿದೆ…"</string>
<string-array name="color_mode_names">
<item msgid="3836559907767149216">"ಸ್ಪಂದನಾತ್ಮಕ (ಡೀಫಾಲ್ಟ್)"</item>
- <item msgid="9112200311983078311">"ಪ್ರಾಕೃತಿಕ"</item>
+ <item msgid="9112200311983078311">"ಸ್ವಾಭಾವಿಕ"</item>
<item msgid="6564241960833766170">"ಪ್ರಮಾಣಿತ"</item>
</string-array>
<string-array name="color_mode_descriptions">
@@ -467,8 +466,8 @@
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ನಿರ್ವಾಹಕರ ಮೂಲಕ ನಿಯಂತ್ರಿಸಲಾಗಿದೆ"</string>
<string name="disabled" msgid="8017887509554714950">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="external_source_trusted" msgid="1146522036773132905">"ಅನುಮತಿಸಲಾಗಿದೆ"</string>
- <string name="external_source_untrusted" msgid="5037891688911672227">"ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string>
- <string name="install_other_apps" msgid="3232595082023199454">"ಅಪರಿಚಿತ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಥಾಪಿಸಿ"</string>
+ <string name="external_source_untrusted" msgid="5037891688911672227">"ಅನುಮತಿ ಇಲ್ಲ"</string>
+ <string name="install_other_apps" msgid="3232595082023199454">"ಅಪರಿಚಿತ ಆ್ಯಪ್ಗಳನ್ನು ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
<string name="home" msgid="973834627243661438">"ಸೆಟ್ಟಿಂಗ್ಗಳ ಮುಖಪುಟ"</string>
<string-array name="battery_labels">
<item msgid="7878690469765357158">"0%"</item>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"ಅಲಾರಂಗಳನ್ನು ಹೊಂದಿಸಲು ಮತ್ತು ಇತರ ಕ್ರಿಯೆಗಳನ್ನು ನಿಗದಿಪಡಿಸಲು ಈ ಆ್ಯಪ್ ಅನ್ನು ಅನುಮತಿಸಿ. ನಿಮ್ಮ ಫೋನ್ ಬಳಸದಿದ್ದಾಗ ಈ ಆ್ಯಪ್ ಅನ್ನು ಬಳಸಬಹುದು, ಅದು ಹೆಚ್ಚು ಬ್ಯಾಟರಿ ಬಳಸಬಹುದು. ಈ ಅನುಮತಿ ಆಫ್ ಆಗಿದ್ದರೆ, ಈ ಆ್ಯಪ್ ಸಾಮಾನ್ಯವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸದೆ ಇರಬಹುದು ಮತ್ತು ಅದರ ಅಲಾರಂಗಳು ನಿಗದಿಯಂತೆ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"ಅಲಾರಂಗಳನ್ನು ಹೊಂದಿಸಲು ಮತ್ತು ಇತರ ಕ್ರಿಯೆಗಳನ್ನು ನಿಗದಿಪಡಿಸಲು ಈ ಆ್ಯಪ್ ಅನ್ನು ಅನುಮತಿಸಿ. ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ನೀವು ಬಳಸದಿದ್ದಾಗ ಈ ಆ್ಯಪ್ ಅನ್ನು ಬಳಸಬಹುದು, ಅದು ಹೆಚ್ಚಿನ ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸಬಹುದು. ಈ ಅನುಮತಿ ಆಫ್ ಆಗಿದ್ದರೆ, ಈ ಆ್ಯಪ್ ಸಾಮಾನ್ಯವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸದೆ ಇರಬಹುದು ಮತ್ತು ಅದರ ಅಲಾರಂಗಳು ನಿಗದಿಯಂತೆ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"ಅಲಾರಂಗಳನ್ನು ಹೊಂದಿಸಲು ಮತ್ತು ಇತರ ಕ್ರಿಯೆಗಳನ್ನು ನಿಗದಿಪಡಿಸಲು ಈ ಆ್ಯಪ್ ಅನ್ನು ಅನುಮತಿಸಿ. ನಿಮ್ಮ ಸಾಧನವನ್ನು ನೀವು ಬಳಸದಿದ್ದಾಗ ಈ ಆ್ಯಪ್ ಅನ್ನು ಬಳಸಬಹುದು, ಅದು ಹೆಚ್ಚಿನ ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸಬಹುದು. ಈ ಅನುಮತಿ ಆಫ್ ಆಗಿದ್ದರೆ, ಈ ಆ್ಯಪ್ ಸಾಮಾನ್ಯವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸದೆ ಇರಬಹುದು ಮತ್ತು ಅದರ ಅಲಾರಂಗಳು ನಿಗದಿಯಂತೆ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
@@ -579,7 +577,7 @@
<string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ಈ ಬದಲಾವಣೆ ಅನ್ವಯವಾಗಲು ನಿಮ್ಮ ಸಾಧನವನ್ನು ರೀಬೂಟ್ ಮಾಡಬೇಕು. ಇದೀಗ ರೀಬೂಟ್ ಮಾಡಿ ಅಥವಾ ರದ್ದುಗೊಳಿಸಿ."</string>
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ವೈಯರ್ ಹೊಂದಿರುವ ಹೆಡ್ಫೋನ್"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ಆನ್ ಆಗಿದೆ"</string>
- <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ಆಫ್ ಆಗಿದೆ"</string>
+ <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ಆಫ್"</string>
<string name="carrier_network_change_mode" msgid="4257621815706644026">"ವಾಹಕ ನೆಟ್ವರ್ಕ್ ಬದಲಾಯಿಸುವಿಕೆ"</string>
<string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
<string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 2bedaa2..6e6a5a7 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"클립 경계, 여백 등을 표시"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL 레이아웃 방향 강제 적용"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"모든 언어에 대해 화면 레이아웃 방향을 RTL로 강제 적용"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"창 수준 블러 허용"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA 강제 사용"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 앱에서 4x MSAA 사용"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"사각형이 아닌 클립 작업 디버그"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"앱에서 알람을 설정하고 다른 작업의 일정을 예약할 수 있도록 허용합니다. 휴대전화를 사용하지 않을 때 앱이 사용될 수 있으며 이로 인해 배터리 사용량이 증가할 수 있습니다. 이 권한을 사용 중지하면 앱이 정상 작동하지 않고 알람이 일정대로 실행되지 않을 수 있습니다."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"앱에서 알람을 설정하고 다른 작업의 일정을 예약할 수 있도록 허용합니다. 태블릿을 사용하지 않을 때 앱이 사용될 수 있으며 이로 인해 배터리 사용량이 증가할 수 있습니다. 이 권한을 사용 중지하면 앱이 정상 작동하지 않고 알람이 일정대로 실행되지 않을 수 있습니다."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"앱에서 알람을 설정하고 다른 작업의 일정을 예약할 수 있도록 허용합니다. 기기를 사용하지 않을 때 앱이 사용될 수 있으며 이로 인해 배터리 사용량이 증가할 수 있습니다. 이 권한을 사용 중지하면 앱이 정상 작동하지 않고 알람이 일정대로 실행되지 않을 수 있습니다."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index c6086ad..140eb3b 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Кесилген нерсенин чектери жана жээктери көрүнөт"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Интерфейсти чагылдыруу"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Интерфейстин элементтери бардык тилдерде оңдон солго карай жайгашат"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Терезенин деңгээлинде бүдөмүктөтүүгө уруксат берүү"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA иштетүү"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 колдонмолорунда 4x MSAA иштетилет"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Татаал формаларды кесүү операцияларынын мүчүлүштүктөрүн оңдоо"</string>
@@ -484,7 +483,7 @@
<string name="screen_zoom_summary_extremely_large" msgid="1438045624562358554">"Эң чоң"</string>
<string name="screen_zoom_summary_custom" msgid="3468154096832912210">"Ыңгайлаштырылган (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="content_description_menu_button" msgid="6254844309171779931">"Меню"</string>
- <string name="retail_demo_reset_message" msgid="5392824901108195463">"Демо режиминде демейки жөндөөлөргө кайтаруу үчүн сырсөздү киргизиңиз"</string>
+ <string name="retail_demo_reset_message" msgid="5392824901108195463">"Демо режиминде баштапкы абалга кайтаруу үчүн сырсөздү киргизиңиз"</string>
<string name="retail_demo_reset_next" msgid="3688129033843885362">"Кийинки"</string>
<string name="retail_demo_reset_title" msgid="1866911701095959800">"Сырсөз талап кылынат"</string>
<string name="active_input_method_subtypes" msgid="4232680535471633046">"Жигердүү киргизүү ыкмалары"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"Бул колдонмого ойготкучтарды коюуга жана башка аракеттерди графикке киргизүүгө уруксат берүү. Бул колдонмо телефонуңуз колдонулбай турганда да иштей алат. Мында батареянын кубаты көбүрөөк керектелиши мүмкүн. Бул параметр өчүрүлгөн болсо, бул колдонмо жана анын ойготкучтары жакшы иштебеши мүмкүн."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Бул колдонмого ойготкучтарды коюуга жана башка аракеттерди графикке киргизүүгө уруксат берүү. Бул колдонмо планшетиңиз колдонулбай турганда да иштей алат. Мында батареянын кубаты көбүрөөк керектелиши мүмкүн. Бул параметр өчүрүлгөн болсо, бул колдонмо жана анын ойготкучтары жакшы иштебеши мүмкүн."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Бул колдонмого ойготкучтарды коюуга жана башка аракеттерди графикке киргизүүгө уруксат берүү. Бул колдонмо түзмөгүңүз колдонулбай турганда да иштей алат. Мында батареянын кубаты көбүрөөк керектелиши мүмкүн. Бул параметр өчүрүлгөн болсо, бул колдонмо жана анын ойготкучтары жакшы иштебеши мүмкүн."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 7eea529..f4962f9 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"ສະແດງໜ້າປົກຄລິບ, ຂອບ ແລະ ອື່ນໆ."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"ບັງຄັບໃຫ້ຮູບຮ່າງຂຽນຈາກຂວາຫາຊ້າຍ"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"ບັງຄັບໃຫ້ຮູບຮ່າງໜ້າຈໍ ຂຽນຈາກຂວາໄປຊ້າຍ ສຳລັບທຸກພາສາ"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"ອະນຸຍາດການມົວໃນລະດັບໜ້າຈໍ"</string>
<string name="force_msaa" msgid="4081288296137775550">"ບັງຄັບໃຊ້ 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"ເປິດໃຊ້ 4x MSAA ໃນແອັບ OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"ດີບັກການເຮັດວຽກຂອງຄລິບທີ່ບໍ່ແມ່ນສີ່ຫຼ່ຽມ"</string>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"ອະນຸຍາດໃຫ້ແອັບນີ້ຕັ້ງໂມງປຸກ ແລະ ກຳນົດເວລາຄຳສັ່ງອື່ນໆ. ແອັບນີ້ອາດຖືກໃຊ້ເມື່ອທ່ານບໍ່ໄດ້ກຳລັງໃຊ້ໂທລະສັບຂອງທ່ານຢູ່, ເຊິ່ງອາດໃຊ້ແບັດເຕີຣີຫຼາຍຂຶ້ນ. ຫາກການອະນຸຍາດນີ້ຖືກປິດໄວ້, ແອັບນີ້ອາດບໍ່ສາມາດເຮັດວຽກໄດ້ຕາມປົກກະຕິ ແລະ ໂມງປຸກຂອງມັນອາດບໍ່ປຸກຕາມທີ່ກຳນົດເວລາໄວ້."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"ອະນຸຍາດໃຫ້ແອັບນີ້ຕັ້ງໂມງປຸກ ແລະ ກຳນົດເວລາຄຳສັ່ງອື່ນໆ. ແອັບນີ້ອາດຖືກໃຊ້ເມື່ອທ່ານບໍ່ໄດ້ກຳລັງໃຊ້ແທັບເລັດຂອງທ່ານຢູ່, ເຊິ່ງອາດໃຊ້ແບັດເຕີຣີຫຼາຍຂຶ້ນ. ຫາກການອະນຸຍາດນີ້ຖືກປິດໄວ້, ແອັບນີ້ອາດບໍ່ສາມາດເຮັດວຽກໄດ້ຕາມປົກກະຕິ ແລະ ໂມງປຸກຂອງມັນອາດບໍ່ປຸກຕາມທີ່ກຳນົດເວລາໄວ້."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"ອະນຸຍາດໃຫ້ແອັບນີ້ຕັ້ງໂມງປຸກ ແລະ ກຳນົດເວລາຄຳສັ່ງອື່ນໆ. ແອັບນີ້ອາດຖືກໃຊ້ເມື່ອທ່ານບໍ່ໄດ້ກຳລັງໃຊ້ອຸປະກອນຂອງທ່ານຢູ່, ເຊິ່ງອາດໃຊ້ແບັດເຕີຣີຫຼາຍຂຶ້ນ. ຫາກການອະນຸຍາດນີ້ຖືກປິດໄວ້, ແອັບນີ້ອາດບໍ່ສາມາດເຮັດວຽກໄດ້ຕາມປົກກະຕິ ແລະ ໂມງປຸກຂອງມັນອາດບໍ່ປຸກຕາມທີ່ກຳນົດເວລາໄວ້."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 79e4870..e920b31 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Rodyti iškarpų ribas, kraštines ir t. t."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Išdėst. iš dešin. į kairę"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Nust. visų lokalių ekran. išdėst. iš deš. į kairę"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Leisti lango suliejimus"</string>
<string name="force_msaa" msgid="4081288296137775550">"Priverst. vykdyti 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Įgalinti 4x MSAA „OpenGL ES 2.0“ programose"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Derinti ne stačiakampio klipo operacijas"</string>
@@ -510,9 +509,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Signalai ir priminimai"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Leisti nustatyti signalus ir priminimus"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signalai ir priminimai"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Leiskite šiai programai nustatyti signalus ir suplanuoti kitus veiksmus. Ši programa gali būti naudojama, kai nenaudojate telefono, todėl gali būti išeikvojama daugiau akumuliatoriaus energijos. Jei šis leidimas išjungtas, ši programa gali tinkamai neveikti ir jos signalai neveiks, kaip suplanuota."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Leiskite šiai programai nustatyti signalus ir suplanuoti kitus veiksmus. Ši programa gali būti naudojama, kai nenaudojate planšetinio kompiuterio, todėl gali būti išeikvojama daugiau akumuliatoriaus energijos. Jei šis leidimas išjungtas, ši programa gali tinkamai neveikti ir jos signalai neveiks, kaip suplanuota."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Leiskite šiai programai nustatyti signalus ir suplanuoti kitus veiksmus. Ši programa gali būti naudojama, kai nenaudojate įrenginio, todėl gali būti išeikvojama daugiau akumuliatoriaus energijos. Jei šis leidimas išjungtas, ši programa gali tinkamai neveikti ir jos signalai neveiks, kaip suplanuota."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Leisti šiai programai nustatyti signalus ir suplanuoti veiksmus, kuriems svarbus laiko veiksnys. Dėl to programa gali veikti fone ir sunaudoti daugiau akumuliatoriaus energijos.\n\nJei šis leidimas išjungtas, šios programos suplanuoti esami signalai ir laiku pagrįsti įvykiai neveiks."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"tvarkaraštis, signalas, priminimas, laikrodis"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Įjungti"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Netrukdymo režimo įjungimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 7f56aad..c43d879 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Rādīt klipu robežas, malas utt."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Virziens no labās uz kreiso (Obligāts) WL: 295"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Obl. izkārt. virz. no labās uz kr. pusi visām lok."</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Atļaut logu aizmiglošanu"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA piespiedu palaiš."</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Iespējot 4x MSAA OpenGL ES 2.0 lietotnēs"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Atkļūdot darbības daļā, kas nav taisnstūris."</string>
@@ -509,9 +508,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Signāli un atgādinājumi"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Atļaut iestatīt signālus un atgādinājumus"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signāli un atgādinājumi"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Atļaut šai lietotnei iestatīt signālus un ieplānot citas darbības. Šī lietotne var tikt izmantota, kamēr jūs neizmantojat tālruni, tāpēc var tikt patērēts vairāk akumulatora enerģijas. Ja šī atļauja ir izslēgta, šī lietotne var nedarboties, kā paredzēts, un tās signāli netiek rādīti ieplānotajā laikā."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Atļaut šai lietotnei iestatīt signālus un ieplānot citas darbības. Šī lietotne var tikt izmantota, kamēr jūs neizmantojat planšetdatoru, tāpēc var tikt patērēts vairāk akumulatora enerģijas. Ja šī atļauja ir izslēgta, šī lietotne var nedarboties, kā paredzēts, un tās signāli netiek rādīti ieplānotajā laikā."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Atļaut šai lietotnei iestatīt signālus un ieplānot citas darbības. Šī lietotne var tikt izmantota, kamēr jūs neizmantojat ierīci, tāpēc var tikt patērēts vairāk akumulatora enerģijas. Ja šī atļauja ir izslēgta, šī lietotne var nedarboties, kā paredzēts, un tās signāli netiek rādīti ieplānotajā laikā."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Atļaujiet šai lietotnei iestatīt signālus un ieplānot darbības, kas jāveic konkrētā laikā. Tādējādi lietotne darbosies fonā un, iespējams, patērēs vairāk akumulatora enerģijas.\n\nJa šī atļauja nav piešķirta, esošie signāli un šīs lietotnes ieplānotie notikumi, kas jāizpilda konkrētā laikā, nedarbosies."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ieplānot, signāls, atgādinājums, pulkstenis"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ieslēgt"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Režīma “Netraucēt” ieslēgšana"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index aee2e61..81f75c5 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Прикажи граници на клип, маргини, итн."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Принудно користи RTL за насока"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Принудно постави насока на распоред на екранот во RTL за сите локални стандарди"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Дозволи замаглување прозорец"</string>
<string name="force_msaa" msgid="4081288296137775550">"Принудно користи 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Овозможи 4x MSAA за апликации OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Отстрани грешка на неправоаголни клип операции"</string>
@@ -506,11 +505,9 @@
<string name="cancel" msgid="5665114069455378395">"Откажи"</string>
<string name="okay" msgid="949938843324579502">"Во ред"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Аларми и потсетници"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Дозволете поставување аларми и потсетници"</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" product="default" msgid="1122213569699233612">"Дозволете ѝ на апликацијава да поставува аларми и да закажува други дејства. Апликацијава може да се користи кога не го користите телефонот, а тоа може да користи повеќе батерија. Ако дозволава е исклучена, апликацијава можеби нема да функционира нормално, а алармите нема да работат според закажаното."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Дозволете ѝ на апликацијава да поставува аларми и да закажува други дејства. Апликацијава може да се користи кога не го користите таблетот, а тоа може да користи повеќе батерија. Ако дозволава е исклучена, апликацијава можеби нема да функционира нормално, а алармите нема да работат според закажаното."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Дозволете ѝ на апликацијава да поставува аларми и да закажува други дејства. Апликацијава може да се користи кога не го користите уредот, а тоа може да користи повеќе батерија. Ако дозволава е исклучена, апликацијава можеби нема да функционира нормално, а алармите нема да работат според закажаното."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 5ff7d1b..9583b50 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"ക്ലിപ്പ് ബൗണ്ടുകൾ, മാർജിനുകൾ തുടങ്ങിയവ ദൃശ്യമാക്കുക"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL ലേഔട്ട് ഡയറക്ഷൻ നിർബന്ധമാക്കുക"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"എല്ലാ ഭാഷകൾക്കുമായി സ്ക്രീൻ ലേഔട്ട് ഡയറക്ഷൻ RTL-ലേക്ക് നിർബന്ധമാക്കുക"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"വിൻഡോ-ലെവൽ മങ്ങിക്കൽ അനുവദിക്കൂ"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA നിർബന്ധമാക്കുക"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ആപ്പുകളിൽ 4x MSAA പ്രവർത്തനക്ഷമമാക്കൂ"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"ചതുരമല്ലാത്ത ക്ലിപ്പ് പ്രവർത്തനം ഡീബഗ്ഗ് ചെയ്യുക"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"അലാറങ്ങൾ സജ്ജീകരിക്കാനും മറ്റ് പ്രവർത്തനങ്ങൾ ഷെഡ്യൂൾ ചെയ്യാനും ഈ ആപ്പിനെ അനുവദിക്കുക. നിങ്ങൾ ഫോൺ ഉപയോഗിക്കാത്തപ്പോൾ ഈ ആപ്പ് ഉപയോഗിച്ചേക്കാം, ഇത് കൂടുതൽ ബാറ്ററി ഉപയോഗിക്കും. ഈ അനുമതി ഓഫാണെങ്കിൽ, ഈ ആപ്പ് സാധാരണ നിലയിൽ പ്രവർത്തിച്ചേക്കില്ല, ഷെഡ്യൂൾ ചെയ്ത പോലെ അതിന്റെ അലാറങ്ങളും പ്രവർത്തിക്കില്ല."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"അലാറങ്ങൾ സജ്ജീകരിക്കാനും മറ്റ് പ്രവർത്തനങ്ങൾ ഷെഡ്യൂൾ ചെയ്യാനും ഈ ആപ്പിനെ അനുവദിക്കുക. കൂടുതൽ ബാറ്ററി ഉപയോഗിച്ചേക്കാവുന്ന നിങ്ങളുടെ ടാബ്ലെറ്റ് ഉപയോഗിക്കാത്തപ്പോൾ ഈ ആപ്പ് ഉപയോഗിച്ചേക്കാം. ഈ അനുമതി ഓഫാണെങ്കിൽ, ഈ ആപ്പ് സ്വാഭാവികമായി പ്രവർത്തിച്ചേക്കില്ല, ഷെഡ്യൂൾ ചെയ്ത പോലെ അതിന്റെ അലാറങ്ങളും പ്രവർത്തിക്കില്ല."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"അലാറങ്ങൾ സജ്ജീകരിക്കാനും മറ്റ് പ്രവർത്തനങ്ങൾ ഷെഡ്യൂൾ ചെയ്യാനും ഈ ആപ്പിനെ അനുവദിക്കുക. കൂടുതൽ ബാറ്ററി ഉപയോഗിച്ചേക്കാവുന്ന നിങ്ങളുടെ ഉപകരണം ഉപയോഗിക്കാത്തപ്പോൾ ഈ ആപ്പ് ഉപയോഗിച്ചേക്കാം. ഈ അനുമതി ഓഫാണെങ്കിൽ, ഈ ആപ്പ് സ്വാഭാവികമായി പ്രവർത്തിച്ചേക്കില്ല, ഷെഡ്യൂൾ ചെയ്ത പോലെ അതിന്റെ അലാറങ്ങളും പ്രവർത്തിക്കില്ല."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index a7d621350..955937b 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Клипийн зах, хязгаар зэргийг харуулах"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL байрлалын чиглэлийг хүчээр тогтоох"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Бүх локалын хувьд дэлгэцийн байрлалын чиглэлийг хүчээр RTL болгох"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Цонхны түвшний бүдгэрүүлэлтийг зөвшөөрөх"</string>
<string name="force_msaa" msgid="4081288296137775550">"Хүчээр 4x MSAA ашиглах"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 апп-уудад 4x MSAA-г идэвхжүүлэх"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Тэгш өнцөгт бус клипийн үйлдлүүдийн согогийг засах"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"Энэ аппад сэрүүлэг тавих болон бусад үйлдлийн хуваарь гаргахыг зөвшөөрнө үү. Таныг утсаа ашиглаагүй үед энэ аппыг ашиглаж магадгүй бөгөөд үүнд илүү их батарей зарцуулж магадгүй. Энэ зөвшөөрлийг унтраасан үед энэ апп хэвийн ажиллахгүй байж магадгүй бөгөөд сэрүүлэг нь хуваарийн дагуу ажиллахгүй."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Энэ аппад сэрүүлэг тавих болон бусад үйлдлийн хуваарь гаргахыг зөвшөөрнө үү. Таныг таблетаа ашиглаагүй үед энэ аппыг ашиглаж магадгүй бөгөөд үүнд илүү их батарей зарцуулж магадгүй. Энэ зөвшөөрлийг унтраасан үед энэ апп хэвийн ажиллахгүй байж магадгүй бөгөөд сэрүүлэг нь хуваарийн дагуу ажиллахгүй."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Энэ аппад сэрүүлэг тавих болон бусад үйлдлийн хуваарь гаргахыг зөвшөөрнө үү. Таныг төхөөрөмжөө ашиглаагүй үед энэ аппыг ашиглаж магадгүй бөгөөд үүнд илүү их батарей зарцуулж магадгүй. Энэ зөвшөөрлийг унтраасан үед энэ апп хэвийн ажиллахгүй байж магадгүй бөгөөд сэрүүлэг нь хуваарийн дагуу ажиллахгүй."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 667b339..8ddb298 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"क्लिप सीमा, समास इत्यादी दर्शवा."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL लेआउट दिशानिर्देशाची सक्ती करा"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"सर्व लोकॅलसाठी RTL स्क्रीन लेआउट दिशानिर्देशाची सक्ती करा"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"विंडो पातळीवरील ब्लरना अनुमती द्या"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA ची सक्ती करा"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ॲप्समध्ये 4x MSAA सुरू करा"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"आयताकृती नसलेले क्लिप ऑपरेशन डीबग करा"</string>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"या ॲपला अलार्म सेट करण्याची आणि इतर कृती शेड्युल करण्याची अनुमती द्या. तुम्ही तुमचा फोन वापरत नसताना हे ॲप वापरले जाऊ शकते, ज्यामुळे जास्त बॅटरी वापरली जाऊ शकते. ही परवानगी नसल्यास, हे ॲप सामान्यपणे काम करू शकणार नाही आणि त्याचे अलार्म शेड्युल केल्याप्रमाणे काम करणार नाहीत."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"या ॲपला अलार्म सेट करण्याची आणि इतर कृती शेड्युल करण्याची अनुमती द्या. तुम्ही तुमचा टॅबलेट वापरत नसताना हे ॲप वापरले जाऊ शकते, ज्यामुळे जास्त बॅटरी वापरली जाऊ शकते. ही परवानगी नसल्यास, हे ॲप सामान्यपणे काम करू शकणार नाही आणि त्याचे अलार्म शेड्युल केल्याप्रमाणे काम करणार नाहीत."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"या ॲपला अलार्म सेट करण्याची आणि इतर कृती शेड्युल करण्याची अनुमती द्या. तुम्ही तुमचे डिव्हाइस वापरत नसताना हे ॲप वापरले जाऊ शकते, ज्यामुळे जास्त बॅटरी वापरली जाऊ शकते. ही परवानगी नसल्यास, हे ॲप सामान्यपणे काम करू शकणार नाही आणि त्याचे अलार्म शेड्युल केल्याप्रमाणे काम करणार नाहीत."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 1011e33..13788c4 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Tunjukkan batas klip, margin dll."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Paksa arah reka letak RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Paksa arah reka letak skrin RTL bagi semua tempat peristiwa"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Benarkan kabur tahap tetingkap"</string>
<string name="force_msaa" msgid="4081288296137775550">"Paksa 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Dayakan 4x MSAA dalam apl OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Nyahpepijat operasi keratan bukan segi empat tepat"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Penggera dan peringatan"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Benarkan penetapan penggera dan peringatan"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Penggera & peringatan"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Benarkan apl ini menetapkan penggera dan menjadualkan tindakan lain. Apl ini mungkin digunakan ketika anda tidak menggunakan telefon, apl mungkin menggunakan lebih banyak bateri. Jika kebenaran ini dimatikan, apl ini mungkin tidak berfungsi seperti biasa dan penggera tidak akan berfungsi seperti yang dijadualkan."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Benarkan apl ini menetapkan penggera dan menjadualkan tindakan lain. Apl ini mungkin digunakan ketika anda tidak menggunakan tablet, apl mungkin menggunakan lebih banyak bateri. Jika kebenaran ini dimatikan, apl ini mungkin tidak berfungsi seperti biasa dan penggera tidak akan berfungsi seperti yang dijadualkan."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Benarkan apl ini menetapkan penggera dan menjadualkan tindakan lain. Apl ini mungkin digunakan ketika anda tidak menggunakan peranti, apl mungkin menggunakan lebih banyak bateri. Jika kebenaran ini dimatikan, apl ini mungkin tidak berfungsi seperti biasa dan penggera tidak akan berfungsi seperti yang dijadualkan."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Benarkan apl ini menetapkan penggera dan menjadualkan tindakan yang sensitif masa. Ini membolehkan apl berjalan di latar, yang mungkin menggunakan lebih banyak bateri.\n\nJika kebenaran ini dimatikan, penggera sedia ada dan acara berdasarkan masa yang dijadualkan oleh apl ini tidak akan berfungsi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadual, penggera, peringatan, jam"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Hidupkan"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Hidupkan Jangan Ganggu"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index e01c123..dac55c5 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"ဖြတ်ပိုင်းအနားသတ်များ၊ အနားများ စသဖြင့် ပြပါ။"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL အပြင်အဆင်အတိုင်း ဖြစ်စေခြင်း"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"ဘာသာစကားအားလုံးအတွက် RTL အပြင်အဆင်အတိုင်း ဖြစ်စေသည်"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"ဝင်းဒိုးအဆင့် မှုန်ဝါးမှု ခွင့်ပြုရန်"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA မဖြစ်မနေဖွင့်ခြင်း"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 အက်ပ်များတွင် 4x MSAA ဖွင့်သည်"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"စတုဂံပုံမကျသောဖြတ်ပိုင်း လုပ်ဆောင်ချက်များကို အမှားဖယ်ရှားသည်"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"နှိုးစက်များသတ်မှတ်ရန်နှင့် အခြားလုပ်ဆောင်ချက်များ အစီအစဉ်ဆွဲရန် ဤအက်ပ်အား ခွင့်ပြုပါ။ သင့်ဖုန်းကို အသုံးမပြုသောအခါ ဤအက်ပ်ကိုသုံးနိုင်ပြီး ၎င်းက ဘက်ထရီပိုသုံးနိုင်သည်။ ဤခွင့်ပြုချက်ကို ပိတ်ထားပါက ဤအက်ပ်သည် ပုံမှန်လုပ်ဆောင်နိုင်ခြင်းမရှိ၍ ၎င်း၏နှိုးစက်များလည်း သတ်မှတ်ထားသည့်အတိုင်း အလုပ်လုပ်တော့မည်မဟုတ်ပါ။"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"နှိုးစက်များသတ်မှတ်ရန်နှင့် အခြားလုပ်ဆောင်ချက်များ အစီအစဉ်ဆွဲရန် ဤအက်ပ်အား ခွင့်ပြုပါ။ သင့်တက်ဘလက်ကို အသုံးမပြုသောအခါ ဤအက်ပ်ကိုသုံးနိုင်ပြီး ၎င်းက ဘက်ထရီပိုသုံးနိုင်သည်။ ဤခွင့်ပြုချက်ကို ပိတ်ထားပါက ဤအက်ပ်သည် ပုံမှန်လုပ်ဆောင်နိုင်ခြင်းမရှိ၍ ၎င်း၏နှိုးစက်များလည်း သတ်မှတ်ထားသည့်အတိုင်း အလုပ်လုပ်တော့မည်မဟုတ်ပါ။"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"နှိုးစက်များသတ်မှတ်ရန်နှင့် အခြားလုပ်ဆောင်ချက်များ အစီအစဉ်ဆွဲရန် ဤအက်ပ်အား ခွင့်ပြုပါ။ သင့်စက်ကို အသုံးမပြုသောအခါ ဤအက်ပ်ကိုသုံးနိုင်ပြီး ၎င်းက ဘက်ထရီပိုသုံးနိုင်သည်။ ဤခွင့်ပြုချက်ကို ပိတ်ထားပါက ဤအက်ပ်သည် ပုံမှန်လုပ်ဆောင်နိုင်ခြင်းမရှိ၍ ၎င်း၏နှိုးစက်များလည်း သတ်မှတ်ထားသည့်အတိုင်း အလုပ်လုပ်တော့မည်မဟုတ်ပါ။"</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index cde30ca..769b468 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Vis kanter, marger osv."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Tving layoutretning for RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Tving RTL-retning på skjermen for alle språk"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Tillat uskarphet i vindu"</string>
<string name="force_msaa" msgid="4081288296137775550">"Tving 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Slå på 4x MSAA i OpenGL ES 2.0-apper"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Feilsøk ikke-rektangulær klipping"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmer og påminnelser"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Tillat innstilling av alarmer og påminnelser"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmer og påminnelser"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Tillat at denne appen stiller inn alarmer og planlegger andre handlinger. Denne appen kan brukes når du ikke bruker telefonen, noe som kan bruke mer batteri. Hvis denne tillatelsen er av, fungerer appen muligens ikke som normalt, og alarmene i den fungerer ikke som planlagt."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Tillat at denne appen stiller inn alarmer og planlegger andre handlinger. Denne appen kan brukes når du ikke bruker nettbrettet, noe som kan bruke mer batteri. Hvis denne tillatelsen er av, fungerer appen muligens ikke som normalt, og alarmene i den fungerer ikke som planlagt."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Tillat at denne appen stiller inn alarmer og planlegger andre handlinger. Denne appen kan brukes når du ikke bruker enheten, noe som kan bruke mer batteri. Hvis denne tillatelsen er av, fungerer appen muligens ikke som normalt, og alarmene i den fungerer ikke som planlagt."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Gi denne appen tillatelse til å angi alarmer og planlegge tidssensitive handlinger. Dette gir appen tillatelse til å kjøre i bakgrunnen, noe som kan bruke mer batteri.\n\nHvis denne tillatelsen er av, fungerer ikke eksisterende alarmer og tidsbaserte hendelser som er planlagt av denne appen."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"tidsplan, alarm, påminnelse, klokke"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Slå på"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Slå på Ikke forstyrr"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index aaf2c63..0bf1a78 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -162,7 +162,7 @@
<string name="tts_default_pitch_title" msgid="6988592215554485479">"पिच"</string>
<string name="tts_default_pitch_summary" msgid="9132719475281551884">"संश्लेषित बोलीको टोनमा प्रभाव पार्छ"</string>
<string name="tts_default_lang_title" msgid="4698933575028098940">"भाषा"</string>
- <string name="tts_lang_use_system" msgid="6312945299804012406">"प्रणालीको भाषा प्रयोग गर्नुहोस्"</string>
+ <string name="tts_lang_use_system" msgid="6312945299804012406">"सिस्टमको भाषा प्रयोग गर्नुहोस्"</string>
<string name="tts_lang_not_selected" msgid="7927823081096056147">"भाषा चयन गरिएको छैन"</string>
<string name="tts_default_lang_summary" msgid="9042620014800063470">"बोली पाठका लागि भाषा-विशेष आवाज सेट गर्दछ"</string>
<string name="tts_play_example_title" msgid="1599468547216481684">"एउटा उदाहरण सुन्नुहोस्"</string>
@@ -223,9 +223,9 @@
<string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"डिभाइसको फिंगरप्रिन्ट: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
<string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"वायरलेसमा जोड्न सकिएन"</string>
<string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> सही नेटवर्कमा जोडिएको कुरा सुनिश्चित गर्नुहोस्"</string>
- <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"यन्त्रसँग जोडा बनाउनुहोस्"</string>
+ <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"यन्त्रसँग कनेक्ट गर्नुहोस्"</string>
<string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi मा कनेक्ट गर्ने कोड"</string>
- <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"जोडा बनाउने प्रक्रिया सफल भएन"</string>
+ <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"कनेक्ट गर्न सकिएन"</string>
<string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"यन्त्र उही नेटवर्कमा जोडिएको कुरा सुनिश्चित गर्नुहोस्।"</string>
<string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR कोड स्क्यान गरेर Wi‑Fi प्रयोग गरी डिभाइस कनेक्ट गर्नुहोस्"</string>
<string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"डिभाइस कनेक्ट गर्दै…"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"क्लिप सीमा, मार्जिन, इत्यादि देखाइयोस्।"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL लेआउट बलपूर्वक प्रयोग गरियोस्"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"सबै लोकेलमा RTLमा स्क्रिन लेआउट बलपूर्वक प्रयोग गरियोस्"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"विन्डो ब्लर गरियोस्"</string>
<string name="force_msaa" msgid="4081288296137775550">"बलपूर्वक 4x MSAA प्रयोग गरियोस्"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES २.० एपमा ४x MSAA अन गरियोस्"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"गैर आयातकर क्लिप रहेका कार्यहरू डिबग गरियोस्"</string>
@@ -468,7 +467,7 @@
<string name="disabled" msgid="8017887509554714950">"असक्षम पारियो"</string>
<string name="external_source_trusted" msgid="1146522036773132905">"अनुमति छ"</string>
<string name="external_source_untrusted" msgid="5037891688911672227">"अनुमति छैन"</string>
- <string name="install_other_apps" msgid="3232595082023199454">"अज्ञात एपहरू इन्स्टल गर्नुहोस्"</string>
+ <string name="install_other_apps" msgid="3232595082023199454">"अज्ञात एप इन्स्टल गर्ने अनुमति"</string>
<string name="home" msgid="973834627243661438">"सेटिङहरूको गृहपृष्ठ"</string>
<string-array name="battery_labels">
<item msgid="7878690469765357158">"०%"</item>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"यो एपलाई अलार्म सेट गर्न तथा अन्य कार्यको समयतालिका तोक्न दिनुहोस्। तपाईंले आफ्नो फोन नचलाएका बेला पनि यो एप प्रयोग गरिन सक्छ। यसले गर्दा थप ब्याट्री खपत हुन सक्छ। यो अनुमति नदिइएका खण्डमा यो एप राम्ररी नचल्न सक्छ र यो एपका अलार्म पनि तोकिएको समयमा बज्ने छैनन्।"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"यो एपलाई अलार्म सेट गर्न तथा अन्य कार्यको समयतालिका तोक्न दिनुहोस्। तपाईंले आफ्नो ट्याब्लेट नचलाएका बेला पनि यो एप प्रयोग गरिन सक्छ। यसले गर्दा थप ब्याट्री खपत हुन सक्छ। यो अनुमति नदिइएका खण्डमा यो एप राम्ररी नचल्न सक्छ र यो एपका अलार्म पनि तोकिएको समयमा बज्ने छैनन्।"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"यो एपलाई अलार्म सेट गर्न तथा अन्य कार्यको समयतालिका तोक्न दिनुहोस्। तपाईंले आफ्नो डिभाइस नचलाएका बेला पनि यो एप प्रयोग गरिन सक्छ। यसले गर्दा थप ब्याट्री खपत हुन सक्छ। यो अनुमति नदिइएका खण्डमा यो एप राम्ररी नचल्न सक्छ र यो एपका अलार्म पनि तोकिएको समयमा बज्ने छैनन्।"</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 806d87b..ca4308c 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Toon clipgrenzen, marges en meer"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"V.r.n.l.-indelingsrichting afdwingen"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Stel de schermindelingsrichting geforceerd in op v.r.n.l. voor alle talen"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Vervagen op vensterniveau toestaan"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA forceren"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Zet 4x MSAA aan in OpenGL ES 2.0-apps"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Foutopsporing niet-rechthoekig bijsnijden"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en herinneringen"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Wekkers en herinneringen laten instellen"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en herinneringen"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Sta deze app toe om wekkers te zetten en andere acties te plannen. Deze app kan actief zijn als je je telefoon niet gebruikt, waardoor je meer batterijlading verbruikt. Als dit recht uitstaat, werkt deze app mogelijk niet naar behoren en de wekkers niet zoals gepland."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Sta deze app toe om wekkers te zetten en andere acties te plannen. Deze app kan worden gebruikt als je je tablet niet gebruikt, waardoor er meer batterijlading wordt verbruikt. Als deze toestemming uit staat, werkt deze app mogelijk niet naar behoren en werken de wekkers niet zoals gepland."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Sta deze app toe om wekkers te zetten en andere acties te plannen. Deze app kan worden gebruikt als je je apparaat niet gebruikt, waardoor er meer batterijlading wordt verbruikt. Als deze toestemming uit staat, werkt deze app mogelijk niet naar behoren en werken de wekkers niet zoals gepland."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Sta toe dat deze app wekkers zet en tijdgevoelige acties plant. De app kan hierdoor op de achtergrond worden uitgevoerd, waardoor je misschien meer batterijlading verbruikt.\n\nAls dit recht uitstaat, werken door deze app geplande bestaande wekkers en tijdgebaseerde afspraken niet."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plannen, schema, wekker, alarm, herinnering, klok"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aanzetten"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zet Niet storen aan."</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 8c86031..21bd1ad 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"କ୍ଲିପ୍ ବାଉଣ୍ଡ, ମାର୍ଜିନ୍ ଆଦି ଦେଖନ୍ତୁ"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL ଲେଆଉଟ୍ ଦିଗ ବାଧ୍ୟ କରନ୍ତୁ"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"ସମସ୍ତ ଲୋକେଲ୍ ସକାଶେ ସ୍କ୍ରୀନ୍ ଲେଆଉଟ୍ ଦିଗ RTL ପାଇଁ ବାଧ୍ୟ କରନ୍ତୁ"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"ୱିଣ୍ଡୋ-ଲେଭେଲରେ ବ୍ଲରକୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA ବାଧ୍ୟ କରନ୍ତୁ"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ଆପ୍ରେ 4x MSAA ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"ଅଣ-ଆୟତାକାର କ୍ଲିପ୍ କାର୍ଯ୍ୟକୁ ଡିବଗ୍ କରନ୍ତୁ"</string>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"ଆଲାରାମଗୁଡ଼ିକୁ ସେଟ୍ କରିବା ଏବଂ ଅନ୍ୟ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ସିଡୁଲ୍ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦିଅନ୍ତୁ। ଆପଣ ଆପଣଙ୍କ ଟାବଲେଟ୍ ବ୍ୟବହାର କରୁନଥିବା ସମୟରେ ଏହି ଆପକୁ ବ୍ୟବହାର କରାଯାଇପାରେ, ଯାହା ଅଧିକ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରିପାରେ। ଯଦି ଏହି ଅନୁମତି ବନ୍ଦ ଥାଏ, ଏହି ଆପ୍ ସାମାନ୍ୟ ରୂପେ କାର୍ଯ୍ୟ କରିନପାରେ ଏବଂ ଏହାର ଆଲାରାମଗୁଡ଼ିକ ସିଡୁଲ୍ କରାଯାଇଥିବା ଅନୁସାରେ କାମ କରିବ ନାହିଁ।"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"ଆଲାରାମଗୁଡ଼ିକୁ ସେଟ୍ କରିବା ଏବଂ ଅନ୍ୟ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ସିଡୁଲ୍ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦିଅନ୍ତୁ। ଆପଣ ଆପଣଙ୍କ ଟାବଲେଟ୍ ବ୍ୟବହାର କରୁନଥିବା ସମୟରେ ଏହି ଆପକୁ ବ୍ୟବହାର କରାଯାଇପାରେ, ଯାହା ଅଧିକ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରିପାରେ। ଯଦି ଏହି ଅନୁମତି ବନ୍ଦ ଥାଏ, ଏହି ଆପ୍ ସାମାନ୍ୟ ରୂପେ କାର୍ଯ୍ୟ କରିନପାରେ ଏବଂ ଏହାର ଆଲାରାମଗୁଡ଼ିକ ସିଡୁଲ୍ କରାଯାଇଥିବା ଅନୁସାରେ କାମ କରିବ ନାହିଁ।"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"ଆଲାରାମଗୁଡ଼ିକୁ ସେଟ୍ କରିବା ଏବଂ ଅନ୍ୟ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ସିଡୁଲ୍ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦିଅନ୍ତୁ। ଆପଣ ଆପଣଙ୍କ ଟାବଲେଟ୍ ବ୍ୟବହାର କରୁନଥିବା ସମୟରେ ଏହି ଆପକୁ ବ୍ୟବହାର କରାଯାଇପାରେ, ଯାହା ଅଧିକ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରିପାରେ। ଯଦି ଏହି ଅନୁମତି ବନ୍ଦ ଥାଏ, ଏହି ଆପ୍ ସାମାନ୍ୟ ରୂପେ କାର୍ଯ୍ୟ କରିନପାରେ ଏବଂ ଏହାର ଆଲାରାମଗୁଡ଼ିକ ସିଡୁଲ୍ କରାଯାଇଥିବା ଅନୁସାରେ କାମ କରିବ ନାହିଁ।"</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 635f0a8..aaa892a 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -156,7 +156,7 @@
<string name="launch_defaults_some" msgid="3631650616557252926">"ਕੁਝ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈੱਟ ਕੀਤੇ"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"ਕੋਈ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਸੈੱਟ ਨਹੀਂ ਕੀਤੇ"</string>
<string name="tts_settings" msgid="8130616705989351312">"ਲਿਖਤ ਤੋਂ ਬੋਲੀ ਸੈਟਿੰਗਾਂ"</string>
- <string name="tts_settings_title" msgid="7602210956640483039">"ਲਿਖਤ ਤੋਂ ਬੋਲੀ ਆਊਟਪੁੱਟ"</string>
+ <string name="tts_settings_title" msgid="7602210956640483039">"ਲਿਖਤ-ਤੋਂ-ਬੋਲੀ ਆਊਟਪੁੱਟ"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"ਬੋਲਣ ਦੀ ਗਤੀ"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"ਸਪੀਡ ਜਿਸਤੇ ਟੈਕਸਟ ਬੋਲਿਆ ਜਾਂਦਾ ਹੈ"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"ਪਿਚ"</string>
@@ -196,7 +196,7 @@
</string-array>
<string name="choose_profile" msgid="343803890897657450">"ਪ੍ਰੋਫਾਈਲ ਚੁਣੋ"</string>
<string name="category_personal" msgid="6236798763159385225">"ਨਿੱਜੀ"</string>
- <string name="category_work" msgid="4014193632325996115">"ਕਾਰਜ-ਸਥਾਨ"</string>
+ <string name="category_work" msgid="4014193632325996115">"ਕੰਮ ਸੰਬੰਧੀ"</string>
<string name="development_settings_title" msgid="140296922921597393">"ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"ਵਿਕਾਸਕਾਰ ਵਿਕਲਪਾਂ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
<string name="development_settings_summary" msgid="8718917813868735095">"ਐਪ ਵਿਕਾਸ ਲਈ ਚੋਣਾਂ ਸੈੱਟ ਕਰੋ"</string>
@@ -214,7 +214,7 @@
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ਉਪਲਬਧ ਡੀਵਾਈਸਾਂ ਨੂੰ ਦੇਖਣ ਅਤੇ ਵਰਤਣ ਲਈ, ਵਾਇਰਲੈੱਸ ਡੀਬੱਗਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR ਕੋਡ ਨਾਲ ਡੀਵਾਈਸ ਨੂੰ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"QR ਕੋਡ ਸਕੈਨਰ ਵਰਤ ਕੇ ਨਵੇਂ ਡੀਵਾਈਸਾਂ ਨੂੰ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
- <string name="adb_pair_method_code_title" msgid="1122590300445142904">"ਜੋੜਾਬੱਧਕਰਨ ਕੋਡ ਨਾਲ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+ <string name="adb_pair_method_code_title" msgid="1122590300445142904">"ਜੋੜਾਬੱਧਕਰਨ ਕੋਡ ਨਾਲ ਡੀਵਾਈਸ ਨੂੰ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
<string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ਛੇ ਅੰਕਾਂ ਵਾਲਾ ਕੋਡ ਵਰਤ ਕੇ ਨਵੇਂ ਡੀਵਾਈਸਾਂ ਨੂੰ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
<string name="adb_paired_devices_title" msgid="5268997341526217362">"ਜੋੜਾਬੱਧ ਕੀਤੇ ਡੀਵਾਈਸ"</string>
<string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"ਇਸ ਵੇਲੇ ਕਨੈਕਟ ਹੈ"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"ਕਲਿੱਪ ਸੀਮਾਵਾਂ, ਹਾਸ਼ੀਏ ਆਦਿ ਦਿਖਾਓ"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਵਾਲਾ ਖਾਕਾ ਲਾਗੂ ਕਰੋ"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ ਲਈ ਸਕ੍ਰੀਨ \'ਤੇ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਵਾਲਾ ਖਾਕਾ ਲਾਗੂ ਕਰੋ"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"ਵਿੰਡੋ-ਪੱਧਰ \'ਤੇ ਧੁੰਦਲਾ ਕਰਨ ਦਿਓ"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA ਤੇ ਜ਼ੋਰ ਪਾਓ"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ਐਪਾਂ ਵਿੱਚ 4x MSAA ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"ਗੈਰ-ਆਇਤਾਕਾਰ ਕਲਿੱਪ ਓਪਰੇਸ਼ਨ ਡੀਬੱਗ ਕਰੋ"</string>
@@ -427,7 +426,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ਲਾਲ-ਹਰਾ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ਨੀਲਾ-ਪੀਲਾ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ਰੰਗ ਸੁਧਾਈ"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਰੰਗਾਂ ਨੂੰ ਦਿਖਾਉਣ ਦੇ ਤਰੀਕੇ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ। ਇਹ ਉਦੋਂ ਲਾਹੇਵੰਦ ਹੋ ਸਕਦਾ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਇਹ ਕਰਨਾ ਚਾਹੋਗੇ:<br/><br/> <ol> <li>&nbsp;ਰੰਗਾਂ ਨੂੰ ਹੋਰ ਸਟੀਕਤਾ ਨਾਲ ਦੇਖਣਾ</li> <li>&nbsp;ਫੋਕਸ ਕਰਨ ਵਿੱਚ ਤੁਹਾਡੀ ਮਦਦ ਲਈ ਰੰਗਾਂ ਨੂੰ ਹਟਾਉਣਾ</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਰੰਗਾਂ ਨੂੰ ਦਿਖਾਉਣ ਦੇ ਤਰੀਕੇ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ। ਇਹ ਉਦੋਂ ਲਾਹੇਵੰਦ ਹੋ ਸਕਦਾ ਹੈ ਜਦੋਂ ਤੁਸੀਂ:<br/><br/> <ol> <li>&nbsp;ਰੰਗਾਂ ਨੂੰ ਹੋਰ ਸਟੀਕਤਾ ਨਾਲ ਦੇਖਣਾ ਚਾਹੋ</li> <li>&nbsp;ਫੋਕਸ ਕਰਨ ਵਿੱਚ ਤੁਹਾਡੀ ਮਦਦ ਕਰਨ ਲਈ ਰੰਗਾਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੋ</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ"</string>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"ਇਸ ਐਪ ਨੂੰ ਅਲਾਰਮ ਸੈੱਟ ਕਰਨ ਅਤੇ ਹੋਰ ਕਾਰਵਾਈਆਂ ਨੂੰ ਨਿਯਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ। ਇਸ ਐਪ ਦੀ ਵਰਤੋਂ ਉਦੋਂ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਆਪਣੇ ਫ਼ੋਨ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕਰ ਰਹੇ ਹੋ, ਜਿਸ ਕਾਰਨ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਵਧੇਰੇ ਹੋ ਸਕਦੀ ਹੈ। ਜੇ ਇਹ ਇਜਾਜ਼ਤ ਬੰਦ ਹੋ ਜਾਂਦੀ ਹੈ, ਤਾਂ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਐਪ ਆਮ ਵਾਂਗ ਕੰਮ ਨਾ ਕਰੇ ਅਤੇ ਇਸਦੇ ਅਲਾਰਮ ਨਿਯਤ ਸਮੇਂ ਅਨੁਸਾਰ ਕੰਮ ਨਾ ਕਰਨ।"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"ਇਸ ਐਪ ਨੂੰ ਅਲਾਰਮ ਸੈੱਟ ਕਰਨ ਅਤੇ ਹੋਰ ਕਾਰਵਾਈਆਂ ਨੂੰ ਨਿਯਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ। ਇਸ ਐਪ ਦੀ ਵਰਤੋਂ ਉਦੋਂ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਆਪਣੇ ਟੈਬਲੈੱਟ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕਰ ਰਹੇ ਹੋ, ਜਿਸ ਕਾਰਨ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਵਧੇਰੇ ਹੋ ਸਕਦੀ ਹੈ। ਜੇ ਇਹ ਇਜਾਜ਼ਤ ਬੰਦ ਹੋ ਜਾਂਦੀ ਹੈ, ਤਾਂ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਐਪ ਆਮ ਵਾਂਗ ਕੰਮ ਨਾ ਕਰੇ ਅਤੇ ਇਸਦੇ ਅਲਾਰਮ ਨਿਯਤ ਸਮੇਂ ਅਨੁਸਾਰ ਕੰਮ ਨਾ ਕਰਨ।"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"ਇਸ ਐਪ ਨੂੰ ਅਲਾਰਮ ਸੈੱਟ ਕਰਨ ਅਤੇ ਹੋਰ ਕਾਰਵਾਈਆਂ ਨੂੰ ਨਿਯਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ। ਇਸ ਐਪ ਦੀ ਵਰਤੋਂ ਉਦੋਂ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਆਪਣੇ ਡੀਵਾਈਸ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕਰ ਰਹੇ ਹੋ, ਜਿਸ ਕਾਰਨ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਵਧੇਰੇ ਹੋ ਸਕਦੀ ਹੈ। ਜੇ ਇਹ ਇਜਾਜ਼ਤ ਬੰਦ ਹੋ ਜਾਂਦੀ ਹੈ, ਤਾਂ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਐਪ ਆਮ ਵਾਂਗ ਕੰਮ ਨਾ ਕਰੇ ਅਤੇ ਇਸਦੇ ਅਲਾਰਮ ਨਿਯਤ ਸਮੇਂ ਅਨੁਸਾਰ ਕੰਮ ਨਾ ਕਰਨ।"</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 7e8a571..99faea7 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Pokaż granice przycięcia, marginesy itd."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Układ od prawej do lewej"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Wymuś wszędzie układ ekranu od prawej do lewej"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Zezwól na rozmycie na poziomie okna"</string>
<string name="force_msaa" msgid="4081288296137775550">"Wymuś 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Włącz 4x MSAA w aplikacjach OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Debuguj operacje przycinania nieprostokątnego"</string>
@@ -508,11 +507,9 @@
<string name="cancel" msgid="5665114069455378395">"Anuluj"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmy i przypomnienia"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Zezwól na ustawianie alarmów i przypomnień"</string>
+ <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Zezwalaj na ustawianie alarmów i przypomnień"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmy i przypomnienia"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Zezwól na ustawianie alarmów i planowanie innych działań przez tę aplikację. Ta aplikacja może być używana, gdy nie korzystasz z telefonu. Może to zwiększyć wykorzystanie baterii. Jeśli nie włączysz tych uprawnień, ta aplikacja może nie działać prawidłowo, a jej alarmy nie będą uruchamiane zgodnie z harmonogramem."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Zezwól na ustawianie alarmów i planowanie innych działań przez tę aplikację. Ta aplikacja może być używana, gdy nie korzystasz z tabletu. Może to zwiększyć wykorzystanie baterii. Jeśli nie włączysz tych uprawnień, ta aplikacja może nie działać prawidłowo, a jej alarmy nie będą uruchamiane zgodnie z harmonogramem."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Zezwól na ustawianie alarmów i planowanie innych działań przez tę aplikację. Ta aplikacja może być używana, gdy nie korzystasz z urządzenia. Może to zwiększyć wykorzystanie baterii. Jeśli nie włączysz tych uprawnień, ta aplikacja może nie działać prawidłowo, a jej alarmy nie będą uruchamiane zgodnie z harmonogramem."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwól na ustawianie alarmów i planowanie innych działań, w przypadku których czas jest istotny. Dzięki temu aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tych uprawnień, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"harmonogram, alarm, przypomnienie, zegar"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Włącz"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Włącz tryb Nie przeszkadzać"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index d6f6da3..021a75e 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -211,7 +211,7 @@
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuração quando a rede Wi‑Fi estiver conectada"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Erro"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração por Wi-Fi"</string>
- <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar dispositivos disponíveis, ative a depuração por Wi-Fi"</string>
+ <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar dispositivos disponíveis, ative a depuração por Wi-Fi."</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parear o dispositivo com um código QR"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Parear novos dispositivos usando um leitor de código QR"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"Parear o dispositivo com um código de pareamento"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Mostrar limites de corte, margens, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forçar layout da direita p/ esquerda"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Forçar a direção do layout da direita para a esquerda para todas as localidades"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Permitir desfoques de janela"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forçar 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Ativar 4x MSAA em apps OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operações de corte não retangulares"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Permitir que esse app defina alarmes e programe outras ações. Ele poderá ser usado quando você não estiver usando o smartphone, o que consumirá mais bateria. Se essa permissão for desativada, o app e os alarmes dele poderão não funcionar como planejado."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Permitir que esse app defina alarmes e programe outras ações. Ele poderá ser usado quando você não estiver usando o tablet, o que consumirá mais bateria. Se essa permissão for desativada, o app e os alarmes dele poderão não funcionar como planejado."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Permitir que esse app defina alarmes e programe outras ações. Ele poderá ser usado quando você não estiver usando o dispositivo, o que consumirá mais bateria. Se essa permissão for desativada, o app e os alarmes dele poderão não funcionar como planejado."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 294f61a..cdea8b2 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Apresentar limites de clipes, margens, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forçar direção do esquema RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Forçar dir. do esq. do ecrã p. RTL tds os locais"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Permitir esbater janelas"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forçar 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Ativar o 4x MSAA em aplicações OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operações de clipe não retangulares"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Permita que esta app defina alarmes e agende outras ações. Esta app pode ser utilizada quando não estiver a utilizar o seu telemóvel, o que pode consumir mais bateria. Se esta autorização estiver desativada, esta app pode não funcionar normalmente e os respetivos alarmes não irão funcionar conforme agendado."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Permita que esta app defina alarmes e agende outras ações. Esta app pode ser utilizada quando não estiver a utilizar o seu tablet, o que pode consumir mais bateria. Se esta autorização estiver desativada, esta app pode não funcionar normalmente e os respetivos alarmes não irão funcionar conforme agendado."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Permita que esta app defina alarmes e agende outras ações. Esta app pode ser utilizada quando não estiver a utilizar o seu dispositivo, o que pode consumir mais bateria. Se esta autorização estiver desativada, esta app pode não funcionar normalmente e os respetivos alarmes não irão funcionar conforme agendado."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permita que esta app defina alarmes e agende outras ações com base no tempo. Esta ação permite que a app seja executada em segundo plano, o que pode utilizar mais bateria.\n\nSe esta autorização estiver desativada, os alarmes existentes e os eventos com base no tempo agendados por esta app não funcionam."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"agendar, alarme, lembrete, relógio"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o modo Não incomodar"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index d6f6da3..021a75e 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -211,7 +211,7 @@
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuração quando a rede Wi‑Fi estiver conectada"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Erro"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração por Wi-Fi"</string>
- <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar dispositivos disponíveis, ative a depuração por Wi-Fi"</string>
+ <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar dispositivos disponíveis, ative a depuração por Wi-Fi."</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parear o dispositivo com um código QR"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Parear novos dispositivos usando um leitor de código QR"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"Parear o dispositivo com um código de pareamento"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Mostrar limites de corte, margens, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forçar layout da direita p/ esquerda"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Forçar a direção do layout da direita para a esquerda para todas as localidades"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Permitir desfoques de janela"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forçar 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Ativar 4x MSAA em apps OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operações de corte não retangulares"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Permitir que esse app defina alarmes e programe outras ações. Ele poderá ser usado quando você não estiver usando o smartphone, o que consumirá mais bateria. Se essa permissão for desativada, o app e os alarmes dele poderão não funcionar como planejado."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Permitir que esse app defina alarmes e programe outras ações. Ele poderá ser usado quando você não estiver usando o tablet, o que consumirá mais bateria. Se essa permissão for desativada, o app e os alarmes dele poderão não funcionar como planejado."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Permitir que esse app defina alarmes e programe outras ações. Ele poderá ser usado quando você não estiver usando o dispositivo, o que consumirá mais bateria. Se essa permissão for desativada, o app e os alarmes dele poderão não funcionar como planejado."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index c922684..e02bada 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Afișați limitele clipului, marginile etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Direcție aspect dreapta - stânga"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Direcție obligatorie aspect ecran dreapta - stânga"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Permiteți estompări la nivel de fereastră"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forțați MSAA 4x"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Activați MSAA 4x în aplicațiile OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Remediați decupări nerectangulare"</string>
@@ -509,9 +508,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarme și mementouri"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permiteți setarea pentru alarme și mementouri"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Permiteți ca aplicația să seteze alarme și să programeze alte acțiuni. Aplicația poate rula când nu folosiți telefonul, ceea ce poate consuma mai multă baterie. Dacă permisiunea este dezactivată, este posibil ca aplicația să nu funcționeze normal, iar alarmele nu vor funcționa conform planului."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Permiteți ca aplicația să seteze alarme și să programeze alte acțiuni. Aplicația poate rula când nu folosiți tableta, ceea ce poate consuma mai multă baterie. Dacă permisiunea este dezactivată, este posibil ca aplicația să nu funcționeze normal, iar alarmele nu vor funcționa conform planului."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Permiteți ca aplicația să seteze alarme și să programeze alte acțiuni. Aplicația poate rula când nu folosiți dispozitivul, ceea ce poate consuma mai multă baterie. Dacă permisiunea este dezactivată, este posibil ca aplicația să nu funcționeze normal, iar alarmele nu vor funcționa conform planului."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permiteți acestei aplicații să stabilească alarme și să planifice acțiuni dependente de timp. Astfel, aplicația poate să ruleze în fundal, fapt care ar putea consuma mai multă baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programare, alarmă, memento, ceas"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activați"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activați Nu deranja"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 24a5039..923917b 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -179,7 +179,7 @@
<string name="tts_status_checking" msgid="8026559918948285013">"Проверка…"</string>
<string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
<string name="tts_engine_settings_button" msgid="477155276199968948">"Настройки синтеза речи"</string>
- <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"Система по умолчанию"</string>
+ <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"Синтезатор речи по умолчанию"</string>
<string name="tts_general_section_title" msgid="8919671529502364567">"Общие"</string>
<string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"Тон по умолчанию"</string>
<string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"Установить стандартный тон при озвучивании текста."</string>
@@ -213,9 +213,9 @@
<string name="adb_wireless_settings" msgid="2295017847215680229">"Отладка по Wi-Fi"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Чтобы увидеть и использовать доступные устройства, включите отладку по Wi-Fi."</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Подключить устройство с помощью QR-кода"</string>
- <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Подключение новых устройств с помощью сканера QR-кодов"</string>
+ <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Отсканировать QR-код для подключения устройства"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"Подключить устройство с помощью кода подключения"</string>
- <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Подключение новых устройств с помощью шестизначного кода"</string>
+ <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Ввести шестизначный код для подключения устройства"</string>
<string name="adb_paired_devices_title" msgid="5268997341526217362">"Подключенные устройства"</string>
<string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Текущие подключения"</string>
<string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Сведения об устройстве"</string>
@@ -226,13 +226,13 @@
<string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Подключение к устройству"</string>
<string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Код подключения по сети Wi‑Fi"</string>
<string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Не удалось подключить устройство"</string>
- <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Устройство должно быть подключено к той же самой сети."</string>
- <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Подключение устройства через Wi‑Fi с использованием QR-кода"</string>
+ <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Оба устройства должны быть подключены к одной и той же сети."</string>
+ <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Отсканируйте QR-код, чтобы подключить устройство через Wi‑Fi."</string>
<string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Подключение устройства…"</string>
<string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Не удалось подключить устройство. QR-код неверный, или устройство находится в другой сети."</string>
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-адрес и порт"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Отсканируйте QR-код"</string>
- <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Подключение устройства через Wi‑Fi с использованием QR-кода"</string>
+ <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Отсканируйте QR-код, чтобы подключить устройство через Wi‑Fi."</string>
<string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Подключите устройство к сети Wi-Fi."</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, отладка, разработчик"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Отчет об ошибке"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Показывать границы обрезки, поля и т. п."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Отразить интерфейс"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Принудительно расположить элементы интерфейса справа налево во всех локалях"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Размытие на уровне окон"</string>
<string name="force_msaa" msgid="4081288296137775550">"Включить 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Включить 4x MSAA в приложениях OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Отладка операций усечения сложной формы"</string>
@@ -510,9 +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>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Если вы разрешите этому приложению устанавливать будильники и создавать напоминания, оно сможет работать, даже когда вы не пользуетесь телефоном. Правда, в результате заряд батареи будет расходоваться быстрее. Если отключить эту настройку, в работе приложения могут возникать сбои, а будильники не будут запускаться вовремя."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Если вы разрешите этому приложению устанавливать будильники и создавать напоминания, оно сможет работать, даже когда вы не пользуетесь планшетом. Правда, в результате заряд батареи будет расходоваться быстрее. Если отключить эту настройку, в работе приложения могут возникать сбои, а будильники не будут запускаться вовремя."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Если вы разрешите этому приложению устанавливать будильники и создавать напоминания, оно сможет работать, даже когда вы не пользуетесь устройством. Правда, в результате заряд батареи будет расходоваться быстрее. Если отключить эту настройку, в работе приложения могут возникать сбои, а будильники не будут запускаться вовремя."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index ddfa1c5..3c79bf3 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"ක්ලිප් සීමා, මායිම්, ආදිය පෙන්වන්න."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"බල RTL පිරිසැලසුම් දිශාව"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"සියලු පෙදෙසි සඳහා RTL වෙත බල තිර පිරිසැලසුම"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"කවුළු මට්. බොඳ කි. ඉඩ දෙ."</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA බල කරන්න"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 යෙදුම්හි 4x MSAA සබල කරන්න"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"සෘජුකෝණාස්ර-නොවන ක්ලිප් මෙහෙයුම් නිදොස් කරන්න"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"එලාම සැකසීමට සහ වෙනත් ක්රියා කාල සටහන්ගත කිරීමට මෙම යෙදුමට ඉඩ දෙන්න. ඔබ ඔබගේ දුරකථනය භාවිත නොකරන විට මෙම යෙදුම භාවිත කළ හැකිය, එය බැටරිය වැඩියෙන් භාවිත කළ හැකිය. මෙම අවසරය ක්රියාවිරහිත නම්, මෙම යෙදුම සාමාන්ය ආකාරයට ක්රියා නොකළ හැකි අතර, එහි එලාම කාල සටහන්ගත කර ඇති පරිදි ක්රියා නොකරනු ඇත."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"එලාම සැකසීමට සහ වෙනත් ක්රියා කාල සටහන්ගත කිරීමට මෙම යෙදුමට ඉඩ දෙන්න. ඔබ ඔබගේ ටැබ්ලටය භාවිත නොකරන විට මෙම යෙදුම භාවිත කළ හැකිය, එය බැටරිය වැඩියෙන් භාවිත කළ හැකිය. මෙම අවසරය ක්රියාවිරහිත නම්, මෙම යෙදුම සාමාන්ය ආකාරයට ක්රියා නොකළ හැකි අතර, එහි එලාම කාල සටහන්ගත කර ඇති පරිදි ක්රියා නොකරනු ඇත."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"එලාම සැකසීමට සහ වෙනත් ක්රියා කාල සටහන්ගත කිරීමට මෙම යෙදුමට ඉඩ දෙන්න. ඔබ ඔබගේ උපාංගය භාවිත නොකරන විට මෙම යෙදුම භාවිත කළ හැකිය, එය බැටරිය වැඩියෙන් භාවිත කළ හැකිය. මෙම අවසරය ක්රියාවිරහිත නම්, මෙම යෙදුම සාමාන්ය ආකාරයට ක්රියා නොකළ හැකි අතර, එහි එලාම කාල සටහන්ගත කර ඇති පරිදි ක්රියා නොකරනු ඇත."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 0d04d69..5be0d99 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Zobraziť vo výstrižku ohraničenie, okraje a pod."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Rozloženie sprava doľava"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Vynútiť pre všetky jazyky rozloženie obrazovky sprava doľava"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Povolenie rozmazania na úrovni okna"</string>
<string name="force_msaa" msgid="4081288296137775550">"Vynútiť 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Povoliť 4x MSAA v aplikáciách OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Ladiť operácie s neobdĺžnikovými výstrižkami"</string>
@@ -510,9 +509,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Budíky a pripomenutia"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Povoliť nastavovanie budíkov a pripomenutí"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a pripomenutia"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Povoľte tejto aplikácii nastavovať budíky a plánovať ďalšie akcie. Táto aplikácia môže byť spustená, keď nepoužívate telefón, čo môže zvýšiť spotrebu batérie. Ak je toto povolenie vypnuté, daná aplikácia nemusí správne fungovať a jej budíky nebudú aktivované podľa plánu."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Povoľte tejto aplikácii nastavovať budíky a plánovať ďalšie akcie. Táto aplikácia môže byť spustená, keď nepoužívate tablet, čo môže zvýšiť spotrebu batérie. Ak je toto povolenie vypnuté, daná aplikácia nemusí správne fungovať a jej budíky nebudú aktivované podľa plánu."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Povoľte tejto aplikácii nastavovať budíky a plánovať ďalšie akcie. Táto aplikácia môže byť spustená, keď nepoužívate zariadenie, čo môže zvýšiť spotrebu batérie. Ak je toto povolenie vypnuté, daná aplikácia nemusí správne fungovať a jej budíky nebudú aktivované podľa plánu."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, súčasné budíky a udalosti s časovým obmedzením naplánované touto aplikáciu nebudú fungovať."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, pripomenutie, hodiny"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnúť"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapnite režim bez vyrušení"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 796b938..07e367b 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Pokaži meje obrezovanja, obrobe ipd."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Vsili od desne proti levi"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Vsili smer postavitve na zaslonu od desne proti levi za vse jezike."</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Dovoli zameglitve na ravni okna"</string>
<string name="force_msaa" msgid="4081288296137775550">"Vsili 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"V aplikacijah OpenGL ES 2.0 omogoči 4x MSAA."</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Odpravljanje težav s postopki nepravokotnega izrezovanja"</string>
@@ -510,9 +509,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi in opomniki"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dovoli nastavljanje alarmov in opomnikov"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi in opomniki"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Tej aplikaciji dovolite nastavljanje alarmov in načrtovanje drugih dejanj. Ta aplikacija je lahko v uporabi, ko ne uporabljate telefona, kar lahko povzroči večjo porabo energije baterije. Če je to dovoljenje izklopljeno, ta aplikacija morda ne bo normalno delovala in se zato alarmi ne bodo sprožili po urniku."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Tej aplikaciji dovolite nastavljanje alarmov in načrtovanje drugih dejanj. Ta aplikacija je lahko v uporabi, ko ne uporabljate tabličnega računalnika, kar lahko povzroči večjo porabo energije baterije. Če je to dovoljenje izklopljeno, ta aplikacija morda ne bo normalno delovala in se zato alarmi ne bodo sprožili po urniku."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Tej aplikaciji dovolite nastavljanje alarmov in načrtovanje drugih dejanj. Ta aplikacija je lahko v uporabi, ko ne uporabljate naprave, kar lahko povzroči večjo porabo energije baterije. Če je to dovoljenje izklopljeno, ta aplikacija morda ne bo normalno delovala in se zato alarmi ne bodo sprožili po urniku."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Tej aplikaciji dovolite nastavljanje alarmov in načrtovanje časovno občutljivih dejanj. S tem aplikaciji omogočite izvajanje v ozadju, kar bo morda povečalo porabo energije baterije.\n\nČe je to dovoljenje izklopljeno, obstoječi alarmi in časovno občutljivi dogodki, ki jih nastavi ta aplikacija, ne bodo delovali."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"načrtovanje, urnik, alarm, opomnik, ura"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Vklopi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Vklop načina »Ne moti«"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 99d5c71..1f30a02 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Shfaq konturet e klipit, hapësirat etj."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Detyro drejtimin e shkrimit nga e djathta në të majtë"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Ndrysho me detyrim drejtimin e planit të ekranit nga e djathta në të majtë për të gjitha vendet"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Lejo turbullimet në nivel dritareje"</string>
<string name="force_msaa" msgid="4081288296137775550">"Detyro 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Aktivizo 4x MSAA në aplikacionet OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Korrigjo veprimet mbi klipet jodrejtkëndore"</string>
@@ -508,9 +507,8 @@
<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>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Lejo që ky aplikacion të caktojë alarme dhe të planifikojë veprime të tjera. Ky aplikacion mund të përdoret kur ti nuk e përdor telefonin, gjë që mund të përdorë më shumë bateri. Nëse leja është joaktive, ky aplikacion mund të mos funksionojë në mënyrë normale dhe alarmet e tij nuk do të punojnë siç janë planifikuar."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Lejo që ky aplikacion të caktojë alarme dhe të planifikojë veprime të tjera. Ky aplikacion mund të përdoret kur ti nuk e përdor tabletin, gjë që mund të përdorë më shumë bateri. Nëse leja është joaktive, ky aplikacion mund të mos funksionojë në mënyrë normale dhe alarmet e tij nuk do të punojnë siç janë planifikuar."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Lejo që ky aplikacion të caktojë alarme dhe të planifikojë veprime të tjera. Ky aplikacion mund të përdoret kur ti nuk e përdor pajisjen, gjë që mund të përdorë më shumë bateri. Nëse leja është joaktive, ky aplikacion mund të mos funksionojë në mënyrë normale dhe alarmet e tij nuk do të punojnë siç janë planifikuar."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 9830ddb..11adbe5 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -236,7 +236,7 @@
<string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Повежите се на WiFi мрежу"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, отклањање грешака, програмер"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Пречица за извештај о грешкама"</string>
- <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Приказује дугме у менију напајања за прављење извештаја о грешкама"</string>
+ <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Приказује дугме у менију дугмета за укључивање за прављење извештаја о грешкама"</string>
<string name="keep_screen_on" msgid="1187161672348797558">"Не закључавај"</string>
<string name="keep_screen_on_summary" msgid="1510731514101925829">"Екран неће бити у режиму спавања током пуњења"</string>
<string name="bt_hci_snoop_log" msgid="7291287955649081448">"Омогући snoop евид. за Bluetooth HCI"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Приказује границе клипа, маргине итд."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Наметни смер распореда здесна налево"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Намеће смер распореда екрана здесна налево за све локалитете"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Дозволи замагљења прозора"</string>
<string name="force_msaa" msgid="4081288296137775550">"Наметни 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Омогућава 4x MSAA у OpenGL ES 2.0 апликацијама"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Отклони грешке исецања области неправоугаоног облика"</string>
@@ -509,9 +508,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" product="default" msgid="1122213569699233612">"Омогућите овој апликацији да подешава аларме и заказује друге радње. Ова апликација може да се користи када не користите телефон, што може да додатно троши батерију. Ако је ова дозвола искључена, ова апликација можда неће радити нормално и њени аларми неће радити по распореду."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Омогућите овој апликацији да подешава аларме и заказује друге радње. Ова апликација може да се користи када не користите таблет, што може да додатно троши батерију. Ако је ова дозвола искључена, ова апликација можда неће радити нормално и њени аларми неће радити по распореду."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Омогућите овој апликацији да подешава аларме и заказује друге радње. Ова апликација може да се користи када не користите уређај, што може да додатно троши батерију. Ако је ова дозвола искључена, ова апликација можда неће радити нормално и њени аларми неће радити по распореду."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 1208022..f4b92af 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Visa gränser för videoklipp, marginaler m.m."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Tvinga fram RTL-layout"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Tvinga fram RTL-skärmlayout (hö–vä) för alla språk"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Tillåt oskärpa på fönsternivå"</string>
<string name="force_msaa" msgid="4081288296137775550">"Tvinga 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Aktivera 4x MSAA i OpenGL ES 2.0-appar"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Felsök icke-rektangulära urklippsåtgärder"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarm och påminnelser"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Tillåt att alarm och påminnelser ställs in"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm och påminnelser"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Tillåt att den här appen ställer in alarm och schemalägger andra åtgärder. Appen kan användas när du inte använder telefonen, vilket drar mer batteri. Om behörigheten är inaktiverad kanske appen inte fungerar som den ska och dess alarm fungerar inte enligt schemat."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Tillåt att den här appen ställer in alarm och schemalägger andra åtgärder. Appen kan användas när du inte använder surfplattan, vilket drar mer batteri. Om behörigheten är inaktiverad kanske appen inte fungerar som den ska och dess alarm fungerar inte enligt schemat."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Tillåt att den här appen ställer in alarm och schemalägger andra åtgärder. Appen kan användas när du inte använder enheten, vilket drar mer batteri. Om behörigheten är inaktiverad kanske appen inte fungerar som den ska och dess alarm fungerar inte enligt schemat."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Tillåt att den här appen ställer in alarm och schemalägger tidskänsliga åtgärder. Om du tillåter detta kan appen köras i bakgrunden, vilket kan dra mer batteri.\n\nOm behörigheten är inaktiverad fungerar inte befintliga alarm och tidsbaserade händelser som schemalagts av den här appen."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schema, alarm, påminnelse, klocka"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivera"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktivera Stör ej."</string>
@@ -525,7 +522,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Fråga varje gång"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Tills du inaktiverar funktionen"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Nyss"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonens högtalare"</string>
+ <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonhögtalare"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Den här telefonen"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Det gick inte att ansluta. Stäng av enheten och slå på den igen"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ljudenhet med kabelanslutning"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 0b49cf5..2625a414 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Onyesha mipaka ya picha, kingo, nk."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Lazimisha uelekezaji wa muundo wa RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Lazimisha mkao wa skrini uwe wa kulia kwenda kushoto kwa lugha zote"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Ruhusu ukungu wa kiwango cha dirisha"</string>
<string name="force_msaa" msgid="4081288296137775550">"Lazimisha 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Wezesha 4x MSAA katika programu za OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Tatua uendeshaji wa klipu usio mstatili"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Ving\'ora na vikumbusho"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Ruhusu iweke kengele na vikumbusho"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Kengele na vikumbusho"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Ruhusu programu hii iweke kengele na ratiba za vitendo vingine. Programu hii inaweza kutumika wakati hutumii simu yako, hali inayoweza kutumia chaji nyingi ya betri. Ikiwa ruhusa hii itazimwa, huenda programu hii isifanye kazi ipasavyo, na kengele zake hazitafanya kazi kama zilivyoratibiwa."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Ruhusu programu hii iweke kengele na ratiba za vitendo vingine. Programu hii inaweza kutumika wakati hutumii kompyuta yako kibao, hali inayoweza kutumia chaji nyingi ya betri. Ikiwa ruhusa hii itazimwa, huenda programu hii isifanye kazi ipasavyo, na kengele zake hazitafanya kazi kama zilivyoratibiwa."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Ruhusu programu hii iweke kengele na ratiba za vitendo vingine. Programu hii inaweza kutumika wakati hutumii kifaa chako, hali inayoweza kutumia chaji nyingi ya betri. Ikiwa ruhusa hii itazimwa, huenda programu hii isifanye kazi ipasavyo, na kengele zake hazitafanya kazi kama zilivyoratibiwa."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Ruhusu programu hii iweke kengele na ratiba za vitendo vingine vinavyotegemea wakati. Hatua hii inairuhusu programu itumike chinichini, hali inayoweza kutumia chaji nyingi ya betri.\n\nIkiwa ruhusa hii itazimwa, kengele zilizopo na ratiba za vitendo vinavyotegemea wakati zilizowekwa na programu hii hazitafanya kazi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ratiba, kengele, kikumbusho, saa"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Washa"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Washa kipengele cha Usinisumbue"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index a829ab2..612fd70 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"கிளிப் எல்லைகள், ஓரங்கள், மேலும் பலவற்றைக் காட்டு"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL தளவமைப்பின் திசையை வலியுறுத்து"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"எல்லா மொழிகளுக்கும் திரையின் தளவமைப்பு திசையை RTL க்கு மாற்று"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"திரை-நிலை மங்கலை அனுமதி"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA ஐ வலியுறுத்து"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 பயன்பாடுகளில் 4x MSAA ஐ இயக்கு"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"செவ்வகம் அல்லாத கிளிப் செயல்பாடுகளைப் பிழைத்திருத்து"</string>
@@ -509,9 +508,7 @@
<!-- unknown quoting pattern: original -1, translation 1 -->
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"அலாரங்கள் &amp; நினைவூட்டல்களை அமைக்க அனுமதித்தல்"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"அலாரங்கள் & நினைவூட்டல்கள்"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"அலாரங்களை அமைக்கவும் பிற செயல்களைத் திட்டமிடவும் இந்த ஆப்ஸை அனுமதிக்கும். உங்கள் மொபைலை உபயோகிக்காதபோதும் இந்த ஆப்ஸ் பயன்படுத்தப்படக்கூடும், இதனால் பேட்டரி அதிகமாகப் பயன்படுத்தப்படலாம். ஆப்ஸுக்கான அனுமதி முடக்கப்பட்டிருந்தால், அது இயல்பாகச் செயல்படாமல் போகலாம். மேலும் இதன் அலாரங்களும் திட்டமிட்டபடி இயங்காது."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"அலாரங்களை அமைக்கவும் பிற செயல்களைத் திட்டமிடவும் இந்த ஆப்ஸை அனுமதிக்கும். உங்கள் டேப்லெட்டை உபயோகிக்காதபோதும் இந்த ஆப்ஸ் பயன்படுத்தப்படக்கூடும், இதனால் பேட்டரி அதிகமாகப் பயன்படுத்தப்படலாம். ஆப்ஸுக்கான அனுமதி முடக்கப்பட்டிருந்தால், அது இயல்பாகச் செயல்படாமல் போகலாம். மேலும் இதன் அலாரங்களும் திட்டமிட்டபடி இயங்காது."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"அலாரங்களை அமைக்கவும் பிற செயல்களைத் திட்டமிடவும் இந்த ஆப்ஸை அனுமதிக்கும். உங்கள் சாதனத்தை உபயோகிக்காதபோதும் இந்த ஆப்ஸ் பயன்படுத்தப்படக்கூடும், இதனால் பேட்டரி அதிகமாகப் பயன்படுத்தப்படலாம். ஆப்ஸுக்கான அனுமதி முடக்கப்பட்டிருந்தால், அது இயல்பாகச் செயல்படாமல் போகலாம். மேலும் இதன் அலாரங்களும் திட்டமிட்டபடி இயங்காது."</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 83ff620..7f596e3 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -211,7 +211,7 @@
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi కనెక్ట్ అయి ఉన్నప్పుడు, డీబగ్ మోడ్లో ఉంచు"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"ఎర్రర్"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"వైర్లెస్ డీబగ్గింగ్"</string>
- <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"అందుబాటులో వున్న పరికరాలను చూడటానికి, ఉపయోగించడానికి, వైర్లెస్ డీబగ్గింగ్ను ఆన్ చేయండి"</string>
+ <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"అందుబాటులో ఉన్న పరికరాలను చూడటానికి, ఉపయోగించడానికి, వైర్లెస్ డీబగ్గింగ్ను ఆన్ చేయండి"</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR కోడ్తో పరికరాన్ని పెయిర్ చేయండి"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"QR కోడ్ స్కానర్ను ఉపయోగించి కొత్త పరికరాలను పెయిర్ చేయండి"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"పెయిరింగ్ కోడ్తో పరికరాన్ని పెయిర్ చేయండి"</string>
@@ -226,7 +226,7 @@
<string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"పరికరంతో పెయిర్ చేయండి"</string>
<string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi పెయిరింగ్ కోడ్"</string>
<string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"పెయిరింగ్ విఫలమైంది"</string>
- <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"పరికరం అదే నెట్వర్క్కు కనెక్ట్ అయి వుందో లేదో సరి చూసుకోండి."</string>
+ <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"పరికరం అదే నెట్వర్క్కు కనెక్ట్ చేయబడి ఉందని నిర్ధారించుకోండి."</string>
<string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR కోడ్ను స్కాన్ చేయడం ద్వారా Wi-Fiని ఉపయోగించి పరికరాన్ని పెయిర్ చెయ్యండి"</string>
<string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"పరికరం పెయిర్ చేయబడుతోంది…"</string>
<string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"పరికరాన్ని పెయిర్ చేయడం విఫలమైంది. QR కోడ్ తప్పుగా ఉండడం గాని, లేదా పరికరం అదే నెట్వర్క్కు కనెక్ట్ అయి లేకపోవడం గాని జరిగింది."</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"క్లిప్ సరిహద్దులు, అంచులు మొ. చూపు"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL లేఅవుట్ దిశను నిర్బంధం చేయండి"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"అన్ని లొకేల్ల కోసం RTLకి స్క్రీన్ లేఅవుట్ దిశను నిర్భందించు"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"విండో-స్థాయి బ్లర్ అనుమతించు"</string>
<string name="force_msaa" msgid="4081288296137775550">"నిర్భందం 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 యాప్లలో 4x MSAAను ప్రారంభించండి"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"దీర్ఘ చతురస్రం కాని క్లిప్ చర్యలను డీబగ్ చేయండి"</string>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"అలారాలను సెట్ చేయడానికి, ఇతర చర్యలను షెడ్యూల్ చేయడానికి ఈ యాప్ను అనుమతించండి. మీ ఫోన్ను మీరు ఉపయోగించనప్పుడు కూడా ఈ యాప్ ఉపయోగించబడవచ్చు, తద్వారా ఎక్కువ బ్యాటరీని ఉపయోగించవచ్చు. ఈ అనుమతిని ఆఫ్ చేస్తే, ఈ యాప్ సాధారణ రీతిలో పనిచేయకపోవచ్చు, దాని అలారాలు షెడ్యూల్ ప్రకారం పనిచేయవు."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"అలారాలను సెట్ చేయడానికి, ఇతర చర్యలను షెడ్యూల్ చేయడానికి ఈ యాప్ను అనుమతించండి. మీరు మీ టాబ్లెట్ను ఉపయోగించనప్పుడు ఈ యాప్ ఉపయోగించబడవచ్చు, ఇది ఎక్కువ బ్యాటరీని ఉపయోగించవచ్చు. ఈ అనుమతిని ఆఫ్ చేసినట్లైతే, ఈ యాప్ సాధారణంగా పనిచేయకపోవచ్చు అలాగే దాని అలారాలు షెడ్యూల్ ప్రకారం పనిచేయవు."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"అలారాలను సెట్ చేయడానికి, ఇతర చర్యలను షెడ్యూల్ చేయడానికి ఈ యాప్ను అనుమతించండి. మీరు మీ పరికరాన్ని ఉపయోగించనప్పుడు ఈ యాప్ ఉపయోగించబడవచ్చు, ఇది ఎక్కువ బ్యాటరీని ఉపయోగించవచ్చు. ఈ అనుమతిని ఆఫ్ చేసినట్లైతే, ఈ యాప్ సాధారణంగా పనిచేయకపోవచ్చు అలాగే దాని అలారాలు షెడ్యూల్ ప్రకారం పనిచేయవు."</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
@@ -563,7 +561,7 @@
<string name="profile_info_settings_title" msgid="105699672534365099">"ప్రొఫైల్ సమాచారం"</string>
<string name="user_need_lock_message" msgid="4311424336209509301">"మీరు పరిమితం చేయబడిన ప్రొఫైల్ను సృష్టించడానికి ముందు, మీ యాప్లు మరియు వ్యక్తిగత డేటాను రక్షించడానికి స్క్రీన్ లాక్ను సెటప్ చేయాల్సి ఉంటుంది."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"లాక్ను సెట్ చేయి"</string>
- <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>కు మార్చు"</string>
+ <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>కు స్విచ్ చేయి"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"కొత్త యూజర్ను క్రియేట్ చేస్తోంది…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"కొత్త యూజర్ను క్రియేట్ చేయడం విఫలమైంది"</string>
<string name="user_nickname" msgid="262624187455825083">"మారుపేరు"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index f721f15..3851ccb 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"แสดงหน้าปกคลิป ขอบ ฯลฯ"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"บังคับทิศทางการจัดวาง RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"บังคับทิศทางการจัดวางหน้าจอเป็น RTL สำหรับทุกภาษา"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"อนุญาตการเบลอระดับหน้าต่าง"</string>
<string name="force_msaa" msgid="4081288296137775550">"บังคับใช้ 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"เปิดใช้งาน 4x MSAA ในแอปพลิเคชัน OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"แก้ไขการทำงานของคลิปที่ไม่ใช่สี่เหลี่ยม"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"อนุญาตให้แอปตั้งปลุกและกำหนดเวลาการดำเนินการอื่นๆ ระบบอาจใช้แอปนี้แม้คุณจะไม่ได้ใช้โทรศัพท์อยู่ จึงอาจทำให้เปลืองแบตเตอรี่มากขึ้น การปิดสิทธิ์นี้จะทำให้แอปทำงานไม่ปกติและการปลุกไม่ทำงานตามกำหนดเวลา"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"อนุญาตให้แอปตั้งปลุกและกำหนดเวลาการดำเนินการอื่นๆ ระบบอาจใช้แอปนี้แม้คุณจะไม่ได้ใช้แท็บเล็ตอยู่ จึงอาจทำให้เปลืองแบตเตอรี่มากขึ้น การปิดสิทธิ์นี้จะทำให้แอปทำงานไม่ปกติและการปลุกไม่ทำงานตามกำหนดเวลา"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"อนุญาตให้แอปตั้งปลุกและกำหนดเวลาการดำเนินการอื่นๆ ระบบอาจใช้แอปนี้แม้คุณจะไม่ได้ใช้อุปกรณ์อยู่ จึงอาจทำให้เปลืองแบตเตอรี่มากขึ้น การปิดสิทธิ์นี้จะทำให้แอปทำงานไม่ปกติและการปลุกไม่ทำงานตามกำหนดเวลา"</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 57f01a3..a381c35 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Ipakita ang mga hangganan ng clip, margin, atbp."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Ipilit ang RTL na dir. ng layout"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Ipilit ang RTL na direksyon ng screen layout sa lahat ng lokal"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Payagan ang pag-blur sa antas ng window"</string>
<string name="force_msaa" msgid="4081288296137775550">"Puwersahin ang 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Paganahin ang 4x MSAA sa OpenGL ES 2.0 na apps"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"I-debug ang di-parihabang mga clip operation"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Mga alarm at paalala"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Payagan ang pagtakda ng mga alarm at paalala"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Mga alarm at paalala"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Payagan ang app na ito na magtakda ng mga alarm at mag-iskedyul ng iba pang aksyon. Posibleng gamitin ang app na ito kapag hindi mo ginagamit ang iyong telepono, na posibleng gumamit ng mas maraming baterya. Kung naka-off ang pahintulot na ito, posibleng hindi gumana nang normal ang app na ito, at hindi gagana ang mga alarm nito gaya ng nakaiskedyul."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Payagan ang app na ito na magtakda ng mga alarm at mag-iskedyul ng iba pang aksyon. Posibleng gamitin ang app na ito kapag hindi mo ginagamit ang iyong tablet, na posibleng gumamit ng mas maraming baterya. Kung naka-off ang pahintulot na ito, posibleng hindi gumana nang normal ang app na ito, at hindi gagana ang mga alarm nito gaya ng nakaiskedyul."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Payagan ang app na ito na magtakda ng mga alarm at mag-iskedyul ng iba pang aksyon. Posibleng gamitin ang app na ito kapag hindi mo ginagamit ang iyong device, na posibleng gumamit ng mas maraming baterya. Kung naka-off ang pahintulot na ito, posibleng hindi gumana nang normal ang app na ito, at hindi gagana ang mga alarm nito gaya ng nakaiskedyul."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Payagan ang app na ito na magtakda ng mga alarm at mag-iskedyul ng mga pagkilos na may limitadong oras. Papayagan nitong tumakbo ang app sa background, na posibleng gumamit ng mas maraming baterya.\n\nKung naka-off ang pahintulot na ito, hindi gagana ang mga kasalukuyang alarm at event na nakabatay sa oras na naiskedyul ng app na ito."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"iskedyul, alarm, paalala, orasan"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"I-on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"I-on ang Huwag Istorbohin"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 5067990..03efe82 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Klip sınırlarını, kenar boşluklarını vb. göster"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Sağdan sola düzenini zorla"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Tüm yerel ayarlar için sağdan sola ekran düzenini zorlar"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Pencere bulanıklaştırmaya izin ver"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA\'yı zorla"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 uygulamalarda 4x MSAA\'yı etkinleştir"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Dikdörtgen olmayan kırpma işlemlerinde hata ayıkla"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmlar ve hatırlatıcılar"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlanmasına izin ver"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmlar ve hatırlatıcılar"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Bu uygulamanın, alarmlar kurup başka işlemler programlamasına izin verir. Telefonunuzu kullanmadığınız sırada bu uygulama kullanılabilir. Bu da daha fazla pil kullanımına neden olabilir. Bu izin kapatılırsa hem bu uygulama işlevini normal şekilde yerine getirmeyebilir hem de alarmları programladığı gibi çalışmayabilir."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Bu uygulamanın, alarmlar kurup başka işlemler programlamasına izin verir. Tabletinizi kullanmadığınız sırada bu uygulama kullanılabilir. Bu da daha fazla pil kullanımına neden olabilir. Bu izin kapatılırsa hem bu uygulama işlevini normal şekilde yerine getirmeyebilir hem de alarmları programladığı gibi çalışmayabilir."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Bu uygulamanın, alarmlar kurup başka işlemler programlamasına izin verir. Cihazınızı kullanmadığınız sırada bu uygulama kullanılabilir. Bu da daha fazla pil kullanımına neden olabilir. Bu izin kapatılırsa hem bu uygulama işlevini normal şekilde yerine getirmeyebilir hem de alarmları programladığı gibi çalışmayabilir."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu uygulamanın alarmlar kurmasına ve zamana bağlı işlemler programlamasına izin verin. Bu izin, uygulamanın arka planda çalışmasına olanak sağlayarak daha fazla pil harcanmasına neden olabilir.\n\nBu izin verilmezse bu uygulama tarafından programlanmış mevcut alarmlar ve zamana bağlı etkinlikler çalışmaz."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"program, alarm, hatırlatıcı, saat"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aç"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Rahatsız Etmeyin\'i açın"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 061cace..e737c7d 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Показувати межі роликів, поля тощо"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Макет письма справа наліво"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Застосовувати макет письма справа наліво для всіх мов"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Дозволити розмиття вікон"</string>
<string name="force_msaa" msgid="4081288296137775550">"Примус. запустити 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Увімкнути 4x MSAA в програмах OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Налагодити непрямокутну обрізку"</string>
@@ -510,9 +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>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Дозвольте цьому додатку встановлювати будильники й планувати інші події. Цей додаток може працювати, коли ви не користуєтеся телефоном. Через це акумулятор може розряджатися швидше. Якщо цей дозвіл не надано, додаток не зможе працювати належно й будильники не спрацьовуватимуть за графіком."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Дозвольте цьому додатку встановлювати будильники й планувати інші події. Цей додаток може працювати, коли ви не користуєтеся планшетом. Через це акумулятор може розряджатися швидше. Якщо цей дозвіл не надано, додаток не зможе працювати належно й будильники не спрацьовуватимуть за графіком."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Дозвольте цьому додатку встановлювати будильники й планувати інші події. Цей додаток може працювати, коли ви не користуєтеся пристроєм. Через це акумулятор може розряджатися швидше. Якщо цей дозвіл не надано, додаток не зможе працювати належно й будильники не спрацьовуватимуть за графіком."</string>
+ <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>
@@ -527,7 +524,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Запитувати щоразу"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Доки не вимкнути"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Щойно"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Динамік телефона"</string>
+ <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Динамік"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Цей телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Не вдається підключитися. Перезавантажте пристрій."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Дротовий аудіопристрій"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 6eb3c40..45e9f4f 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"کلپ باؤنڈز، حاشیے وغیرہ دکھائیں"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL لے آؤٹ سمت زبردستی نافذ کریں"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"سبھی زبانوں کیلئے اسکرین لے آؤٹ کی سمت کو RTL پر مجبور کریں"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"ونڈو کی سطح پر دھندلاپن کی اجازت دیں"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA زبردستی نافذ کریں"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ایپس میں 4x MSAA فعال کریں"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"غیر مستطیل نما کلپ آپریشنز ڈیبگ کریں"</string>
@@ -508,9 +507,8 @@
<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" product="default" msgid="1122213569699233612">"اس ایپ کو الارمز سیٹ کرنے اور دیگر کارروائیوں کو شیڈول کرنے کی اجازت دیں۔ اس ایپ کا استعمال اس وقت کیا جا سکتا ہے جب آپ اپنا آلہ استعمال نہ کر رہے ہوں جس میں زیادہ بیٹری کا استعمال ہو سکتا ہے۔ اجازت غیر فعال ہونے کی صورت میں ہو سکتا ہے یہ ایپ عام طور پر کام نہ کرے اور اس کے الارمز شیڈول کے مطابق کام نہیں کریں گے۔"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"اس ایپ کو الارمز سیٹ کرنے اور دیگر کارروائیوں کو شیڈول کرنے کی اجازت دیں۔ اس ایپ کا استعمال اس وقت کیا جا سکتا ہے جب آپ اپنا آلہ استعمال نہ کر رہے ہوں جس میں زیادہ بیٹری کا استعمال ہو سکتا ہے۔ اجازت غیر فعال ہونے کی صورت میں ہو سکتا ہے یہ ایپ عام طور پر کام نہ کرے اور اس کے الارمز شیڈول کے مطابق کام نہیں کریں گے۔"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"اس ایپ کو الارمز سیٹ کرنے اور دیگر کارروائیوں کو شیڈول کرنے کی اجازت دیں۔ اس ایپ کا استعمال اس وقت کیا جا سکتا ہے جب آپ اپنا آلہ استعمال نہ کر رہے ہوں جس میں زیادہ بیٹری کا استعمال ہو سکتا ہے۔ اجازت غیر فعال ہونے کی صورت میں ہو سکتا ہے یہ ایپ عام طور پر کام نہ کرے اور اس کے الارمز شیڈول کے مطابق کام نہیں کریں گے۔"</string>
+ <!-- no translation found for alarms_and_reminders_footer_title (6302587438389079695) -->
+ <skip />
<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>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index ad1a917..96b8853 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -179,7 +179,7 @@
<string name="tts_status_checking" msgid="8026559918948285013">"Tekshirilmoqda…"</string>
<string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> sozlamalari"</string>
<string name="tts_engine_settings_button" msgid="477155276199968948">"Mexanizm sozlamalarini ishga tushirish"</string>
- <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"Standart tizim"</string>
+ <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"Asosiy vosita"</string>
<string name="tts_general_section_title" msgid="8919671529502364567">"Umumiy"</string>
<string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"Standart ohang"</string>
<string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"Matnni o‘qish ohangini standart holatga qaytarish."</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Klip, maydon va h.k. chegaralarini ko‘rsatish"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"O‘ngdan chapga qarab yozish"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Barcha tillarda o‘ngdan chapga qarab yozish"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Oyna xiralashga ruxsat"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAAni yoqish"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ilovasidan 4x MSAAni yoqish"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"To‘g‘ri burchakli bo‘lmagan kesishma amallarini tuzatish"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Signal va eslatmalar"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Signal va eslatmalarni sozlashga ruxsat berish"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signal va eslatmalar"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Bu ilovaga signal oʻrnatish va boshqa amallarni rejalashtirishga ruxsat berish Bu ilova telefon qoʻlingizda emasligida ham ishlaydi va batareya quvvatini koʻproq sarflaydi. Agar ruxsat berilmasa, bu ilova odatiy ishlaydi va uning signallari rejalashtirilmaydi."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Bu ilovaga signal oʻrnatish va boshqa amallarni rejalashtirishga ruxsat berish Bu ilova planshet qoʻlingizda emasligida ham ishlaydi va batareya quvvatini koʻproq sarflaydi. Agar ruxsat berilmasa, bu ilova odatiy ishlaydi va uning signallari rejalashtirilmaydi."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Bu ilovaga signal oʻrnatish va boshqa amallarni rejalashtirishga ruxsat berish Bu ilova qurilma qoʻlingizda emasligida ham ishlaydi va batareya quvvatini koʻproq sarflaydi. Agar ruxsat berilmasa, bu ilova odatiy ishlaydi va uning signallari rejalashtirilmaydi."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu ilovaga signal oʻrnatish va vaqtga asoslangan amallarni rejalashtirishga ruxsat berish. Bunda ilovaga orqa fonda ishlashiga imkon beriladi, shu sababli batareya ortiqcha sarflanishi mumkin.\n\nAgar bu ruxsat oʻchirilsa, ushbu ilova tomonidan rejalashtirilgan mavjud signallar va vaqtga asoslangan tadbirlar ishlamaydi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"reja, signal, eslatma, soat"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Yoqish"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Bezovta qilinmasin rejimini yoqing"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 2c4e97f..4509430 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -150,7 +150,7 @@
<string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"Chia sẻ Internet"</string>
<string name="tether_settings_title_all" msgid="8910259483383010470">"Chia sẻ Internet và điểm phát sóng di động"</string>
<string name="managed_user_title" msgid="449081789742645723">"Tất cả ứng dụng làm việc"</string>
- <string name="user_guest" msgid="6939192779649870792">"Khách"</string>
+ <string name="user_guest" msgid="6939192779649870792">"Chế độ khách"</string>
<string name="unknown" msgid="3544487229740637809">"Không xác định"</string>
<string name="running_process_item_user_label" msgid="3988506293099805796">"Người dùng: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="3631650616557252926">"Đã đặt một số ứng dụng chạy mặc định"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Hiện viền của đoạn video, lề, v.v.."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Buộc hướng bố cục phải sang trái"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Buộc hướng bố cục màn hình phải sang trái cho tất cả ngôn ngữ"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Cho phép làm mờ cửa sổ"</string>
<string name="force_msaa" msgid="4081288296137775550">"Bắt buộc 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Bật 4x MSAA trong ứng dụng OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Gỡ lỗi hoạt động của clip không phải là hình chữ nhật"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Chuông báo và lời nhắc"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Cho phép đặt chuông báo và lời nhắc"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Chuông báo và lời nhắc"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Cho phép ứng dụng này đặt chuông báo và lên lịch thực hiện các thao tác khác. Ứng dụng này có thể được sử dụng khi bạn đang không dùng điện thoại. Việc này có thể làm tiêu hao nhiều pin hơn. Nếu quyền này tắt, ứng dụng có thể hoạt động không bình thường và các chuông báo của ứng dụng sẽ không hoạt động đúng như theo lịch."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Cho phép ứng dụng này đặt chuông báo và lên lịch thực hiện các thao tác khác. Ứng dụng này có thể được sử dụng khi bạn đang không dùng máy tính bảng. Việc này có thể làm tiêu hao nhiều pin hơn. Nếu quyền này tắt, ứng dụng có thể hoạt động không bình thường và các chuông báo của ứng dụng sẽ không hoạt động đúng như theo lịch."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Cho phép ứng dụng này đặt chuông báo và lên lịch thực hiện các thao tác khác. Ứng dụng này có thể được sử dụng khi bạn đang không dùng thiết bị. Việc này có thể làm tiêu hao nhiều pin hơn. Nếu quyền này tắt, ứng dụng có thể hoạt động không bình thường và các chuông báo của ứng dụng sẽ không hoạt động đúng như theo lịch."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Cho phép ứng dụng này đặt chuông báo và lên lịch các hành động cần chính xác về thời gian. Tùy chọn này cho phép ứng dụng chạy ở chế độ nền và có thể làm tiêu hao nhiều pin.\n\nNếu không cấp quyền này, các chuông báo và sự kiện theo thời gian do ứng dụng này lên lịch sẽ không hoạt động."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"lịch biểu, chuông báo, lời nhắc, đồng hồ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Bật"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Bật chế độ Không làm phiền"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index d0cbcd4..3e6b3c2 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"显示剪辑边界、边距等。"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"强制使用从右到左的布局方向"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"强制将所有语言区域的屏幕布局方向改为从右到左"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"允许窗口级模糊处理"</string>
<string name="force_msaa" msgid="4081288296137775550">"强制启用 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"在 OpenGL ES 2.0 应用中启用 4x MSAA"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"调试非矩形剪裁操作"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"允许该应用设置闹钟及安排其他操作的执行时间。该应用可能会在您未使用手机时运行,以致手机的电源消耗更快。如果您关闭此权限,该应用可能无法正常运行,已设置的闹钟也无法在排定的时间响起。"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"允许该应用设置闹钟及安排其他操作的执行时间。该应用可能会在您未使用平板电脑时运行,以致平板电脑的电源消耗更快。如果您关闭此权限,该应用可能无法正常运行,已设置的闹钟也无法在排定的时间响起。"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"允许该应用设置闹钟及安排其他操作的执行时间。该应用可能会在您未使用设备时运行,以致设备电源消耗更快。如果您关闭此权限,该应用可能无法正常运行,已设置的闹钟也无法在排定的时间响起。"</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>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 734a9a5..42d95b7 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"顯示剪輯範圍、邊界等"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"強制使用從右至左的版面配置方向"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"強制將所有語言代碼的畫面配置方向改為從右至左"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"允許視窗層級模糊處理"</string>
<string name="force_msaa" msgid="4081288296137775550">"強制 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"在 OpenGL ES 2.0 應用程式中啟用 4x MSAA"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"對非矩形裁剪操作進行偵錯"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"允許此應用程式設定鬧鐘並安排其他操作。此應用程式可能會在您未使用手機時執行,裝置或會較耗電。如果關閉此權限,此應用程式可能無法正常運作,已設定的鬧鐘亦不會在預定的時間響起。"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"允許此應用程式設定鬧鐘並安排其他操作。此應用程式可能會在您未使用平板電腦時執行,裝置或會較耗電。如果關閉此權限,此應用程式可能無法正常運作,已設定的鬧鐘亦不會在預定的時間響起。"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"允許此應用程式設定鬧鐘並安排其他操作。此應用程式可能會在您未使用裝置時執行,裝置或會較耗電。如果關閉此權限,此應用程式可能無法正常運作,已設定的鬧鐘亦不會在預定的時間響起。"</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 17b0a92..20fa187 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -211,7 +211,7 @@
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"連上 Wi-Fi 時啟用偵錯模式"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"錯誤"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"無線偵錯"</string>
- <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"如要查看並使用可用的裝置,請開啟無線偵錯"</string>
+ <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"如要查看並使用可用的裝置,請開啟無線偵錯功能"</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR 圖碼配對裝置"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"使用 QR 圖碼掃描器配對新裝置"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"使用配對碼配對裝置"</string>
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"顯示剪輯範圍、邊界等"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"強制使用從右至左版面配置方向"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"強制將所有語言代碼的畫面配置方向改為從右至左"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"允許視窗層級模糊處理"</string>
<string name="force_msaa" msgid="4081288296137775550">"強制 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"在 OpenGL ES 2.0 應用程式中啟用 4x MSAA"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"針對非矩形裁剪操作進行偵錯"</string>
@@ -508,9 +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" product="default" msgid="1122213569699233612">"允許這個應用程式設定鬧鐘及安排其他操作的執行時間。這個應用程式可能會在你未使用手機時執行,手機也許會比較耗電。如果關閉這項權限,這個應用程式可能無法正常運作,已設定的鬧鐘也不會在排定的時間響起。"</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"允許這個應用程式設定鬧鐘及安排其他操作的執行時間。這個應用程式可能會在你未使用平板電腦時執行,平板電腦也許會比較耗電。如果關閉這項權限,這個應用程式可能無法正常運作,已設定的鬧鐘也不會在排定的時間響起。"</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"允許這個應用程式設定鬧鐘及安排其他操作的執行時間。這個應用程式可能會在你未使用裝置時執行,裝置也許會比較耗電。如果關閉這項權限,這個應用程式可能無法正常運作,已設定的鬧鐘也不會在排定的時間響起。"</string>
+ <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>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 3236fd04..f49d3cc9 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -353,8 +353,7 @@
<string name="debug_layout_summary" msgid="8825829038287321978">"Bonisa imikhawulo, imiphetho, njll, yesiqeshana."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Phoqelela isikhombisi-ndlela sesakhiwo se-RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Phoqelela isikhombisi-ndlela sesikrini ku-RTL kuzo zonke izifunda"</string>
- <!-- no translation found for window_blurs (6831008984828425106) -->
- <skip />
+ <string name="window_blurs" msgid="6831008984828425106">"Vumela ukufiphala kweleveli yewindi"</string>
<string name="force_msaa" msgid="4081288296137775550">"Phoqelela i-4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Nika amandla i-4x MSAA ezinhlelweni zokusebenza ze-OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Susa iphutha ekusebenzeniokungekhona unxantathu kwesiqeshana"</string>
@@ -508,9 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Ama-alamu nezikhumbuzi"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Vumela ukusetha ama-alamu nezikhumbuzi"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ama-alamu nezikhumbuzi"</string>
- <string name="alarms_and_reminders_footer_title" product="default" msgid="1122213569699233612">"Vumela le app isethe ama-alamu futhi ishejule nezinye izinyathelo. Le app ingasetshenziswa uma ungasebenzisi ifoni yakho, okungasebenzisa ibhethri eliningi. Uma le mvume ivaliwe, le app ingahle ingasebenzi ngokuvamile, futhi ama-alamu ayo ngeke asebenze njengokuhleliwe."</string>
- <string name="alarms_and_reminders_footer_title" product="tablet" msgid="4596201244991057839">"Vumela le app isethe ama-alamu futhi ishejule nezinye izinyathelo. Le app ingasetshenziswa uma ungasebenzisi ithebulethi yakho, okungasebenzisa ibhethri eliningi. Uma le mvume ivaliwe, le app ingahle ingasebenzi ngokuvamile, futhi ama-alamu ayo ngeke asebenze njengokuhleliwe."</string>
- <string name="alarms_and_reminders_footer_title" product="device" msgid="349578867821273761">"Vumela le app isethe ama-alamu futhi ishejule nezinye izinyathelo. Le app ingasetshenziswa uma ungasebenzisi idivayisi yakho, okungasebenzisa ibhethri eliningi. Uma le mvume ivaliwe, le app ingahle ingasebenzi ngokuvamile, futhi ama-alamu ayo ngeke asebenze njengokuhleliwe."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Vumela le app isethe ama-alamu futhi ushejule izenzo zesikhathi esizwelayo. Lokhu kuvumela i-app iqhubeke ngemuva okungasebenzisa ibhethri lakho eliningi.\n\nUma le mvume ivaliwe, ama-alamu asele nemicimbi esekelwe esikhathini ehlelwe yile app ngeke kusebenze."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ishejuli, i-alamu, isikhumbuzi, iwashi"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Vula"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Vula ukungaphazamisi"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 4caced6..603d093 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -886,7 +886,7 @@
<!-- UI debug setting: force right to left layout summary [CHAR LIMIT=100] -->
<string name="force_rtl_layout_all_locales_summary">Force screen layout direction to RTL for all locales</string>
- <!-- UI debug setting: enable or disable window blurs [CHAR LIMIT=25] -->
+ <!-- UI debug setting: enable or disable window blurs [CHAR LIMIT=50] -->
<string name="window_blurs">Allow window-level blurs</string>
<!-- UI debug setting: force anti-aliasing to render apps [CHAR LIMIT=25] -->
@@ -1287,25 +1287,10 @@
<!-- Title for the setting screen for controlling apps that can schedule alarms [CHAR LIMIT=30] -->
<string name="alarms_and_reminders_title">Alarms & reminders</string>
<!-- Description that appears below the alarms_and_reminders switch [CHAR LIMIT=NONE] -->
- <string name="alarms_and_reminders_footer_title" product="default">
- Allow this app to set alarms and schedule other actions.
- This app may be used when you\u2019re not using your phone, which may use more battery.
- If this permission is off, this app may not function normally,
- and its alarms won\u2019t work as scheduled.
- </string>
- <!-- Description that appears below the alarms_and_reminders switch [CHAR LIMIT=NONE] -->
- <string name="alarms_and_reminders_footer_title" product="tablet">
- Allow this app to set alarms and schedule other actions.
- This app may be used when you\u2019re not using your tablet, which may use more battery.
- If this permission is off, this app may not function normally,
- and its alarms won\u2019t work as scheduled.
- </string>
- <!-- Description that appears below the alarms_and_reminders switch [CHAR LIMIT=NONE] -->
- <string name="alarms_and_reminders_footer_title" product="device">
- Allow this app to set alarms and schedule other actions.
- This app may be used when you\u2019re not using your device, which may use more battery.
- If this permission is off, this app may not function normally,
- and its alarms won\u2019t work as scheduled.
+ <string name="alarms_and_reminders_footer_title">
+ Allow this app to set alarms and schedule time-sensitive actions.
+ This lets the app run in the background, which may use more battery.\n\nIf this permission
+ is off, existing alarms and time-based events scheduled by this app won\u2019t work.
</string>
<!-- Keywords for setting screen for controlling apps that can schedule alarms [CHAR LIMIT=100] -->
<string name="keywords_alarms_and_reminders">schedule, alarm, reminder, clock</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncher.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncher.java
index 78a42be..849c3d9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncher.java
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncher.java
@@ -18,6 +18,7 @@
import static java.util.Objects.requireNonNull;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -42,9 +43,10 @@
requireNonNull(enforcedAdmin, "enforcedAdmin cannot be null");
// The "Learn more" button appears only if the restriction is enforced by an admin in the
- // same profile group. Otherwise the admin package and its policies are not accessible to
- // the current user.
- if (isSameProfileGroup(context, enforcementAdminUserId)) {
+ // same profile group or by the device owner. Otherwise the admin package and its policies
+ // are not accessible to the current user.
+ if (isSameProfileGroup(context, enforcementAdminUserId)
+ || isEnforcedByDeviceOwnerOnSystemUserMode(context, enforcementAdminUserId)) {
setLearnMoreButton(() -> showAdminPolicies(context, enforcedAdmin));
}
}
@@ -90,6 +92,15 @@
return um.isSameProfileGroup(enforcementAdminUserId, um.getUserHandle());
}
+ private boolean isEnforcedByDeviceOwnerOnSystemUserMode(
+ Context context, int enforcementAdminUserId) {
+ if (enforcementAdminUserId != UserHandle.USER_SYSTEM) {
+ return false;
+ }
+ DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ return enforcementAdminUserId == dpm.getDeviceOwnerUserId();
+ }
+
/**
* Shows the help page using the given {@code url}.
*/
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncherTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncherTest.java
index 7014da0..62582d7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncherTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncherTest.java
@@ -31,6 +31,7 @@
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -62,6 +63,9 @@
private Context mContext;
@Mock
+ private DevicePolicyManager mDevicePolicyManager;
+
+ @Mock
private UserManager mUserManager;
@Spy
@@ -77,6 +81,7 @@
public void setUp() {
when(mContext.getUserId()).thenReturn(CONTEXT_USER_ID);
when(mUserManager.getUserHandle()).thenReturn(CONTEXT_USER_ID);
+ when(mContext.getSystemService(DevicePolicyManager.class)).thenReturn(mDevicePolicyManager);
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
}
@@ -95,8 +100,9 @@
}
@Test
- public void testSetupLearnMoreButtonToShowAdminPolicies_differentProfileGroup() {
+ public void testSetupLearnMoreButtonToShowAdminPolicies_differentProfileGroup_noDeviceOwner() {
mockDifferentProfileGroup();
+ mockEnforcementAdminIsNotDeviceOwner();
mLauncher.setupLearnMoreButtonToShowAdminPolicies(mContext, ENFORCEMENT_ADMIN_USER_ID,
ENFORCED_ADMIN);
@@ -105,8 +111,34 @@
}
@Test
- public void testSetupLearnMoreButtonToShowAdminPolicies_sameProfileGroup_noComponent() {
+ public void testSetupLearnMoreButtonToShowAdminPolicies_differentGroup_noSystemDeviceOwner() {
+ mockDifferentProfileGroup();
+ mockDeviceOwner(ENFORCEMENT_ADMIN_USER_ID);
+
+ mLauncher.setupLearnMoreButtonToShowAdminPolicies(mContext, ENFORCEMENT_ADMIN_USER_ID,
+ ENFORCED_ADMIN);
+
+ verify(mLauncher, never()).setLearnMoreButton(any());
+ }
+
+ @Test
+ public void testSetupLearnMoreButtonToShowAdminPolicies_differentGroup_systemDeviceOwner() {
+ mockDifferentProfileGroup();
+ mockDeviceOwner(UserHandle.USER_SYSTEM);
+
+ mLauncher.setupLearnMoreButtonToShowAdminPolicies(mContext, UserHandle.USER_SYSTEM,
+ ENFORCED_ADMIN_WITHOUT_COMPONENT);
+ tapLearnMore();
+
+ verify(mLauncher, never()).launchShowAdminPolicies(any(), any(), any());
+ verify(mLauncher).launchShowAdminSettings(mContext);
+ verifyFinishSelf();
+ }
+
+ @Test
+ public void testSetupLearnMoreButtonToShowAdminPolicies_sameProfileGroup_noDeviceOwner() {
mockSameProfileGroup();
+ mockEnforcementAdminIsNotDeviceOwner();
mLauncher.setupLearnMoreButtonToShowAdminPolicies(mContext, ENFORCEMENT_ADMIN_USER_ID,
ENFORCED_ADMIN_WITHOUT_COMPONENT);
@@ -118,8 +150,23 @@
}
@Test
- public void testSetupLearnMoreButtonToShowAdminPolicies_sameProfileGroup_withComponent() {
+ public void testSetupLearnMoreButtonToShowAdminPolicies_sameProfileGroup_noSystemDeviceOwner() {
mockSameProfileGroup();
+ mockDeviceOwner(ENFORCEMENT_ADMIN_USER_ID);
+
+ mLauncher.setupLearnMoreButtonToShowAdminPolicies(mContext, ENFORCEMENT_ADMIN_USER_ID,
+ ENFORCED_ADMIN_WITHOUT_COMPONENT);
+ tapLearnMore();
+
+ verify(mLauncher, never()).launchShowAdminPolicies(any(), any(), any());
+ verify(mLauncher).launchShowAdminSettings(mContext);
+ verifyFinishSelf();
+ }
+
+ @Test
+ public void testSetupLearnMoreButtonToShowAdminPolicies_showsLearnMoreButton_withComponent() {
+ mockSameProfileGroup();
+ mockEnforcementAdminIsNotDeviceOwner();
mLauncher.setupLearnMoreButtonToShowAdminPolicies(mContext, ENFORCEMENT_ADMIN_USER_ID,
ENFORCED_ADMIN);
@@ -164,6 +211,14 @@
.thenReturn(true);
}
+ private void mockEnforcementAdminIsNotDeviceOwner() {
+ when(mDevicePolicyManager.getDeviceOwnerUserId()).thenReturn(ENFORCEMENT_ADMIN_USER_ID + 1);
+ }
+
+ private void mockDeviceOwner(int userId) {
+ when(mDevicePolicyManager.getDeviceOwnerUserId()).thenReturn(userId);
+ }
+
private void tapLearnMore() {
verify(mLauncher).setLearnMoreButton(mLearnMoreActionCaptor.capture());
mLearnMoreActionCaptor.getValue().run();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
index f197cbb..89b0fe7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
@@ -18,8 +18,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.when;
-
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
@@ -57,20 +55,6 @@
}
@Test
- public void isAnimating_lottieAnimationViewIsNotAnimating_shouldReturnFalse() {
- when(mAnimationView.isAnimating()).thenReturn(false);
-
- assertThat(mPreference.isAnimating()).isFalse();
- }
-
- @Test
- public void isAnimating_lottieAnimationViewIsAnimating_shouldReturnTrue() {
- when(mAnimationView.isAnimating()).thenReturn(true);
-
- assertThat(mPreference.isAnimating()).isTrue();
- }
-
- @Test
public void setMiddleGroundView_middleGroundView_shouldVisible() {
final View view = new View(mContext);
final FrameLayout layout = new FrameLayout(mContext);
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index c9c3db8..eb81961 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -75,5 +75,6 @@
Settings.Global.USER_DISABLED_HDR_FORMATS,
Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
Settings.Global.DEVICE_CONFIG_SYNC_DISABLED,
+ Settings.Global.POWER_BUTTON_LONG_PRESS,
};
}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index f538875..3297937 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -587,7 +587,6 @@
Settings.Global.RADIO_BUG_SYSTEM_ERROR_COUNT_THRESHOLD,
Settings.Global.ENABLED_SUBSCRIPTION_FOR_SLOT,
Settings.Global.MODEM_STACK_ENABLED_FOR_SLOT,
- Settings.Global.POWER_BUTTON_LONG_PRESS,
Settings.Global.POWER_BUTTON_VERY_LONG_PRESS,
Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, // Temporary for R beta
Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index bcb21d1..959b5ca 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -526,6 +526,9 @@
<!-- Permission required for CTS test - FontManagerTest -->
<uses-permission android:name="android.permission.UPDATE_FONTS" />
+ <!-- Permission required for Launcher testing - DigitalWellbeingToastTest -->
+ <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"/>
+
<!-- Permission required for hotword detection service CTS tests -->
<uses-permission android:name="android.permission.MANAGE_HOTWORD_DETECTION" />
<uses-permission android:name="android.permission.BIND_HOTWORD_DETECTION_SERVICE" />
diff --git a/packages/Shell/res/values-az/strings.xml b/packages/Shell/res/values-az/strings.xml
index 1522f3f..15853c2 100644
--- a/packages/Shell/res/values-az/strings.xml
+++ b/packages/Shell/res/values-az/strings.xml
@@ -29,7 +29,7 @@
<string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"baq hesabatınızı skrinşot olmadan paylaşmaq üçün tıklayın, skrinşotun tamamlanması üçün isə gözləyin"</string>
<string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"baq hesabatınızı skrinşot olmadan paylaşmaq üçün tıklayın, skrinşotun tamamlanması üçün isə gözləyin"</string>
<string name="bugreport_confirm" msgid="5917407234515812495">"Baq hesabatları sistemin müxtəlif jurnal fayllarından həssas təyin etdiyiniz data (tətbiq istifadəsi və məkan datası kimi) içərir. Baq raportlarını yalnız inandığınız tətbiq və adamlarla paylaşın."</string>
- <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Daha göstərməyin"</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Göstərilməsin"</string>
<string name="bugreport_storage_title" msgid="5332488144740527109">"Baq hesabatları"</string>
<string name="bugreport_unreadable_text" msgid="586517851044535486">"Baq hesabat faylı oxunmur"</string>
<string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Zip faylı üçün baq hesabat detalları əlavə edilmədi"</string>
diff --git a/packages/Shell/res/values-pa/strings.xml b/packages/Shell/res/values-pa/strings.xml
index d0c2905..daeac3c 100644
--- a/packages/Shell/res/values-pa/strings.xml
+++ b/packages/Shell/res/values-pa/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="3701846017049540910">"ਸ਼ੈਲ"</string>
+ <string name="app_label" msgid="3701846017049540910">"ਸ਼ੈੱਲ"</string>
<string name="bugreport_notification_channel" msgid="2574150205913861141">"ਬੱਗ ਰਿਪੋਰਟਾਂ"</string>
<string name="bugreport_in_progress_title" msgid="4311705936714972757">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਸਿਰਜੀ ਜਾ ਰਹੀ ਹੈ"</string>
<string name="bugreport_finished_title" msgid="4429132808670114081">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਕੈਪਚਰ ਕੀਤੀ ਗਈ"</string>
diff --git a/packages/StatementService/Android.bp b/packages/StatementService/Android.bp
index 32defc8..a0d8ac9 100644
--- a/packages/StatementService/Android.bp
+++ b/packages/StatementService/Android.bp
@@ -22,17 +22,24 @@
android_app {
name: "StatementService",
- defaults: ["platform_app_defaults"],
- srcs: ["src/**/*.java"],
+ // Removed because Errorprone doesn't work with Kotlin, can fix up in the future
+ // defaults: ["platform_app_defaults"],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
optimize: {
proguard_flags_files: ["proguard.flags"],
},
+ target_sdk_version: "29",
platform_apis: true,
privileged: true,
- libs: ["org.apache.http.legacy"],
- uses_libs: ["org.apache.http.legacy"],
+ certificate: "platform",
static_libs: [
- "libprotobuf-java-nano",
- "volley",
+ "androidx.appcompat_appcompat",
+ "androidx.collection_collection-ktx",
+ "androidx.work_work-runtime",
+ "androidx.work_work-runtime-ktx",
+ "kotlinx-coroutines-android",
],
}
diff --git a/packages/StatementService/AndroidManifest.xml b/packages/StatementService/AndroidManifest.xml
index e0abd50..42cd143 100644
--- a/packages/StatementService/AndroidManifest.xml
+++ b/packages/StatementService/AndroidManifest.xml
@@ -14,41 +14,62 @@
limitations under the License.
-->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.statementservice"
- android:versionCode="1"
- android:versionName="1.0">
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.android.statementservice"
+ android:versionCode="1"
+ android:versionName="1.0">
- <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.DOMAIN_VERIFICATION_AGENT"/>
<uses-permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
+ <uses-permission android:name="android.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION"/>
<application
- android:label="@string/service_name"
- android:allowBackup="false">
- <uses-library android:name="org.apache.http.legacy" />
- <service
- android:name=".DirectStatementService"
- android:exported="false">
- <intent-filter>
- <category android:name="android.intent.category.DEFAULT"/>
- <action android:name="com.android.statementservice.aosp.service.CHECK_ACTION"/>
- </intent-filter>
- </service>
+ android:label="@string/service_name"
+ android:allowBackup="false"
+ android:name=".StatementServiceApplication"
+ >
<receiver
- android:name=".IntentFilterVerificationReceiver"
- android:permission="android.permission.BIND_INTENT_FILTER_VERIFIER"
- android:exported="true">
- <!-- Set the priority 1 so newer implementation can have higher priority. -->
- <intent-filter
- android:priority="1">
+ android:name=".domain.BootCompletedReceiver"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED"/>
+ </intent-filter>
+ </receiver>
+
+ <receiver
+ android:name=".domain.DomainVerificationReceiverV1"
+ android:permission="android.permission.BIND_INTENT_FILTER_VERIFIER"
+ android:exported="true"
+ >
+ <intent-filter android:priority="1">
<action android:name="android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION"/>
<data android:mimeType="application/vnd.android.package-archive"/>
</intent-filter>
</receiver>
+ <!--
+ v2 receiver remains disabled assuming the device ships its own updated version.
+ If necessary, this can be enabled using shell.
+ -->
+ <receiver
+ android:name=".domain.DomainVerificationReceiverV2"
+ android:permission="android.permission.BIND_DOMAIN_VERIFICATION_AGENT"
+ android:directBootAware="true"
+ android:exported="true"
+ android:enabled="false"
+ >
+ <intent-filter android:priority="1">
+ <action android:name="android.intent.action.DOMAINS_NEED_VERIFICATION"/>
+ </intent-filter>
+ </receiver>
</application>
</manifest>
diff --git a/packages/StatementService/src/com/android/statementservice/DirectStatementService.java b/packages/StatementService/src/com/android/statementservice/DirectStatementService.java
deleted file mode 100644
index 659696e..0000000
--- a/packages/StatementService/src/com/android/statementservice/DirectStatementService.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.statementservice;
-
-import android.app.Service;
-import android.content.Intent;
-import android.net.http.HttpResponseCache;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.ResultReceiver;
-import android.util.Log;
-
-import com.android.statementservice.retriever.AbstractAsset;
-import com.android.statementservice.retriever.AbstractAssetMatcher;
-import com.android.statementservice.retriever.AbstractStatementRetriever;
-import com.android.statementservice.retriever.AbstractStatementRetriever.Result;
-import com.android.statementservice.retriever.AssociationServiceException;
-import com.android.statementservice.retriever.Relation;
-import com.android.statementservice.retriever.Statement;
-
-import org.json.JSONException;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-/**
- * Handles com.android.statementservice.service.CHECK_ALL_ACTION intents.
- */
-public final class DirectStatementService extends Service {
- private static final String TAG = DirectStatementService.class.getSimpleName();
-
- /**
- * Returns true if every asset in {@code SOURCE_ASSET_DESCRIPTORS} is associated with {@code
- * EXTRA_TARGET_ASSET_DESCRIPTOR} for {@code EXTRA_RELATION} relation.
- *
- * <p>Takes parameter {@code EXTRA_RELATION}, {@code SOURCE_ASSET_DESCRIPTORS}, {@code
- * EXTRA_TARGET_ASSET_DESCRIPTOR}, and {@code EXTRA_RESULT_RECEIVER}.
- */
- public static final String CHECK_ALL_ACTION =
- "com.android.statementservice.service.CHECK_ALL_ACTION";
-
- /**
- * Parameter for {@link #CHECK_ALL_ACTION}.
- *
- * <p>A relation string.
- */
- public static final String EXTRA_RELATION =
- "com.android.statementservice.service.RELATION";
-
- /**
- * Parameter for {@link #CHECK_ALL_ACTION}.
- *
- * <p>An array of asset descriptors in JSON.
- */
- public static final String EXTRA_SOURCE_ASSET_DESCRIPTORS =
- "com.android.statementservice.service.SOURCE_ASSET_DESCRIPTORS";
-
- /**
- * Parameter for {@link #CHECK_ALL_ACTION}.
- *
- * <p>An asset descriptor in JSON.
- */
- public static final String EXTRA_TARGET_ASSET_DESCRIPTOR =
- "com.android.statementservice.service.TARGET_ASSET_DESCRIPTOR";
-
- /**
- * Parameter for {@link #CHECK_ALL_ACTION}.
- *
- * <p>A {@code ResultReceiver} instance that will be used to return the result. If the request
- * failed, return {@link #RESULT_FAIL} and an empty {@link android.os.Bundle}. Otherwise, return
- * {@link #RESULT_SUCCESS} and a {@link android.os.Bundle} with the result stored in {@link
- * #IS_ASSOCIATED}.
- */
- public static final String EXTRA_RESULT_RECEIVER =
- "com.android.statementservice.service.RESULT_RECEIVER";
-
- /**
- * A boolean bundle entry that stores the result of {@link #CHECK_ALL_ACTION}.
- * This is set only if the service returns with {@code RESULT_SUCCESS}.
- * {@code IS_ASSOCIATED} is true if and only if {@code FAILED_SOURCES} is empty.
- */
- public static final String IS_ASSOCIATED = "is_associated";
-
- /**
- * A String ArrayList bundle entry that stores sources that can't be verified.
- */
- public static final String FAILED_SOURCES = "failed_sources";
-
- /**
- * Returned by the service if the request is successfully processed. The caller should check
- * the {@code IS_ASSOCIATED} field to determine if the association exists or not.
- */
- public static final int RESULT_SUCCESS = 0;
-
- /**
- * Returned by the service if the request failed. The request will fail if, for example, the
- * input is not well formed, or the network is not available.
- */
- public static final int RESULT_FAIL = 1;
-
- private static final long HTTP_CACHE_SIZE_IN_BYTES = 1 * 1024 * 1024; // 1 MBytes
- private static final String CACHE_FILENAME = "request_cache";
-
- private AbstractStatementRetriever mStatementRetriever;
- private Handler mHandler;
- private HandlerThread mThread;
- private HttpResponseCache mHttpResponseCache;
-
- @Override
- public void onCreate() {
- mThread = new HandlerThread("DirectStatementService thread",
- android.os.Process.THREAD_PRIORITY_BACKGROUND);
- mThread.start();
- onCreate(AbstractStatementRetriever.createDirectRetriever(this), mThread.getLooper(),
- getCacheDir());
- }
-
- /**
- * Creates a DirectStatementService with the dependencies passed in for easy testing.
- */
- public void onCreate(AbstractStatementRetriever statementRetriever, Looper looper,
- File cacheDir) {
- super.onCreate();
- mStatementRetriever = statementRetriever;
- mHandler = new Handler(looper);
-
- try {
- File httpCacheDir = new File(cacheDir, CACHE_FILENAME);
- mHttpResponseCache = HttpResponseCache.install(httpCacheDir, HTTP_CACHE_SIZE_IN_BYTES);
- } catch (IOException e) {
- Log.i(TAG, "HTTPS response cache installation failed:" + e);
- }
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- final HttpResponseCache responseCache = mHttpResponseCache;
- mHandler.post(new Runnable() {
- public void run() {
- try {
- if (responseCache != null) {
- responseCache.delete();
- }
- } catch (IOException e) {
- Log.i(TAG, "HTTP(S) response cache deletion failed:" + e);
- }
- Looper.myLooper().quit();
- }
- });
- mHttpResponseCache = null;
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- super.onStartCommand(intent, flags, startId);
-
- if (intent == null) {
- Log.e(TAG, "onStartCommand called with null intent");
- return START_STICKY;
- }
-
- if (intent.getAction().equals(CHECK_ALL_ACTION)) {
-
- Bundle extras = intent.getExtras();
- List<String> sources = extras.getStringArrayList(EXTRA_SOURCE_ASSET_DESCRIPTORS);
- String target = extras.getString(EXTRA_TARGET_ASSET_DESCRIPTOR);
- String relation = extras.getString(EXTRA_RELATION);
- ResultReceiver resultReceiver = extras.getParcelable(EXTRA_RESULT_RECEIVER);
-
- if (resultReceiver == null) {
- Log.e(TAG, " Intent does not have extra " + EXTRA_RESULT_RECEIVER);
- return START_STICKY;
- }
- if (sources == null) {
- Log.e(TAG, " Intent does not have extra " + EXTRA_SOURCE_ASSET_DESCRIPTORS);
- resultReceiver.send(RESULT_FAIL, Bundle.EMPTY);
- return START_STICKY;
- }
- if (target == null) {
- Log.e(TAG, " Intent does not have extra " + EXTRA_TARGET_ASSET_DESCRIPTOR);
- resultReceiver.send(RESULT_FAIL, Bundle.EMPTY);
- return START_STICKY;
- }
- if (relation == null) {
- Log.e(TAG, " Intent does not have extra " + EXTRA_RELATION);
- resultReceiver.send(RESULT_FAIL, Bundle.EMPTY);
- return START_STICKY;
- }
-
- mHandler.post(new ExceptionLoggingFutureTask<Void>(
- new IsAssociatedCallable(sources, target, relation, resultReceiver), TAG));
- } else {
- Log.e(TAG, "onStartCommand called with unsupported action: " + intent.getAction());
- }
- return START_STICKY;
- }
-
- private class IsAssociatedCallable implements Callable<Void> {
-
- private List<String> mSources;
- private String mTarget;
- private String mRelation;
- private ResultReceiver mResultReceiver;
-
- public IsAssociatedCallable(List<String> sources, String target, String relation,
- ResultReceiver resultReceiver) {
- mSources = sources;
- mTarget = target;
- mRelation = relation;
- mResultReceiver = resultReceiver;
- }
-
- private boolean verifyOneSource(AbstractAsset source, AbstractAssetMatcher target,
- Relation relation) throws AssociationServiceException {
- Result statements = mStatementRetriever.retrieveStatements(source);
- for (Statement statement : statements.getStatements()) {
- if (relation.matches(statement.getRelation())
- && target.matches(statement.getTarget())) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public Void call() {
- Bundle result = new Bundle();
- ArrayList<String> failedSources = new ArrayList<String>();
- AbstractAssetMatcher target;
- Relation relation;
- try {
- target = AbstractAssetMatcher.createMatcher(mTarget);
- relation = Relation.create(mRelation);
- } catch (AssociationServiceException | JSONException e) {
- Log.e(TAG, "isAssociatedCallable failed with exception", e);
- mResultReceiver.send(RESULT_FAIL, Bundle.EMPTY);
- return null;
- }
-
- boolean allSourcesVerified = true;
- for (String sourceString : mSources) {
- AbstractAsset source;
- try {
- source = AbstractAsset.create(sourceString);
- } catch (AssociationServiceException e) {
- mResultReceiver.send(RESULT_FAIL, Bundle.EMPTY);
- return null;
- }
-
- try {
- if (!verifyOneSource(source, target, relation)) {
- failedSources.add(source.toJson());
- allSourcesVerified = false;
- }
- } catch (AssociationServiceException e) {
- failedSources.add(source.toJson());
- allSourcesVerified = false;
- }
- }
-
- result.putBoolean(IS_ASSOCIATED, allSourcesVerified);
- result.putStringArrayList(FAILED_SOURCES, failedSources);
- mResultReceiver.send(RESULT_SUCCESS, result);
- return null;
- }
- }
-}
diff --git a/packages/StatementService/src/com/android/statementservice/ExceptionLoggingFutureTask.java b/packages/StatementService/src/com/android/statementservice/ExceptionLoggingFutureTask.java
deleted file mode 100644
index 20c7f97..0000000
--- a/packages/StatementService/src/com/android/statementservice/ExceptionLoggingFutureTask.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.statementservice;
-
-import android.util.Log;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-
-/**
- * {@link FutureTask} that logs unhandled exceptions.
- */
-final class ExceptionLoggingFutureTask<V> extends FutureTask<V> {
-
- private final String mTag;
-
- public ExceptionLoggingFutureTask(Callable<V> callable, String tag) {
- super(callable);
- mTag = tag;
- }
-
- @Override
- protected void done() {
- try {
- get();
- } catch (ExecutionException | InterruptedException e) {
- Log.e(mTag, "Uncaught exception.", e);
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/packages/StatementService/src/com/android/statementservice/IntentFilterVerificationReceiver.java b/packages/StatementService/src/com/android/statementservice/IntentFilterVerificationReceiver.java
deleted file mode 100644
index ba8e7a1..0000000
--- a/packages/StatementService/src/com/android/statementservice/IntentFilterVerificationReceiver.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.statementservice;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Patterns;
-
-import com.android.statementservice.retriever.Utils;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.regex.Pattern;
-
-/**
- * Receives {@link Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION} broadcast and calls
- * {@link DirectStatementService} to verify the request. Calls
- * {@link PackageManager#verifyIntentFilter} to notify {@link PackageManager} the result of the
- * verification.
- *
- * This implementation of the API will send a HTTP request for each host specified in the query.
- * To avoid overwhelming the network at app install time, {@code MAX_HOSTS_PER_REQUEST} limits
- * the maximum number of hosts in a query. If a query contains more than
- * {@code MAX_HOSTS_PER_REQUEST} hosts, it will fail immediately without making any HTTP request
- * and call {@link PackageManager#verifyIntentFilter} with
- * {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}.
- */
-public final class IntentFilterVerificationReceiver extends BroadcastReceiver {
- private static final String TAG = IntentFilterVerificationReceiver.class.getSimpleName();
-
- private static final Integer MAX_HOSTS_PER_REQUEST = 10;
-
- private static final String HANDLE_ALL_URLS_RELATION
- = "delegate_permission/common.handle_all_urls";
-
- private static final String ANDROID_ASSET_FORMAT = "{\"namespace\": \"android_app\", "
- + "\"package_name\": \"%s\", \"sha256_cert_fingerprints\": [\"%s\"]}";
- private static final String WEB_ASSET_FORMAT = "{\"namespace\": \"web\", \"site\": \"%s\"}";
- private static final Pattern ANDROID_PACKAGE_NAME_PATTERN =
- Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*$");
- private static final String TOO_MANY_HOSTS_FORMAT =
- "Request contains %d hosts which is more than the allowed %d.";
-
- private static void sendErrorToPackageManager(PackageManager packageManager,
- int verificationId) {
- packageManager.verifyIntentFilter(verificationId,
- PackageManager.INTENT_FILTER_VERIFICATION_FAILURE,
- Collections.<String>emptyList());
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION.equals(action)) {
- Bundle inputExtras = intent.getExtras();
- if (inputExtras != null) {
- Intent serviceIntent = new Intent(context, DirectStatementService.class);
- serviceIntent.setAction(DirectStatementService.CHECK_ALL_ACTION);
-
- int verificationId = inputExtras.getInt(
- PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_ID);
- String scheme = inputExtras.getString(
- PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_URI_SCHEME);
- String hosts = inputExtras.getString(
- PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_HOSTS);
- String packageName = inputExtras.getString(
- PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_PACKAGE_NAME);
-
- Bundle extras = new Bundle();
- extras.putString(DirectStatementService.EXTRA_RELATION, HANDLE_ALL_URLS_RELATION);
-
- String[] hostList = hosts.split(" ");
- if (hostList.length > MAX_HOSTS_PER_REQUEST) {
- Log.w(TAG, String.format(TOO_MANY_HOSTS_FORMAT,
- hostList.length, MAX_HOSTS_PER_REQUEST));
- sendErrorToPackageManager(context.getPackageManager(), verificationId);
- return;
- }
-
- ArrayList<String> finalHosts = new ArrayList<String>(hostList.length);
- try {
- ArrayList<String> sourceAssets = new ArrayList<String>();
- for (String host : hostList) {
- // "*.example.tld" is validated via https://example.tld
- if (host.startsWith("*.")) {
- host = host.substring(2);
- }
- sourceAssets.add(createWebAssetString(scheme, host));
- finalHosts.add(host);
- }
- extras.putStringArrayList(DirectStatementService.EXTRA_SOURCE_ASSET_DESCRIPTORS,
- sourceAssets);
- } catch (MalformedURLException e) {
- Log.w(TAG, "Error when processing input host: " + e.getMessage());
- sendErrorToPackageManager(context.getPackageManager(), verificationId);
- return;
- }
- try {
- extras.putString(DirectStatementService.EXTRA_TARGET_ASSET_DESCRIPTOR,
- createAndroidAssetString(context, packageName));
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Error when processing input Android package: " + e.getMessage());
- sendErrorToPackageManager(context.getPackageManager(), verificationId);
- return;
- }
- extras.putParcelable(DirectStatementService.EXTRA_RESULT_RECEIVER,
- new IsAssociatedResultReceiver(
- new Handler(), context.getPackageManager(), verificationId));
-
- // Required for CTS: log a few details of the validcation operation to be performed
- logValidationParametersForCTS(verificationId, scheme, finalHosts, packageName);
-
- serviceIntent.putExtras(extras);
- context.startService(serviceIntent);
- }
- } else {
- Log.w(TAG, "Intent action not supported: " + action);
- }
- }
-
- // CTS requirement: logging of the validation parameters in a specific format
- private static final String CTS_LOG_FORMAT =
- "Verifying IntentFilter. verificationId:%d scheme:\"%s\" hosts:\"%s\" package:\"%s\".";
- private void logValidationParametersForCTS(int verificationId, String scheme,
- ArrayList<String> finalHosts, String packageName) {
- String hostString = TextUtils.join(" ", finalHosts.toArray());
- Log.i(TAG, String.format(CTS_LOG_FORMAT, verificationId, scheme, hostString, packageName));
- }
-
- private String createAndroidAssetString(Context context, String packageName)
- throws NameNotFoundException {
- if (!ANDROID_PACKAGE_NAME_PATTERN.matcher(packageName).matches()) {
- throw new NameNotFoundException("Input package name is not valid.");
- }
-
- List<String> certFingerprints =
- Utils.getCertFingerprintsFromPackageManager(packageName, context);
-
- return String.format(ANDROID_ASSET_FORMAT, packageName,
- Utils.joinStrings("\", \"", certFingerprints));
- }
-
- private String createWebAssetString(String scheme, String host) throws MalformedURLException {
- if (!Patterns.DOMAIN_NAME.matcher(host).matches()) {
- throw new MalformedURLException("Input host is not valid.");
- }
- if (!scheme.equals("http") && !scheme.equals("https")) {
- throw new MalformedURLException("Input scheme is not valid.");
- }
-
- return String.format(WEB_ASSET_FORMAT, new URL(scheme, host, "").toString());
- }
-
- /**
- * Receives the result of {@code StatementService.CHECK_ACTION} from
- * {@link DirectStatementService} and passes it back to {@link PackageManager}.
- */
- private static class IsAssociatedResultReceiver extends ResultReceiver {
-
- private final int mVerificationId;
- private final PackageManager mPackageManager;
-
- public IsAssociatedResultReceiver(Handler handler, PackageManager packageManager,
- int verificationId) {
- super(handler);
- mVerificationId = verificationId;
- mPackageManager = packageManager;
- }
-
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == DirectStatementService.RESULT_SUCCESS) {
- if (resultData.getBoolean(DirectStatementService.IS_ASSOCIATED)) {
- mPackageManager.verifyIntentFilter(mVerificationId,
- PackageManager.INTENT_FILTER_VERIFICATION_SUCCESS,
- Collections.<String>emptyList());
- } else {
- mPackageManager.verifyIntentFilter(mVerificationId,
- PackageManager.INTENT_FILTER_VERIFICATION_FAILURE,
- resultData.getStringArrayList(DirectStatementService.FAILED_SOURCES));
- }
- } else {
- sendErrorToPackageManager(mPackageManager, mVerificationId);
- }
- }
- }
-}
diff --git a/packages/StatementService/src/com/android/statementservice/StatementServiceApplication.kt b/packages/StatementService/src/com/android/statementservice/StatementServiceApplication.kt
new file mode 100644
index 0000000..021a514
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/StatementServiceApplication.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice
+
+import android.app.Application
+import android.os.UserManager
+import androidx.work.WorkManager
+import com.android.statementservice.domain.DomainVerificationUtils
+
+class StatementServiceApplication : Application() {
+
+ override fun onCreate() {
+ super.onCreate()
+ val userManager = getSystemService(UserManager::class.java) ?: return
+ if (userManager.isUserUnlocked) {
+ // WorkManager can only schedule when the user data directories are unencrypted (after
+ // the user has entered their lock password.
+ DomainVerificationUtils.schedulePeriodicCheckUnlocked(WorkManager.getInstance(this))
+ }
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/BaseDomainVerificationReceiver.kt b/packages/StatementService/src/com/android/statementservice/domain/BaseDomainVerificationReceiver.kt
new file mode 100644
index 0000000..de41486
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/BaseDomainVerificationReceiver.kt
@@ -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 com.android.statementservice.domain
+
+import android.content.BroadcastReceiver
+import android.util.Log
+import androidx.work.Constraints
+import androidx.work.NetworkType
+
+abstract class BaseDomainVerificationReceiver : BroadcastReceiver() {
+
+ companion object {
+ const val DEBUG = false
+ }
+
+ protected abstract val tag: String
+
+ protected val networkConstraints = Constraints.Builder()
+ .setRequiredNetworkType(NetworkType.CONNECTED)
+ .build()
+
+ protected fun debugLog(block: () -> String) {
+ if (DEBUG) {
+ Log.d(tag, block())
+ }
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/BootCompletedReceiver.kt b/packages/StatementService/src/com/android/statementservice/domain/BootCompletedReceiver.kt
new file mode 100644
index 0000000..7b5da83
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/BootCompletedReceiver.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import androidx.work.Constraints
+import androidx.work.ExistingWorkPolicy
+import androidx.work.NetworkType
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.WorkManager
+import com.android.statementservice.domain.worker.RetryRequestWorker
+
+/**
+ * Handles [Intent.ACTION_BOOT_COMPLETED] to schedule recurring maintenance [WorkManager] tasks and
+ * run a one-time retry request to attempt to verify domains that may have failed or been added
+ * since last device reboot.
+ *
+ * Note that this requires the user to have unlocked the device, since [WorkManager] cannot handle
+ * the encrypted user data directories.
+ */
+class BootCompletedReceiver : BroadcastReceiver() {
+
+ companion object {
+ private const val PACKAGE_BOOT_REQUEST_KEY = "package_boot_request"
+ }
+
+ override fun onReceive(context: Context, intent: Intent) {
+ if (intent.action != Intent.ACTION_BOOT_COMPLETED) return
+ val workManager = WorkManager.getInstance(context)
+ DomainVerificationUtils.schedulePeriodicCheckUnlocked(workManager)
+ workManager.beginUniqueWork(
+ PACKAGE_BOOT_REQUEST_KEY,
+ ExistingWorkPolicy.REPLACE,
+ OneTimeWorkRequestBuilder<RetryRequestWorker>()
+ .setConstraints(
+ Constraints.Builder()
+ .setRequiredNetworkType(NetworkType.CONNECTED)
+ .build()
+ )
+ .build()
+ ).enqueue()
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt
new file mode 100644
index 0000000..0ec8ed3
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import androidx.work.ExistingWorkPolicy
+import androidx.work.WorkManager
+import com.android.statementservice.domain.worker.CollectV1Worker
+import com.android.statementservice.domain.worker.SingleV1RequestWorker
+
+/**
+ * Receiver for V1 API. Separated so that the receiver permission can be declared for only the
+ * v1 and v2 permissions individually, exactly matching the intended usage.
+ */
+class DomainVerificationReceiverV1 : BaseDomainVerificationReceiver() {
+
+ companion object {
+ private const val ENABLE_V1 = true
+ private const val PACKAGE_WORK_PREFIX_V1 = "package_request_v1-"
+ }
+
+ override val tag = DomainVerificationReceiverV1::class.java.simpleName
+
+ override fun onReceive(context: Context, intent: Intent) {
+ when (intent.action) {
+ Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION ->
+ scheduleUnlockedV1(context, intent)
+ else -> debugLog { "Received invalid broadcast: $intent" }
+ }
+ }
+
+ private fun scheduleUnlockedV1(context: Context, intent: Intent) {
+ if (!ENABLE_V1) {
+ return
+ }
+
+ val verificationId =
+ intent.getIntExtra(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_ID, -1)
+ val hosts =
+ (intent.getStringExtra(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_HOSTS) ?: return)
+ .split(" ")
+ val packageName =
+ intent.getStringExtra(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_PACKAGE_NAME)
+ ?: return
+
+ debugLog { "Attempting v1 verification for $packageName" }
+
+ val workRequests = hosts.map {
+ SingleV1RequestWorker.buildRequest(packageName, it) {
+ setConstraints(networkConstraints)
+ }
+ }
+
+ WorkManager.getInstance(context)
+ .beginUniqueWork(
+ "$PACKAGE_WORK_PREFIX_V1$packageName",
+ ExistingWorkPolicy.REPLACE,
+ workRequests
+ )
+ .then(CollectV1Worker.buildRequest(verificationId, packageName))
+ .enqueue()
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV2.kt b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV2.kt
new file mode 100644
index 0000000..24e0f50
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV2.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.verify.domain.DomainVerificationManager
+import android.content.pm.verify.domain.DomainVerificationRequest
+import android.os.UserManager
+import androidx.work.BackoffPolicy
+import androidx.work.ExistingWorkPolicy
+import androidx.work.WorkManager
+import com.android.statementservice.domain.worker.SingleV2RequestWorker
+import com.android.statementservice.utils.component1
+import com.android.statementservice.utils.component2
+import com.android.statementservice.utils.component3
+
+import java.time.Duration
+
+/**
+ * Handles [DomainVerificationRequest]s from the system, which indicates a package on the device
+ * has domains which require verification against a server side assetlinks.json file, allowing the
+ * app to resolve web [Intent]s.
+ *
+ * This will delegate to v1 or v2 depending on the received broadcast and which components are
+ * enabled. See [DomainVerificationManager] for the full API.
+ */
+open class DomainVerificationReceiverV2 : BaseDomainVerificationReceiver() {
+
+ companion object {
+
+ private const val ENABLE_V2 = true
+
+ /**
+ * Toggle to always re-verify packages that this receiver is notified of. This means on
+ * every package change, even previously successful requests are re-sent. Generally only
+ * for debugging.
+ */
+ @Suppress("SimplifyBooleanWithConstants")
+ private const val ALWAYS_VERIFY = false || DEBUG
+
+ private const val PACKAGE_WORK_PREFIX_V2 = "package_request_v2-"
+ }
+
+ override val tag = DomainVerificationReceiverV2::class.java.simpleName
+
+ override fun onReceive(context: Context, intent: Intent) {
+ when (intent.action) {
+ Intent.ACTION_DOMAINS_NEED_VERIFICATION -> {
+ // If the user isn't unlocked yet, the request will be ignored, as WorkManager
+ // cannot schedule workers when the user data directories are encrypted.
+ if (context.getSystemService(UserManager::class.java)?.isUserUnlocked == true) {
+ scheduleUnlockedV2(context, intent)
+ }
+ }
+ else -> debugLog { "Received invalid broadcast: $intent" }
+ }
+ }
+
+ private fun scheduleUnlockedV2(context: Context, intent: Intent) {
+ if (!ENABLE_V2) {
+ return
+ }
+
+ val manager = context.getSystemService(DomainVerificationManager::class.java) ?: return
+ val workManager = WorkManager.getInstance(context)
+
+ val request = intent.getParcelableExtra<DomainVerificationRequest>(
+ DomainVerificationManager.EXTRA_VERIFICATION_REQUEST
+ ) ?: return
+
+ debugLog { "Attempting v2 verification for ${request.packageNames}" }
+
+ request.packageNames.forEach { packageName ->
+ val (domainSetId, _, hostToStateMap) = manager.getDomainVerificationInfo(packageName)
+ ?: return@forEach
+
+ val workRequests = hostToStateMap
+ .filterValues {
+ // TODO(b/159952358): Should we support re-query? There's no good way to
+ // signal to an AOSP implementation from an entity's website about when
+ // to re-query, unless it's just done on each update.
+ // AOSP implementation does not support re-query
+ ALWAYS_VERIFY || VerifyStatus.shouldRetry(it)
+ }
+ .map { (host, _) ->
+ SingleV2RequestWorker.buildRequest(domainSetId, packageName, host) {
+ setConstraints(networkConstraints)
+ setBackoffCriteria(BackoffPolicy.EXPONENTIAL, Duration.ofHours(1))
+ }
+ }
+
+ if (workRequests.isNotEmpty()) {
+ workManager.beginUniqueWork(
+ "$PACKAGE_WORK_PREFIX_V2$packageName",
+ ExistingWorkPolicy.REPLACE, workRequests
+ )
+ .enqueue()
+ }
+ }
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationUtils.kt b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationUtils.kt
new file mode 100644
index 0000000..6944248
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationUtils.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain
+
+import androidx.work.Constraints
+import androidx.work.ExistingPeriodicWorkPolicy
+import androidx.work.NetworkType
+import androidx.work.PeriodicWorkRequestBuilder
+import androidx.work.WorkManager
+import com.android.statementservice.domain.worker.RetryRequestWorker
+import java.time.Duration
+
+object DomainVerificationUtils {
+
+ private const val PERIODIC_SHORT_ID = "retry_short"
+ private const val PERIODIC_SHORT_HOURS = 24L
+ private const val PERIODIC_LONG_ID = "retry_long"
+ private const val PERIODIC_LONG_HOURS = 72L
+
+ /**
+ * In a majority of cases, the initial requests will be enough to verify domains, since they
+ * are also restricted to [NetworkType.CONNECTED], but for cases where they aren't sufficient,
+ * attempts are also made on a periodic basis.
+ *
+ * Once per 24 hours, a check of all packages is done with [NetworkType.CONNECTED]. To avoid
+ * cases where a proxy or other unusual device configuration prevents [WorkManager] from
+ * running, also schedule a 3 day task without constraints which will force the check to run.
+ *
+ * The actual logic may be skipped if a request was previously run successfully or there are no
+ * more domains that need verifying.
+ */
+ fun schedulePeriodicCheckUnlocked(workManager: WorkManager) {
+ workManager.apply {
+ PeriodicWorkRequestBuilder<RetryRequestWorker>(Duration.ofHours(PERIODIC_SHORT_HOURS))
+ .setConstraints(
+ Constraints.Builder()
+ .setRequiredNetworkType(NetworkType.CONNECTED)
+ .setRequiresDeviceIdle(true)
+ .build()
+ )
+ .build()
+ .let {
+ enqueueUniquePeriodicWork(
+ PERIODIC_SHORT_ID,
+ ExistingPeriodicWorkPolicy.KEEP, it
+ )
+ }
+ PeriodicWorkRequestBuilder<RetryRequestWorker>(Duration.ofDays(PERIODIC_LONG_HOURS))
+ .setConstraints(
+ Constraints.Builder()
+ .setRequiresDeviceIdle(true)
+ .build()
+ )
+ .build()
+ .let {
+ enqueueUniquePeriodicWork(
+ PERIODIC_LONG_ID,
+ ExistingPeriodicWorkPolicy.KEEP, it
+ )
+ }
+ }
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/DomainVerifier.kt b/packages/StatementService/src/com/android/statementservice/domain/DomainVerifier.kt
new file mode 100644
index 0000000..29f844f
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/DomainVerifier.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain
+
+import android.content.Context
+import android.content.pm.verify.domain.DomainVerificationManager
+import android.net.Network
+import android.util.Log
+import androidx.collection.LruCache
+import com.android.statementservice.network.retriever.StatementRetriever
+import com.android.statementservice.retriever.AbstractAsset
+import com.android.statementservice.retriever.AbstractAssetMatcher
+import com.android.statementservice.utils.Result
+import com.android.statementservice.utils.StatementUtils
+import com.android.statementservice.utils.component1
+import com.android.statementservice.utils.component2
+import com.android.statementservice.utils.component3
+import java.net.HttpURLConnection
+import java.util.Optional
+import java.util.UUID
+
+private typealias WorkResult = androidx.work.ListenableWorker.Result
+
+class DomainVerifier private constructor(
+ private val appContext: Context,
+ private val manager: DomainVerificationManager
+) {
+ companion object {
+ private val TAG = DomainVerifier::class.java.simpleName
+ private const val DEBUG = false
+
+ private var singleton: DomainVerifier? = null
+
+ fun getInstance(context: Context) = when {
+ singleton != null -> singleton!!
+ else -> synchronized(this) {
+ if (singleton == null) {
+ val appContext = context.applicationContext
+ val manager =
+ appContext.getSystemService(DomainVerificationManager::class.java)!!
+ singleton = DomainVerifier(appContext, manager)
+ }
+ singleton!!
+ }
+ }
+ }
+
+ private val retriever = StatementRetriever()
+
+ private val targetAssetCache = AssetLruCache()
+
+ fun collectHosts(packageNames: Iterable<String>): Iterable<Triple<UUID, String, String>> {
+ return packageNames.mapNotNull { packageName ->
+ val (domainSetId, _, hostToStateMap) = try {
+ manager.getDomainVerificationInfo(packageName)
+ } catch (ignored: Exception) {
+ // Package disappeared, assume it will be rescheduled if the package reappears
+ null
+ } ?: return@mapNotNull null
+
+ val hostsToRetry = hostToStateMap
+ .filterValues(VerifyStatus::shouldRetry)
+ .takeIf { it.isNotEmpty() }
+ ?.map { it.key }
+ ?: return@mapNotNull null
+
+ hostsToRetry.map { Triple(domainSetId, packageName, it) }
+ }
+ .flatten()
+ }
+
+ suspend fun verifyHost(
+ host: String,
+ packageName: String,
+ network: Network? = null
+ ): Pair<WorkResult, VerifyStatus> {
+ val assetMatcher = synchronized(targetAssetCache) { targetAssetCache[packageName] }
+ .takeIf { it!!.isPresent }
+ ?: return WorkResult.failure() to VerifyStatus.FAILURE_PACKAGE_MANAGER
+ return verifyHost(host, assetMatcher.get(), network)
+ }
+
+ private suspend fun verifyHost(
+ host: String,
+ assetMatcher: AbstractAssetMatcher,
+ network: Network? = null
+ ): Pair<WorkResult, VerifyStatus> {
+ var exception: Exception? = null
+ val resultAndStatus = try {
+ val sourceAsset = StatementUtils.createWebAssetString(host)
+ .let(AbstractAsset::create)
+ val result = retriever.retrieve(sourceAsset, network)
+ ?: return WorkResult.success() to VerifyStatus.FAILURE_UNKNOWN
+ when (result.responseCode) {
+ HttpURLConnection.HTTP_MOVED_PERM,
+ HttpURLConnection.HTTP_MOVED_TEMP -> {
+ WorkResult.failure() to VerifyStatus.FAILURE_REDIRECT
+ }
+ else -> {
+ val isVerified = result.statements.any { statement ->
+ (StatementUtils.RELATION.matches(statement.relation) &&
+ assetMatcher.matches(statement.target))
+ }
+
+ if (isVerified) {
+ WorkResult.success() to VerifyStatus.SUCCESS
+ } else {
+ WorkResult.failure() to VerifyStatus.FAILURE_REJECTED_BY_SERVER
+ }
+ }
+ }
+ } catch (e: Exception) {
+ exception = e
+ WorkResult.retry() to VerifyStatus.FAILURE_UNKNOWN
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "Verifying $host: ${resultAndStatus.second}", exception)
+ }
+
+ return resultAndStatus
+ }
+
+ private inner class AssetLruCache : LruCache<String, Optional<AbstractAssetMatcher>>(50) {
+ override fun create(packageName: String) =
+ StatementUtils.getCertFingerprintsFromPackageManager(appContext, packageName)
+ .let { (it as? Result.Success)?.value }
+ ?.let { StatementUtils.createAndroidAsset(packageName, it) }
+ ?.let(AbstractAssetMatcher::createMatcher)
+ .let { Optional.ofNullable(it) }
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/VerifyStatus.kt b/packages/StatementService/src/com/android/statementservice/domain/VerifyStatus.kt
new file mode 100644
index 0000000..2193ec5
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/VerifyStatus.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain
+
+import android.content.pm.verify.domain.DomainVerificationInfo
+import android.content.pm.verify.domain.DomainVerificationManager
+
+/**
+ * Wraps known [DomainVerificationManager] status codes so that they can be used in a when
+ * statement. Unknown codes are coerced to [VerifyStatus.UNKNOWN] and should be treated as
+ * unverified.
+ *
+ * Also includes error codes specific to this implementation of the domain verification agent.
+ * These must be stable across all versions, as codes are persisted to disk. They do not
+ * technically have to be stable across different device factory resets, since they will be reset
+ * once the apps are re-initialized, but easier to keep them unique forever.
+ */
+enum class VerifyStatus(val value: Int) {
+ NO_RESPONSE(DomainVerificationInfo.STATE_NO_RESPONSE),
+ SUCCESS(DomainVerificationInfo.STATE_SUCCESS),
+
+ UNKNOWN(DomainVerificationInfo.STATE_FIRST_VERIFIER_DEFINED),
+ FAILURE_LEGACY_UNSUPPORTED_WILDCARD(DomainVerificationInfo.STATE_FIRST_VERIFIER_DEFINED + 1),
+ FAILURE_REJECTED_BY_SERVER(DomainVerificationInfo.STATE_FIRST_VERIFIER_DEFINED + 2),
+ FAILURE_TIMEOUT(DomainVerificationInfo.STATE_FIRST_VERIFIER_DEFINED + 3),
+ FAILURE_UNKNOWN(DomainVerificationInfo.STATE_FIRST_VERIFIER_DEFINED + 4),
+ FAILURE_REDIRECT(DomainVerificationInfo.STATE_FIRST_VERIFIER_DEFINED + 5),
+
+ // Failed to retrieve signature information from PackageManager
+ FAILURE_PACKAGE_MANAGER(DomainVerificationInfo.STATE_FIRST_VERIFIER_DEFINED + 6);
+
+ companion object {
+ fun shouldRetry(state: Int): Boolean {
+ if (state == DomainVerificationInfo.STATE_UNMODIFIABLE) {
+ return false
+ }
+
+ val status = values().find { it.value == state } ?: return true
+ return when (status) {
+ SUCCESS,
+ FAILURE_LEGACY_UNSUPPORTED_WILDCARD,
+ FAILURE_REJECTED_BY_SERVER,
+ FAILURE_PACKAGE_MANAGER,
+ UNKNOWN -> false
+ NO_RESPONSE,
+ FAILURE_TIMEOUT,
+ FAILURE_UNKNOWN,
+ FAILURE_REDIRECT -> true
+ }
+ }
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/BaseRequestWorker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/BaseRequestWorker.kt
new file mode 100644
index 0000000..a17f9c9
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/worker/BaseRequestWorker.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain.worker
+
+import android.content.Context
+import android.content.pm.verify.domain.DomainVerificationManager
+import androidx.work.CoroutineWorker
+import androidx.work.WorkerParameters
+import com.android.statementservice.domain.DomainVerifier
+
+abstract class BaseRequestWorker(
+ protected val appContext: Context,
+ protected val params: WorkerParameters
+) : CoroutineWorker(appContext, params) {
+
+ protected val verificationManager =
+ appContext.getSystemService(DomainVerificationManager::class.java)!!
+
+ protected val verifier = DomainVerifier.getInstance(appContext)
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt
new file mode 100644
index 0000000..3a3aea9
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain.worker
+
+import android.content.Context
+import android.content.pm.PackageManager
+import android.util.Log
+import androidx.work.Data
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.WorkerParameters
+import com.android.statementservice.utils.AndroidUtils
+import kotlinx.coroutines.coroutineScope
+
+class CollectV1Worker(appContext: Context, params: WorkerParameters) :
+ BaseRequestWorker(appContext, params) {
+
+ companion object {
+ private val TAG = CollectV1Worker::class.java.simpleName
+ private const val DEBUG = false
+
+ private const val VERIFICATION_ID_KEY = "verificationId"
+ private const val PACKAGE_NAME_KEY = "packageName"
+
+ fun buildRequest(verificationId: Int, packageName: String) =
+ OneTimeWorkRequestBuilder<CollectV1Worker>()
+ .setInputData(
+ Data.Builder()
+ .putInt(VERIFICATION_ID_KEY, verificationId)
+ .apply {
+ if (DEBUG) {
+ putString(PACKAGE_NAME_KEY, packageName)
+ }
+ }
+ .build()
+ )
+ .build()
+ }
+
+ override suspend fun doWork() = coroutineScope {
+ if (!AndroidUtils.isReceiverV1Enabled(appContext)) {
+ return@coroutineScope Result.success()
+ }
+
+ val inputData = params.inputData
+ val verificationId = inputData.getInt(VERIFICATION_ID_KEY, -1)
+ val successfulHosts = mutableListOf<String>()
+ val failedHosts = mutableListOf<String>()
+ inputData.keyValueMap.entries.forEach { (key, _) ->
+ when {
+ key.startsWith(SingleV1RequestWorker.HOST_SUCCESS_PREFIX) ->
+ successfulHosts += key.removePrefix(SingleV1RequestWorker.HOST_SUCCESS_PREFIX)
+ key.startsWith(SingleV1RequestWorker.HOST_FAILURE_PREFIX) ->
+ failedHosts += key.removePrefix(SingleV1RequestWorker.HOST_FAILURE_PREFIX)
+ }
+ }
+
+ if (DEBUG) {
+ val packageName = inputData.getString(PACKAGE_NAME_KEY)
+ Log.d(
+ TAG, "Domain verification v1 request for $packageName: " +
+ "success = $successfulHosts, failed = $failedHosts"
+ )
+ }
+
+ val resultCode = if (failedHosts.isEmpty()) {
+ PackageManager.INTENT_FILTER_VERIFICATION_SUCCESS
+ } else {
+ PackageManager.INTENT_FILTER_VERIFICATION_FAILURE
+ }
+
+ appContext.packageManager.verifyIntentFilter(verificationId, resultCode, failedHosts)
+
+ Result.success()
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/RetryRequestWorker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/RetryRequestWorker.kt
new file mode 100644
index 0000000..61ab2c2
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/worker/RetryRequestWorker.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain.worker
+
+import android.content.Context
+import androidx.work.NetworkType
+import androidx.work.WorkerParameters
+import com.android.statementservice.domain.VerifyStatus
+import com.android.statementservice.utils.AndroidUtils
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.isActive
+import java.util.UUID
+
+/**
+ * Scheduled every 24 hours with [NetworkType.CONNECTED] and every 72 hours without any constraints
+ * to retry all domains for all packages with a failing error code.
+ */
+class RetryRequestWorker(
+ appContext: Context,
+ params: WorkerParameters
+) : BaseRequestWorker(appContext, params) {
+
+ data class VerifyResult(val domainSetId: UUID, val host: String, val status: VerifyStatus)
+
+ override suspend fun doWork() = coroutineScope {
+ if (!AndroidUtils.isReceiverV2Enabled(appContext)) {
+ return@coroutineScope Result.success()
+ }
+
+ val packageNames = verificationManager.queryValidVerificationPackageNames()
+
+ verifier.collectHosts(packageNames)
+ .map { (domainSetId, packageName, host) ->
+ async {
+ if (isActive && !isStopped) {
+ val (_, status) = verifier.verifyHost(host, packageName, params.network)
+ VerifyResult(domainSetId, host, status)
+ } else {
+ // If the job gets cancelled, stop the remaining hosts, but continue the
+ // job to commit the results for hosts that were already requested.
+ null
+ }
+ }
+ }
+ .awaitAll()
+ .filterNotNull() // TODO(b/159952358): Fast fail packages which can't be retrieved.
+ .groupBy { it.domainSetId }
+ .forEach { (domainSetId, resultsById) ->
+ resultsById.groupBy { it.status }
+ .mapValues { it.value.map(VerifyResult::host).toSet() }
+ .forEach { (status, hosts) ->
+ verificationManager.setDomainVerificationStatus(
+ domainSetId,
+ hosts,
+ status.value
+ )
+ }
+ }
+
+ // Succeed regardless of results since this retry is best effort and not required
+ Result.success()
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt
new file mode 100644
index 0000000..cd8a182
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain.worker
+
+import android.content.Context
+import android.util.Log
+import androidx.work.Data
+import androidx.work.OneTimeWorkRequest
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.WorkerParameters
+import com.android.statementservice.utils.AndroidUtils
+import kotlinx.coroutines.coroutineScope
+
+class SingleV1RequestWorker(appContext: Context, params: WorkerParameters) :
+ BaseRequestWorker(appContext, params) {
+
+ companion object {
+ private val TAG = SingleV1RequestWorker::class.java.simpleName
+ private const val DEBUG = false
+
+ private const val PACKAGE_NAME_KEY = "packageName"
+ private const val HOST_KEY = "host"
+ const val HOST_SUCCESS_PREFIX = "hostSuccess:"
+ const val HOST_FAILURE_PREFIX = "hostFailure:"
+
+ fun buildRequest(
+ packageName: String,
+ host: String,
+ block: OneTimeWorkRequest.Builder.() -> Unit = {}
+ ) = OneTimeWorkRequestBuilder<SingleV1RequestWorker>()
+ .setInputData(
+ Data.Builder()
+ .putString(PACKAGE_NAME_KEY, packageName)
+ .putString(HOST_KEY, host)
+ .build()
+ )
+ .apply(block)
+ .build()
+ }
+
+ override suspend fun doWork() = coroutineScope {
+ if (!AndroidUtils.isReceiverV1Enabled(appContext)) {
+ return@coroutineScope Result.success()
+ }
+
+ val packageName = params.inputData.getString(PACKAGE_NAME_KEY)!!
+ val host = params.inputData.getString(HOST_KEY)!!
+
+ val (result, status) = verifier.verifyHost(host, packageName, params.network)
+
+ if (DEBUG) {
+ Log.d(
+ TAG, "Domain verification v1 request for $packageName: " +
+ "host = $host, status = $status"
+ )
+ }
+
+ // Coerce failure results into success so that final collection task gets a chance to run
+ when (result) {
+ is Result.Success -> Result.success(
+ Data.Builder()
+ .putInt("$HOST_SUCCESS_PREFIX$host", status.value)
+ .build()
+ )
+ is Result.Failure -> Result.success(
+ Data.Builder()
+ .putInt("$HOST_FAILURE_PREFIX$host", status.value)
+ .build()
+ )
+ else -> result
+ }
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV2RequestWorker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV2RequestWorker.kt
new file mode 100644
index 0000000..562b132
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV2RequestWorker.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.domain.worker
+
+import android.content.Context
+import androidx.work.Data
+import androidx.work.OneTimeWorkRequest
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.WorkerParameters
+import com.android.statementservice.utils.AndroidUtils
+import kotlinx.coroutines.coroutineScope
+import java.util.UUID
+
+class SingleV2RequestWorker(appContext: Context, params: WorkerParameters) :
+ BaseRequestWorker(appContext, params) {
+
+ companion object {
+ private const val DOMAIN_SET_ID_KEY = "domainSetId"
+ private const val PACKAGE_NAME_KEY = "packageName"
+ private const val HOST_KEY = "host"
+
+ fun buildRequest(
+ domainSetId: UUID,
+ packageName: String,
+ host: String,
+ block: OneTimeWorkRequest.Builder.() -> Unit = {}
+ ) = OneTimeWorkRequestBuilder<SingleV2RequestWorker>()
+ .setInputData(
+ Data.Builder()
+ .putString(DOMAIN_SET_ID_KEY, domainSetId.toString())
+ .putString(PACKAGE_NAME_KEY, packageName)
+ .putString(HOST_KEY, host)
+ .build()
+ )
+ .apply(block)
+ .build()
+ }
+
+ override suspend fun doWork() = coroutineScope {
+ if (!AndroidUtils.isReceiverV2Enabled(appContext)) {
+ return@coroutineScope Result.success()
+ }
+
+ val domainSetId = params.inputData.getString(DOMAIN_SET_ID_KEY)!!.let(UUID::fromString)
+ val packageName = params.inputData.getString(PACKAGE_NAME_KEY)!!
+ val host = params.inputData.getString(HOST_KEY)!!
+
+ val (result, status) = verifier.verifyHost(host, packageName, params.network)
+
+ verificationManager.setDomainVerificationStatus(domainSetId, setOf(host), status.value)
+
+ result
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/network/retriever/StatementParser.kt b/packages/StatementService/src/com/android/statementservice/network/retriever/StatementParser.kt
new file mode 100644
index 0000000..455e8085
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/network/retriever/StatementParser.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.network.retriever
+
+import android.util.JsonReader
+import com.android.statementservice.retriever.AbstractAsset
+import com.android.statementservice.retriever.AssetFactory
+import com.android.statementservice.retriever.JsonParser
+import com.android.statementservice.retriever.Relation
+import com.android.statementservice.retriever.Statement
+import com.android.statementservice.utils.Result
+import com.android.statementservice.utils.StatementUtils
+import java.io.StringReader
+import java.util.ArrayList
+import com.android.statementservice.retriever.WebAsset
+import com.android.statementservice.retriever.AndroidAppAsset
+
+/**
+ * Parses JSON from the Digital Asset Links specification. For examples, see [WebAsset],
+ * [AndroidAppAsset], and [Statement].
+ */
+object StatementParser {
+
+ private const val FIELD_NOT_STRING_FORMAT_STRING = "Expected %s to be string."
+ private const val FIELD_NOT_ARRAY_FORMAT_STRING = "Expected %s to be array."
+
+ /**
+ * Parses a JSON array of statements.
+ */
+ fun parseStatementList(statementList: String, source: AbstractAsset): Result<ParsedStatement> {
+ val statements: MutableList<Statement> = ArrayList()
+ val delegates: MutableList<String> = ArrayList()
+ StringReader(statementList).use { stringReader ->
+ JsonReader(stringReader).use { reader ->
+ reader.isLenient = false
+ reader.beginArray()
+ while (reader.hasNext()) {
+ val result = parseOneStatement(reader, source)
+ if (result is Result.Failure) {
+ continue
+ }
+ result as Result.Success
+ statements.addAll(result.value.statements)
+ delegates.addAll(result.value.delegates)
+ }
+ reader.endArray()
+ }
+ }
+ return Result.Success(ParsedStatement(statements, delegates))
+ }
+
+ /**
+ * Parses a single JSON statement.
+ */
+ fun parseStatement(statementString: String, source: AbstractAsset) =
+ StringReader(statementString).use { stringReader ->
+ JsonReader(stringReader).use { reader ->
+ reader.isLenient = false
+ parseOneStatement(reader, source)
+ }
+ }
+
+ /**
+ * Parses a single JSON statement. This method guarantees that exactly one JSON object
+ * will be consumed.
+ */
+ private fun parseOneStatement(
+ reader: JsonReader,
+ source: AbstractAsset
+ ): Result<ParsedStatement> {
+ val statement = JsonParser.parse(reader)
+ val delegate = statement.optString(StatementUtils.DELEGATE_FIELD_DELEGATE)
+ if (!delegate.isNullOrEmpty()) {
+ return Result.Success(ParsedStatement(emptyList(), listOfNotNull(delegate)))
+ }
+
+ val targetObject = statement.optJSONObject(StatementUtils.ASSET_DESCRIPTOR_FIELD_TARGET)
+ ?: return Result.Failure(
+ FIELD_NOT_STRING_FORMAT_STRING.format(StatementUtils.ASSET_DESCRIPTOR_FIELD_TARGET)
+ )
+ val relations = statement.optJSONArray(StatementUtils.ASSET_DESCRIPTOR_FIELD_RELATION)
+ ?: return Result.Failure(
+ FIELD_NOT_ARRAY_FORMAT_STRING.format(StatementUtils.ASSET_DESCRIPTOR_FIELD_RELATION)
+ )
+ val target = AssetFactory.create(targetObject)
+
+ val statements = (0 until relations.length())
+ .map { relations.getString(it) }
+ .map(Relation::create)
+ .map { Statement.create(source, target, it) }
+ return Result.Success(ParsedStatement(statements, listOfNotNull(delegate)))
+ }
+
+ data class ParsedStatement(val statements: List<Statement>, val delegates: List<String>)
+}
diff --git a/packages/StatementService/src/com/android/statementservice/network/retriever/StatementRetriever.kt b/packages/StatementService/src/com/android/statementservice/network/retriever/StatementRetriever.kt
new file mode 100644
index 0000000..c27a26a
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/network/retriever/StatementRetriever.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.network.retriever
+
+import android.content.Intent
+import android.net.Network
+import com.android.statementservice.retriever.AbstractAsset
+import com.android.statementservice.retriever.AndroidAppAsset
+import com.android.statementservice.retriever.Statement
+import com.android.statementservice.retriever.WebAsset
+import com.android.statementservice.utils.StatementUtils.tryOrNull
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.withContext
+import java.net.URL
+
+/**
+ * Retrieves the JSON configured at a given domain that's compliant with the Digital Asset Links
+ * specification, returning the list of statements which serve as assertions by the web server as
+ * to what other assets it can be connected with.
+ *
+ * Relevant to this app, it allows the website to report which Android app package and signature
+ * digest has been approved by the website owner, which considers them as the same author and safe
+ * to automatically delegate web [Intent]s to.
+ *
+ * The relevant data classes are [WebAsset], [AndroidAppAsset], and [Statement].
+ */
+class StatementRetriever {
+
+ companion object {
+ private const val HTTP_CONNECTION_TIMEOUT_MILLIS = 5000
+ private const val HTTP_CONTENT_SIZE_LIMIT_IN_BYTES = (1024 * 1024).toLong()
+ private const val MAX_INCLUDE_LEVEL = 1
+ private const val WELL_KNOWN_STATEMENT_PATH = "/.well-known/assetlinks.json"
+ }
+
+ private val fetcher = UrlFetcher()
+
+ data class Result(
+ val statements: List<Statement>,
+ val responseCode: Int?
+ ) {
+ companion object {
+ val EMPTY = Result(emptyList(), null)
+ }
+
+ constructor(statements: List<Statement>, webResult: UrlFetcher.Response) : this(
+ statements,
+ webResult.responseCode
+ )
+ }
+
+ suspend fun retrieve(source: AbstractAsset, network: Network? = null) = when (source) {
+ // TODO:(b/171219506): Does this have to be implemented?
+ is AndroidAppAsset -> null
+ is WebAsset -> retrieveFromWeb(source, network)
+ else -> null
+ }
+
+ private suspend fun retrieveFromWeb(asset: WebAsset, network: Network? = null): Result? {
+ val url = computeAssociationJsonUrl(asset) ?: return null
+ return retrieve(url, MAX_INCLUDE_LEVEL, asset, network)
+ }
+
+ private fun computeAssociationJsonUrl(asset: WebAsset) = tryOrNull {
+ URL(asset.scheme, asset.domain, asset.port, WELL_KNOWN_STATEMENT_PATH).toExternalForm()
+ }
+
+ private suspend fun retrieve(
+ urlString: String,
+ maxIncludeLevel: Int,
+ source: AbstractAsset,
+ network: Network? = null
+ ): Result {
+ if (maxIncludeLevel < 0) {
+ return Result.EMPTY
+ }
+
+ return withContext(Dispatchers.IO) {
+ val url = try {
+ @Suppress("BlockingMethodInNonBlockingContext")
+ URL(urlString)
+ } catch (ignored: Exception) {
+ return@withContext Result.EMPTY
+ }
+
+ val webResponse = fetcher.fetch(
+ url = url,
+ connectionTimeoutMillis = HTTP_CONNECTION_TIMEOUT_MILLIS,
+ fileSizeLimit = HTTP_CONTENT_SIZE_LIMIT_IN_BYTES,
+ network
+ ).successValueOrNull() ?: return@withContext Result.EMPTY
+
+ val content = webResponse.content ?: return@withContext Result(emptyList(), webResponse)
+ val (statements, delegates) = StatementParser.parseStatementList(content, source)
+ .successValueOrNull() ?: return@withContext Result(emptyList(), webResponse)
+
+ val delegatedStatements = delegates
+ .map { async { retrieve(it, maxIncludeLevel - 1, source).statements } }
+ .awaitAll()
+ .flatten()
+
+ Result(statements + delegatedStatements, webResponse)
+ }
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/network/retriever/UrlFetcher.kt b/packages/StatementService/src/com/android/statementservice/network/retriever/UrlFetcher.kt
new file mode 100644
index 0000000..5c1f5e0
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/network/retriever/UrlFetcher.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.statementservice.network.retriever
+
+import android.net.Network
+import android.net.TrafficStats
+import android.util.Log
+import com.android.statementservice.utils.Result
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.withContext
+import java.net.HttpURLConnection
+import java.net.URL
+import java.nio.charset.Charset
+import javax.net.ssl.HttpsURLConnection
+
+class UrlFetcher {
+
+ companion object {
+ private val TAG = UrlFetcher::class.java.simpleName
+ }
+
+ suspend fun fetch(
+ url: URL,
+ connectionTimeoutMillis: Int,
+ fileSizeLimit: Long,
+ network: Network? = null
+ ) = withContext(Dispatchers.IO) {
+ TrafficStats.setThreadStatsTag(Thread.currentThread().id.toInt())
+ @Suppress("BlockingMethodInNonBlockingContext")
+ val connection =
+ ((network?.openConnection(url) ?: url.openConnection()) as HttpsURLConnection)
+ try {
+ connection.apply {
+ connectTimeout = connectionTimeoutMillis
+ readTimeout = connectionTimeoutMillis
+ useCaches = true
+ instanceFollowRedirects = false
+ addRequestProperty("Cache-Control", "max-stale=60")
+ }
+ val responseCode = connection.responseCode
+ when {
+ responseCode != HttpURLConnection.HTTP_OK -> {
+ Log.w(TAG, "The responses code is not 200 but $responseCode")
+ Result.Success(Response(responseCode))
+ }
+ connection.contentLength > fileSizeLimit -> {
+ Log.w(TAG, "The content size of the url is larger than $fileSizeLimit")
+ Result.Success(Response(responseCode))
+ }
+ else -> {
+ val content = async {
+ connection.inputStream
+ .bufferedReader(Charset.forName("UTF-8"))
+ .readText()
+ }
+
+ Result.Success(Response(responseCode, content.await()))
+ }
+ }
+ } catch (ignored: Throwable) {
+ Result.Failure(ignored)
+ } finally {
+ connection.disconnect()
+ }
+ }
+
+ data class Response(
+ val responseCode: Int,
+ val content: String? = null
+ )
+}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/AbstractAsset.java b/packages/StatementService/src/com/android/statementservice/retriever/AbstractAsset.java
index 8d6fd66..4834626 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/AbstractAsset.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/AbstractAsset.java
@@ -81,6 +81,9 @@
/**
* If this is the source asset of a statement file, should the retriever follow
* any insecure (non-HTTPS) include statements made by the asset.
+ *
+ * TODO(b/171219506): Why would this be allowed? Can it be removed, even for web assets?
+ * Android doesn't even allow non-secure traffic by default.
*/
public abstract boolean followInsecureInclude();
}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/AbstractStatementRetriever.java b/packages/StatementService/src/com/android/statementservice/retriever/AbstractStatementRetriever.java
deleted file mode 100644
index fe9b99a..0000000
--- a/packages/StatementService/src/com/android/statementservice/retriever/AbstractStatementRetriever.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.statementservice.retriever;
-
-import android.content.Context;
-import android.annotation.NonNull;
-
-import java.util.List;
-
-/**
- * Retrieves the statements made by assets. This class is the entry point of the package.
- * <p>
- * An asset is an identifiable and addressable online entity that typically
- * provides some service or content. Examples of assets are websites, Android
- * apps, Twitter feeds, and Plus Pages.
- * <p>
- * Ownership of an asset is defined by being able to control it and speak for it.
- * An asset owner may establish a relationship between the asset and another
- * asset by making a statement about an intended relationship between the two.
- * An example of a relationship is permission delegation. For example, the owner
- * of a website (the webmaster) may delegate the ability the handle URLs to a
- * particular mobile app. Relationships are considered public information.
- * <p>
- * A particular kind of relationship (like permission delegation) defines a binary
- * relation on assets. The relation is not symmetric or transitive, nor is it
- * antisymmetric or anti-transitive.
- * <p>
- * A statement S(r, a, b) is an assertion that the relation r holds for the
- * ordered pair of assets (a, b). For example, taking r = "delegates permission
- * to view user's location", a = New York Times mobile app,
- * b = nytimes.com website, S(r, a, b) would be an assertion that "the New York
- * Times mobile app delegates its ability to use the user's location to the
- * nytimes.com website".
- * <p>
- * A statement S(r, a, b) is considered <b>reliable</b> if we have confidence that
- * the statement is true; the exact criterion depends on the kind of statement,
- * since some kinds of statements may be true on their face whereas others may
- * require multiple parties to agree.
- * <p>
- * For example, to get the statements made by www.example.com use:
- * <pre>
- * result = retrieveStatements(AssetFactory.create(
- * "{\"namespace\": \"web\", \"site\": \"https://www.google.com\"}"))
- * </pre>
- * {@code result} will contain the statements and the expiration time of this result. The statements
- * are considered reliable until the expiration time.
- */
-public abstract class AbstractStatementRetriever {
-
- /**
- * Returns the statements made by the {@code source} asset with ttl.
- *
- * @throws AssociationServiceException if the asset namespace is not supported.
- */
- public abstract Result retrieveStatements(AbstractAsset source)
- throws AssociationServiceException;
-
- /**
- * The retrieved statements and the expiration date.
- */
- public interface Result {
-
- /**
- * @return the retrieved statements.
- */
- @NonNull
- public List<Statement> getStatements();
-
- /**
- * @return the expiration time in millisecond.
- */
- public long getExpireMillis();
- }
-
- /**
- * Creates a new StatementRetriever that directly retrieves statements from the asset.
- *
- * <p> For web assets, {@link AbstractStatementRetriever} will try to retrieve the statement
- * file from URL: {@code [webAsset.site]/.well-known/assetlinks.json"} where {@code
- * [webAsset.site]} is in the form {@code http{s}://[hostname]:[optional_port]}. The file
- * should contain one JSON array of statements.
- *
- * <p> For Android assets, {@link AbstractStatementRetriever} will try to retrieve the statement
- * from the AndroidManifest.xml. The developer should add a {@code meta-data} tag under
- * {@code application} tag where attribute {@code android:name} equals "associated_assets"
- * and {@code android:recourse} points to a string array resource. Each entry in the string
- * array should contain exactly one statement in JSON format. Note that this implementation
- * can only return statements made by installed apps.
- */
- public static AbstractStatementRetriever createDirectRetriever(Context context) {
- return new DirectStatementRetriever(new URLFetcher(),
- new AndroidPackageInfoFetcher(context));
- }
-}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/AndroidAppAsset.java b/packages/StatementService/src/com/android/statementservice/retriever/AndroidAppAsset.java
index 8ead90b..14ca232 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/AndroidAppAsset.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/AndroidAppAsset.java
@@ -16,6 +16,8 @@
package com.android.statementservice.retriever;
+import com.android.statementservice.utils.StatementUtils;
+
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -34,7 +36,8 @@
* "sha256_cert_fingerprints": ["[SHA256 fingerprint of signing cert]", "[additional cert]", ...] }
*
* <p>For example, { "namespace": "android_app", "package_name": "com.test.mytestapp",
- * "sha256_cert_fingerprints": ["24:D9:B4:57:A6:42:FB:E6:E5:B8:D6:9E:7B:2D:C2:D1:CB:D1:77:17:1D:7F:D4:A9:16:10:11:AB:92:B9:8F:3F"]
+ * "sha256_cert_fingerprints": ["24:D9:B4:57:A6:42:FB:E6:E5:B8:D6:9E:7B:2D:C2:D1:CB:D1:77:17:1D
+ * :7F:D4:A9:16:10:11:AB:92:B9:8F:3F"]
* }
*
* <p>Given a signed APK, Java 7's commandline keytool can compute the fingerprint using:
@@ -43,7 +46,7 @@
* <p>Each entry in "sha256_cert_fingerprints" is a colon-separated hex string (e.g. 14:6D:E9:...)
* representing the certificate SHA-256 fingerprint.
*/
-/* package private */ final class AndroidAppAsset extends AbstractAsset {
+public final class AndroidAppAsset extends AbstractAsset {
private static final String MISSING_FIELD_FORMAT_STRING = "Expected %s to be set.";
private static final String MISSING_APPCERTS_FORMAT_STRING =
@@ -65,9 +68,10 @@
public String toJson() {
AssetJsonWriter writer = new AssetJsonWriter();
- writer.writeFieldLower(Utils.NAMESPACE_FIELD, Utils.NAMESPACE_ANDROID_APP);
- writer.writeFieldLower(Utils.ANDROID_APP_ASSET_FIELD_PACKAGE_NAME, mPackageName);
- writer.writeArrayUpper(Utils.ANDROID_APP_ASSET_FIELD_CERT_FPS, mCertFingerprints);
+ writer.writeFieldLower(StatementUtils.NAMESPACE_FIELD,
+ StatementUtils.NAMESPACE_ANDROID_APP);
+ writer.writeFieldLower(StatementUtils.ANDROID_APP_ASSET_FIELD_PACKAGE_NAME, mPackageName);
+ writer.writeArrayUpper(StatementUtils.ANDROID_APP_ASSET_FIELD_CERT_FPS, mCertFingerprints);
return writer.closeAndGetString();
}
@@ -114,17 +118,17 @@
*/
public static AndroidAppAsset create(JSONObject asset)
throws AssociationServiceException {
- String packageName = asset.optString(Utils.ANDROID_APP_ASSET_FIELD_PACKAGE_NAME);
+ String packageName = asset.optString(StatementUtils.ANDROID_APP_ASSET_FIELD_PACKAGE_NAME);
if (packageName.equals("")) {
throw new AssociationServiceException(String.format(MISSING_FIELD_FORMAT_STRING,
- Utils.ANDROID_APP_ASSET_FIELD_PACKAGE_NAME));
+ StatementUtils.ANDROID_APP_ASSET_FIELD_PACKAGE_NAME));
}
- JSONArray certArray = asset.optJSONArray(Utils.ANDROID_APP_ASSET_FIELD_CERT_FPS);
+ JSONArray certArray = asset.optJSONArray(StatementUtils.ANDROID_APP_ASSET_FIELD_CERT_FPS);
if (certArray == null || certArray.length() == 0) {
throw new AssociationServiceException(
String.format(MISSING_APPCERTS_FORMAT_STRING,
- Utils.ANDROID_APP_ASSET_FIELD_CERT_FPS));
+ StatementUtils.ANDROID_APP_ASSET_FIELD_CERT_FPS));
}
List<String> certFingerprints = new ArrayList<>(certArray.length());
for (int i = 0; i < certArray.length(); i++) {
@@ -133,7 +137,7 @@
} catch (JSONException e) {
throw new AssociationServiceException(
String.format(APPCERT_NOT_STRING_FORMAT_STRING,
- Utils.ANDROID_APP_ASSET_FIELD_CERT_FPS));
+ StatementUtils.ANDROID_APP_ASSET_FIELD_CERT_FPS));
}
}
@@ -143,7 +147,7 @@
/**
* Creates a new AndroidAppAsset.
*
- * @param packageName the package name of the Android app.
+ * @param packageName the package name of the Android app.
* @param certFingerprints at least one of the Android app signing certificate sha-256
* fingerprint.
*/
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/AndroidAppAssetMatcher.java b/packages/StatementService/src/com/android/statementservice/retriever/AndroidAppAssetMatcher.java
index 8a9d838..45798fa 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/AndroidAppAssetMatcher.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/AndroidAppAssetMatcher.java
@@ -23,7 +23,7 @@
* Match assets that have the same 'package_name' field and have at least one common certificate
* fingerprint in 'sha256_cert_fingerprints' field.
*/
-/* package private */ final class AndroidAppAssetMatcher extends AbstractAssetMatcher {
+public final class AndroidAppAssetMatcher extends AbstractAssetMatcher {
private final AndroidAppAsset mQuery;
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/AndroidPackageInfoFetcher.java b/packages/StatementService/src/com/android/statementservice/retriever/AndroidPackageInfoFetcher.java
deleted file mode 100644
index 1000c4c..0000000
--- a/packages/StatementService/src/com/android/statementservice/retriever/AndroidPackageInfoFetcher.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.statementservice.retriever;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources.NotFoundException;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Class that provides information about an android app from {@link PackageManager}.
- *
- * Visible for testing.
- *
- * @hide
- */
-public class AndroidPackageInfoFetcher {
-
- /**
- * The name of the metadata tag in AndroidManifest.xml that stores the associated asset array
- * ID. The metadata tag should use the android:resource attribute to point to an array resource
- * that contains the associated assets.
- */
- private static final String ASSOCIATED_ASSETS_KEY = "associated_assets";
-
- private Context mContext;
-
- public AndroidPackageInfoFetcher(Context context) {
- mContext = context;
- }
-
- /**
- * Returns the Sha-256 fingerprints of all certificates from the specified package as a list of
- * upper case HEX Strings with bytes separated by colons. Given an app {@link
- * android.content.pm.Signature}, the fingerprint can be computed as {@link
- * Utils#computeNormalizedSha256Fingerprint} {@code(signature.toByteArray())}.
- *
- * <p>Given a signed APK, Java 7's commandline keytool can compute the fingerprint using: {@code
- * keytool -list -printcert -jarfile signed_app.apk}
- *
- * <p>Example: "10:39:38:EE:45:37:E5:9E:8E:E7:92:F6:54:50:4F:B8:34:6F:C6:B3:46:D0:BB:C4:41:5F:C3:39:FC:FC:8E:C1"
- *
- * @throws NameNotFoundException if an app with packageName is not installed on the device.
- */
- public List<String> getCertFingerprints(String packageName) throws NameNotFoundException {
- return Utils.getCertFingerprintsFromPackageManager(packageName, mContext);
- }
-
- /**
- * Returns all statements that the specified package makes in its AndroidManifest.xml.
- *
- * @throws NameNotFoundException if the app is not installed on the device.
- */
- public List<String> getStatements(String packageName) throws NameNotFoundException {
- PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(
- packageName, PackageManager.GET_META_DATA);
- ApplicationInfo appInfo = packageInfo.applicationInfo;
- if (appInfo.metaData == null) {
- return Collections.<String>emptyList();
- }
- int tokenResourceId = appInfo.metaData.getInt(ASSOCIATED_ASSETS_KEY);
- if (tokenResourceId == 0) {
- return Collections.<String>emptyList();
- }
- try {
- return Arrays.asList(
- mContext.getPackageManager().getResourcesForApplication(packageName)
- .getStringArray(tokenResourceId));
- } catch (NotFoundException e) {
- return Collections.<String>emptyList();
- }
- }
-}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/AssetFactory.java b/packages/StatementService/src/com/android/statementservice/retriever/AssetFactory.java
index 519d73a2..ac0bfab 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/AssetFactory.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/AssetFactory.java
@@ -16,12 +16,14 @@
package com.android.statementservice.retriever;
+import com.android.statementservice.utils.StatementUtils;
+
import org.json.JSONObject;
/**
* Factory to create asset from JSON string.
*/
-/* package private */ final class AssetFactory {
+public final class AssetFactory {
private static final String FIELD_NOT_STRING_FORMAT_STRING = "Expected %s to be string.";
@@ -34,15 +36,15 @@
*/
public static AbstractAsset create(JSONObject asset)
throws AssociationServiceException {
- String namespace = asset.optString(Utils.NAMESPACE_FIELD, null);
+ String namespace = asset.optString(StatementUtils.NAMESPACE_FIELD, null);
if (namespace == null) {
throw new AssociationServiceException(String.format(
- FIELD_NOT_STRING_FORMAT_STRING, Utils.NAMESPACE_FIELD));
+ FIELD_NOT_STRING_FORMAT_STRING, StatementUtils.NAMESPACE_FIELD));
}
- if (namespace.equals(Utils.NAMESPACE_WEB)) {
+ if (namespace.equals(StatementUtils.NAMESPACE_WEB)) {
return WebAsset.create(asset);
- } else if (namespace.equals(Utils.NAMESPACE_ANDROID_APP)) {
+ } else if (namespace.equals(StatementUtils.NAMESPACE_ANDROID_APP)) {
return AndroidAppAsset.create(asset);
} else {
throw new AssociationServiceException("Namespace " + namespace + " is not supported.");
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/AssetMatcherFactory.java b/packages/StatementService/src/com/android/statementservice/retriever/AssetMatcherFactory.java
index 1a50757..7773668 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/AssetMatcherFactory.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/AssetMatcherFactory.java
@@ -16,6 +16,8 @@
package com.android.statementservice.retriever;
+import com.android.statementservice.utils.StatementUtils;
+
import org.json.JSONException;
import org.json.JSONObject;
@@ -31,15 +33,15 @@
JSONException {
JSONObject queryObject = new JSONObject(query);
- String namespace = queryObject.optString(Utils.NAMESPACE_FIELD, null);
+ String namespace = queryObject.optString(StatementUtils.NAMESPACE_FIELD, null);
if (namespace == null) {
throw new AssociationServiceException(String.format(
- FIELD_NOT_STRING_FORMAT_STRING, Utils.NAMESPACE_FIELD));
+ FIELD_NOT_STRING_FORMAT_STRING, StatementUtils.NAMESPACE_FIELD));
}
- if (namespace.equals(Utils.NAMESPACE_WEB)) {
+ if (namespace.equals(StatementUtils.NAMESPACE_WEB)) {
return new WebAssetMatcher(WebAsset.create(queryObject));
- } else if (namespace.equals(Utils.NAMESPACE_ANDROID_APP)) {
+ } else if (namespace.equals(StatementUtils.NAMESPACE_ANDROID_APP)) {
return new AndroidAppAssetMatcher(AndroidAppAsset.create(queryObject));
} else {
throw new AssociationServiceException(
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java b/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
deleted file mode 100644
index 9839329..0000000
--- a/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.statementservice.retriever;
-
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.util.Log;
-
-import org.json.JSONException;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * An implementation of {@link AbstractStatementRetriever} that directly retrieves statements from
- * the asset.
- */
-/* package private */ final class DirectStatementRetriever extends AbstractStatementRetriever {
-
- private static final long DO_NOT_CACHE_RESULT = 0L;
- private static final int HTTP_CONNECTION_TIMEOUT_MILLIS = 5000;
- private static final int HTTP_CONNECTION_BACKOFF_MILLIS = 3000;
- private static final int HTTP_CONNECTION_RETRY = 3;
- private static final long HTTP_CONTENT_SIZE_LIMIT_IN_BYTES = 1024 * 1024;
- private static final int MAX_INCLUDE_LEVEL = 1;
- private static final String WELL_KNOWN_STATEMENT_PATH = "/.well-known/assetlinks.json";
-
- private final URLFetcher mUrlFetcher;
- private final AndroidPackageInfoFetcher mAndroidFetcher;
-
- /**
- * An immutable value type representing the retrieved statements and the expiration date.
- */
- public static class Result implements AbstractStatementRetriever.Result {
-
- private final List<Statement> mStatements;
- private final Long mExpireMillis;
-
- @Override
- public List<Statement> getStatements() {
- return mStatements;
- }
-
- @Override
- public long getExpireMillis() {
- return mExpireMillis;
- }
-
- private Result(List<Statement> statements, Long expireMillis) {
- mStatements = statements;
- mExpireMillis = expireMillis;
- }
-
- public static Result create(List<Statement> statements, Long expireMillis) {
- return new Result(statements, expireMillis);
- }
-
- @Override
- public String toString() {
- StringBuilder result = new StringBuilder();
- result.append("Result: ");
- result.append(mStatements.toString());
- result.append(", mExpireMillis=");
- result.append(mExpireMillis);
- return result.toString();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- Result result = (Result) o;
-
- if (!mExpireMillis.equals(result.mExpireMillis)) {
- return false;
- }
- if (!mStatements.equals(result.mStatements)) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = mStatements.hashCode();
- result = 31 * result + mExpireMillis.hashCode();
- return result;
- }
- }
-
- public DirectStatementRetriever(URLFetcher urlFetcher,
- AndroidPackageInfoFetcher androidFetcher) {
- this.mUrlFetcher = urlFetcher;
- this.mAndroidFetcher = androidFetcher;
- }
-
- @Override
- public Result retrieveStatements(AbstractAsset source) throws AssociationServiceException {
- if (source instanceof AndroidAppAsset) {
- return retrieveFromAndroid((AndroidAppAsset) source);
- } else if (source instanceof WebAsset) {
- return retrieveFromWeb((WebAsset) source);
- } else {
- throw new AssociationServiceException("Namespace is not supported.");
- }
- }
-
- private String computeAssociationJsonUrl(WebAsset asset) {
- try {
- return new URL(asset.getScheme(), asset.getDomain(), asset.getPort(),
- WELL_KNOWN_STATEMENT_PATH)
- .toExternalForm();
- } catch (MalformedURLException e) {
- throw new AssertionError("Invalid domain name in database.");
- }
- }
-
- private Result retrieveStatementFromUrl(String urlString, int maxIncludeLevel,
- AbstractAsset source)
- throws AssociationServiceException {
- List<Statement> statements = new ArrayList<Statement>();
- if (maxIncludeLevel < 0) {
- return Result.create(statements, DO_NOT_CACHE_RESULT);
- }
-
- WebContent webContent;
- try {
- URL url = new URL(urlString);
- if (!source.followInsecureInclude()
- && !url.getProtocol().toLowerCase().equals("https")) {
- return Result.create(statements, DO_NOT_CACHE_RESULT);
- }
- webContent = mUrlFetcher.getWebContentFromUrlWithRetry(url,
- HTTP_CONTENT_SIZE_LIMIT_IN_BYTES, HTTP_CONNECTION_TIMEOUT_MILLIS,
- HTTP_CONNECTION_BACKOFF_MILLIS, HTTP_CONNECTION_RETRY);
- } catch (IOException | InterruptedException e) {
- return Result.create(statements, DO_NOT_CACHE_RESULT);
- }
-
- try {
- ParsedStatement result = StatementParser
- .parseStatementList(webContent.getContent(), source);
- statements.addAll(result.getStatements());
- for (String delegate : result.getDelegates()) {
- statements.addAll(
- retrieveStatementFromUrl(delegate, maxIncludeLevel - 1, source)
- .getStatements());
- }
- return Result.create(statements, webContent.getExpireTimeMillis());
- } catch (JSONException | IOException e) {
- return Result.create(statements, DO_NOT_CACHE_RESULT);
- }
- }
-
- private Result retrieveFromWeb(WebAsset asset)
- throws AssociationServiceException {
- return retrieveStatementFromUrl(computeAssociationJsonUrl(asset), MAX_INCLUDE_LEVEL, asset);
- }
-
- private Result retrieveFromAndroid(AndroidAppAsset asset) throws AssociationServiceException {
- try {
- List<String> delegates = new ArrayList<String>();
- List<Statement> statements = new ArrayList<Statement>();
-
- List<String> certFps = mAndroidFetcher.getCertFingerprints(asset.getPackageName());
- if (!Utils.hasCommonString(certFps, asset.getCertFingerprints())) {
- throw new AssociationServiceException(
- "Specified certs don't match the installed app.");
- }
-
- AndroidAppAsset actualSource = AndroidAppAsset.create(asset.getPackageName(), certFps);
- for (String statementJson : mAndroidFetcher.getStatements(asset.getPackageName())) {
- ParsedStatement result =
- StatementParser.parseStatement(statementJson, actualSource);
- statements.addAll(result.getStatements());
- delegates.addAll(result.getDelegates());
- }
-
- for (String delegate : delegates) {
- statements.addAll(retrieveStatementFromUrl(delegate, MAX_INCLUDE_LEVEL,
- actualSource).getStatements());
- }
-
- return Result.create(statements, DO_NOT_CACHE_RESULT);
- } catch (JSONException | IOException | NameNotFoundException e) {
- Log.w(DirectStatementRetriever.class.getSimpleName(), e);
- return Result.create(Collections.<Statement>emptyList(), DO_NOT_CACHE_RESULT);
- }
- }
-}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/ParsedStatement.java b/packages/StatementService/src/com/android/statementservice/retriever/ParsedStatement.java
deleted file mode 100644
index 9446e66..0000000
--- a/packages/StatementService/src/com/android/statementservice/retriever/ParsedStatement.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.statementservice.retriever;
-
-import java.util.List;
-
-/**
- * A class that stores a list of statement and/or a list of delegate url.
- */
-/* package private */ final class ParsedStatement {
-
- private final List<Statement> mStatements;
- private final List<String> mDelegates;
-
- public ParsedStatement(List<Statement> statements, List<String> delegates) {
- this.mStatements = statements;
- this.mDelegates = delegates;
- }
-
- public List<Statement> getStatements() {
- return mStatements;
- }
-
- public List<String> getDelegates() {
- return mDelegates;
- }
-}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/Statement.java b/packages/StatementService/src/com/android/statementservice/retriever/Statement.java
index 0f40a62..f8bab3e 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/Statement.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/Statement.java
@@ -17,6 +17,11 @@
package com.android.statementservice.retriever;
import android.annotation.NonNull;
+import android.net.Network;
+
+import com.android.statementservice.network.retriever.StatementRetriever;
+
+import kotlin.coroutines.Continuation;
/**
* An immutable value type representing a statement, consisting of a source, target, and relation.
@@ -31,9 +36,9 @@
* }
* </pre>
*
- * Then invoking {@link AbstractStatementRetriever#retrieveStatements(AbstractAsset)} will return a
- * {@link Statement} with {@link #getSource} equal to the input parameter, {@link #getRelation}
- * equal to
+ * Then invoking {@link StatementRetriever#retrieve(AbstractAsset, Network, Continuation)} will
+ * return a {@link Statement} with {@link #getSource} equal to the input parameter,
+ * {@link #getRelation} equal to
*
* <pre>Relation.create("delegate_permission", "common.get_login_creds");</pre>
*
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/StatementParser.java b/packages/StatementService/src/com/android/statementservice/retriever/StatementParser.java
deleted file mode 100644
index 0369718..0000000
--- a/packages/StatementService/src/com/android/statementservice/retriever/StatementParser.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.statementservice.retriever;
-
-import android.util.JsonReader;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Utility class that parses JSON-formatted statements.
- */
-/* package private */ final class StatementParser {
-
- private static final String FIELD_NOT_STRING_FORMAT_STRING = "Expected %s to be string.";
- private static final String FIELD_NOT_ARRAY_FORMAT_STRING = "Expected %s to be array.";
-
- /**
- * Parses a JSON array of statements.
- */
- static ParsedStatement parseStatementList(String statementList, AbstractAsset source)
- throws JSONException, IOException {
- List<Statement> statements = new ArrayList<Statement>();
- List<String> delegates = new ArrayList<String>();
-
- JsonReader reader = new JsonReader(new StringReader(statementList));
- reader.setLenient(false);
-
- reader.beginArray();
- while (reader.hasNext()) {
- ParsedStatement result;
- try {
- result = parseStatement(reader, source);
- } catch (AssociationServiceException e) {
- // The element in the array is well formatted Json but not a well-formed Statement.
- continue;
- }
- statements.addAll(result.getStatements());
- delegates.addAll(result.getDelegates());
- }
- reader.endArray();
-
- return new ParsedStatement(statements, delegates);
- }
-
- /**
- * Parses a single JSON statement.
- */
- static ParsedStatement parseStatement(String statementString, AbstractAsset source)
- throws AssociationServiceException, IOException, JSONException {
- JsonReader reader = new JsonReader(new StringReader(statementString));
- reader.setLenient(false);
- return parseStatement(reader, source);
- }
-
- /**
- * Parses a single JSON statement. This method guarantees that exactly one JSON object
- * will be consumed.
- */
- static ParsedStatement parseStatement(JsonReader reader, AbstractAsset source)
- throws JSONException, AssociationServiceException, IOException {
- List<Statement> statements = new ArrayList<Statement>();
- List<String> delegates = new ArrayList<String>();
-
- JSONObject statement = JsonParser.parse(reader);
-
- if (statement.optString(Utils.DELEGATE_FIELD_DELEGATE, null) != null) {
- delegates.add(statement.optString(Utils.DELEGATE_FIELD_DELEGATE));
- } else {
- JSONObject targetObject = statement.optJSONObject(Utils.ASSET_DESCRIPTOR_FIELD_TARGET);
- if (targetObject == null) {
- throw new AssociationServiceException(String.format(
- FIELD_NOT_STRING_FORMAT_STRING, Utils.ASSET_DESCRIPTOR_FIELD_TARGET));
- }
-
- JSONArray relations = statement.optJSONArray(Utils.ASSET_DESCRIPTOR_FIELD_RELATION);
- if (relations == null) {
- throw new AssociationServiceException(String.format(
- FIELD_NOT_ARRAY_FORMAT_STRING, Utils.ASSET_DESCRIPTOR_FIELD_RELATION));
- }
-
- AbstractAsset target = AssetFactory.create(targetObject);
- for (int i = 0; i < relations.length(); i++) {
- statements.add(Statement
- .create(source, target, Relation.create(relations.getString(i))));
- }
- }
-
- return new ParsedStatement(statements, delegates);
- }
-}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java b/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
deleted file mode 100644
index 23cd832..0000000
--- a/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.statementservice.retriever;
-
-import android.util.Log;
-
-import com.android.volley.Cache;
-import com.android.volley.NetworkResponse;
-import com.android.volley.toolbox.HttpHeaderParser;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Helper class for fetching HTTP or HTTPS URL.
- *
- * Visible for testing.
- *
- * @hide
- */
-public class URLFetcher {
- private static final String TAG = URLFetcher.class.getSimpleName();
-
- private static final long DO_NOT_CACHE_RESULT = 0L;
- private static final int INPUT_BUFFER_SIZE_IN_BYTES = 1024;
-
- /**
- * Fetches the specified url and returns the content and ttl.
- *
- * <p>
- * Retry {@code retry} times if the connection failed or timed out for any reason.
- * HTTP error code (e.g. 404/500) won't be retried.
- *
- * @throws IOException if it can't retrieve the content due to a network problem.
- * @throws AssociationServiceException if the URL scheme is not http or https or the content
- * length exceeds {code fileSizeLimit}.
- */
- public WebContent getWebContentFromUrlWithRetry(URL url, long fileSizeLimit,
- int connectionTimeoutMillis, int backoffMillis, int retry)
- throws AssociationServiceException, IOException, InterruptedException {
- if (retry <= 0) {
- throw new IllegalArgumentException("retry should be a postive inetger.");
- }
- while (retry > 0) {
- try {
- return getWebContentFromUrl(url, fileSizeLimit, connectionTimeoutMillis);
- } catch (IOException e) {
- retry--;
- if (retry == 0) {
- throw e;
- }
- }
-
- Thread.sleep(backoffMillis);
- }
-
- // Should never reach here.
- return null;
- }
-
- /**
- * Fetches the specified url and returns the content and ttl.
- *
- * @throws IOException if it can't retrieve the content due to a network problem.
- * @throws AssociationServiceException if the URL scheme is not http or https or the content
- * length exceeds {code fileSizeLimit}.
- */
- public WebContent getWebContentFromUrl(URL url, long fileSizeLimit, int connectionTimeoutMillis)
- throws AssociationServiceException, IOException {
- final String scheme = url.getProtocol().toLowerCase(Locale.US);
- if (!scheme.equals("http") && !scheme.equals("https")) {
- throw new IllegalArgumentException("The url protocol should be on http or https.");
- }
-
- HttpURLConnection connection = null;
- try {
- connection = (HttpURLConnection) url.openConnection();
- connection.setInstanceFollowRedirects(true);
- connection.setConnectTimeout(connectionTimeoutMillis);
- connection.setReadTimeout(connectionTimeoutMillis);
- connection.setUseCaches(true);
- connection.setInstanceFollowRedirects(false);
- connection.addRequestProperty("Cache-Control", "max-stale=60");
-
- if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
- Log.e(TAG, "The responses code is not 200 but " + connection.getResponseCode());
- return new WebContent("", DO_NOT_CACHE_RESULT);
- }
-
- if (connection.getContentLength() > fileSizeLimit) {
- Log.e(TAG, "The content size of the url is larger than " + fileSizeLimit);
- return new WebContent("", DO_NOT_CACHE_RESULT);
- }
-
- Long expireTimeMillis = getExpirationTimeMillisFromHTTPHeader(
- connection.getHeaderFields());
-
- return new WebContent(inputStreamToString(
- connection.getInputStream(), connection.getContentLength(), fileSizeLimit),
- expireTimeMillis);
- } finally {
- if (connection != null) {
- connection.disconnect();
- }
- }
- }
-
- /**
- * Visible for testing.
- * @hide
- */
- public static String inputStreamToString(InputStream inputStream, int length, long sizeLimit)
- throws IOException, AssociationServiceException {
- if (length < 0) {
- length = 0;
- }
- ByteArrayOutputStream baos = new ByteArrayOutputStream(length);
- BufferedInputStream bis = new BufferedInputStream(inputStream);
- byte[] buffer = new byte[INPUT_BUFFER_SIZE_IN_BYTES];
- int len = 0;
- while ((len = bis.read(buffer)) != -1) {
- baos.write(buffer, 0, len);
- if (baos.size() > sizeLimit) {
- throw new AssociationServiceException("The content size of the url is larger than "
- + sizeLimit);
- }
- }
- return baos.toString("UTF-8");
- }
-
- /**
- * Parses the HTTP headers to compute the ttl.
- *
- * @param headers a map that map the header key to the header values. Can be null.
- * @return the ttl in millisecond or null if the ttl is not specified in the header.
- */
- private Long getExpirationTimeMillisFromHTTPHeader(Map<String, List<String>> headers) {
- if (headers == null) {
- return null;
- }
- Map<String, String> joinedHeaders = joinHttpHeaders(headers);
-
- NetworkResponse response = new NetworkResponse(null, joinedHeaders);
- Cache.Entry cachePolicy = HttpHeaderParser.parseCacheHeaders(response);
-
- if (cachePolicy == null) {
- // Cache is disabled, set the expire time to 0.
- return DO_NOT_CACHE_RESULT;
- } else if (cachePolicy.ttl == 0) {
- // Cache policy is not specified, set the expire time to 0.
- return DO_NOT_CACHE_RESULT;
- } else {
- // cachePolicy.ttl is actually the expire timestamp in millisecond.
- return cachePolicy.ttl;
- }
- }
-
- /**
- * Converts an HTTP header map of the format provided by {@linkHttpUrlConnection} to a map of
- * the format accepted by {@link HttpHeaderParser}. It does this by joining all the entries for
- * a given header key with ", ".
- */
- private Map<String, String> joinHttpHeaders(Map<String, List<String>> headers) {
- Map<String, String> joinedHeaders = new HashMap<String, String>();
- for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
- List<String> values = entry.getValue();
- if (values.size() == 1) {
- joinedHeaders.put(entry.getKey(), values.get(0));
- } else {
- joinedHeaders.put(entry.getKey(), Utils.joinStrings(", ", values));
- }
- }
- return joinedHeaders;
- }
-}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/Utils.java b/packages/StatementService/src/com/android/statementservice/retriever/Utils.java
deleted file mode 100644
index afb4c75..0000000
--- a/packages/StatementService/src/com/android/statementservice/retriever/Utils.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.statementservice.retriever;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.Signature;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * Utility library for computing certificate fingerprints. Also includes fields name used by
- * Statement JSON string.
- */
-public final class Utils {
-
- private Utils() {}
-
- /**
- * Field name for namespace.
- */
- public static final String NAMESPACE_FIELD = "namespace";
-
- /**
- * Supported asset namespaces.
- */
- public static final String NAMESPACE_WEB = "web";
- public static final String NAMESPACE_ANDROID_APP = "android_app";
-
- /**
- * Field names in a web asset descriptor.
- */
- public static final String WEB_ASSET_FIELD_SITE = "site";
-
- /**
- * Field names in a Android app asset descriptor.
- */
- public static final String ANDROID_APP_ASSET_FIELD_PACKAGE_NAME = "package_name";
- public static final String ANDROID_APP_ASSET_FIELD_CERT_FPS = "sha256_cert_fingerprints";
-
- /**
- * Field names in a statement.
- */
- public static final String ASSET_DESCRIPTOR_FIELD_RELATION = "relation";
- public static final String ASSET_DESCRIPTOR_FIELD_TARGET = "target";
- public static final String DELEGATE_FIELD_DELEGATE = "include";
-
- private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F' };
-
- /**
- * Joins a list of strings, by placing separator between each string. For example,
- * {@code joinStrings("; ", Arrays.asList(new String[]{"a", "b", "c"}))} returns
- * "{@code a; b; c}".
- */
- public static String joinStrings(String separator, List<String> strings) {
- switch(strings.size()) {
- case 0:
- return "";
- case 1:
- return strings.get(0);
- default:
- StringBuilder joiner = new StringBuilder();
- boolean first = true;
- for (String field : strings) {
- if (first) {
- first = false;
- } else {
- joiner.append(separator);
- }
- joiner.append(field);
- }
- return joiner.toString();
- }
- }
-
- /**
- * Returns the normalized sha-256 fingerprints of a given package according to the Android
- * package manager.
- */
- public static List<String> getCertFingerprintsFromPackageManager(String packageName,
- Context context) throws NameNotFoundException {
- Signature[] signatures = context.getPackageManager().getPackageInfo(packageName,
- PackageManager.GET_SIGNATURES).signatures;
- ArrayList<String> result = new ArrayList<String>(signatures.length);
- for (Signature sig : signatures) {
- result.add(computeNormalizedSha256Fingerprint(sig.toByteArray()));
- }
- return result;
- }
-
- /**
- * Computes the hash of the byte array using the specified algorithm, returning a hex string
- * with a colon between each byte.
- */
- public static String computeNormalizedSha256Fingerprint(byte[] signature) {
- MessageDigest digester;
- try {
- digester = MessageDigest.getInstance("SHA-256");
- } catch (NoSuchAlgorithmException e) {
- throw new AssertionError("No SHA-256 implementation found.");
- }
- digester.update(signature);
- return byteArrayToHexString(digester.digest());
- }
-
- /**
- * Returns true if there is at least one common string between the two lists of string.
- */
- public static boolean hasCommonString(List<String> list1, List<String> list2) {
- HashSet<String> set2 = new HashSet<>(list2);
- for (String string : list1) {
- if (set2.contains(string)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Converts the byte array to an lowercase hexadecimal digits String with a colon character (:)
- * between each byte.
- */
- private static String byteArrayToHexString(byte[] array) {
- if (array.length == 0) {
- return "";
- }
- char[] buf = new char[array.length * 3 - 1];
-
- int bufIndex = 0;
- for (int i = 0; i < array.length; i++) {
- byte b = array[i];
- if (i > 0) {
- buf[bufIndex++] = ':';
- }
- buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
- buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
- }
- return new String(buf);
- }
-}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/WebAsset.java b/packages/StatementService/src/com/android/statementservice/retriever/WebAsset.java
index 947087a..608ce69 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/WebAsset.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/WebAsset.java
@@ -16,6 +16,8 @@
package com.android.statementservice.retriever;
+import com.android.statementservice.utils.StatementUtils;
+
import org.json.JSONObject;
import java.net.MalformedURLException;
@@ -36,7 +38,7 @@
* <p>The only protocol supported now are https and http. If the optional port is not specified,
* the default for each protocol will be used (i.e. 80 for http and 443 for https).
*/
-/* package private */ final class WebAsset extends AbstractAsset {
+public final class WebAsset extends AbstractAsset {
private static final String MISSING_FIELD_FORMAT_STRING = "Expected %s to be set.";
private static final String SCHEME_HTTP = "http";
@@ -73,8 +75,8 @@
public String toJson() {
AssetJsonWriter writer = new AssetJsonWriter();
- writer.writeFieldLower(Utils.NAMESPACE_FIELD, Utils.NAMESPACE_WEB);
- writer.writeFieldLower(Utils.WEB_ASSET_FIELD_SITE, mUrl.toExternalForm());
+ writer.writeFieldLower(StatementUtils.NAMESPACE_FIELD, StatementUtils.NAMESPACE_WEB);
+ writer.writeFieldLower(StatementUtils.WEB_ASSET_FIELD_SITE, mUrl.toExternalForm());
return writer.closeAndGetString();
}
@@ -119,14 +121,14 @@
*/
protected static WebAsset create(JSONObject asset)
throws AssociationServiceException {
- if (asset.optString(Utils.WEB_ASSET_FIELD_SITE).equals("")) {
+ if (asset.optString(StatementUtils.WEB_ASSET_FIELD_SITE).equals("")) {
throw new AssociationServiceException(String.format(MISSING_FIELD_FORMAT_STRING,
- Utils.WEB_ASSET_FIELD_SITE));
+ StatementUtils.WEB_ASSET_FIELD_SITE));
}
URL url;
try {
- url = new URL(asset.optString(Utils.WEB_ASSET_FIELD_SITE));
+ url = new URL(asset.optString(StatementUtils.WEB_ASSET_FIELD_SITE));
} catch (MalformedURLException e) {
throw new AssociationServiceException("Url is not well formatted.", e);
}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/WebContent.java b/packages/StatementService/src/com/android/statementservice/retriever/WebContent.java
index 86a635c..23b1f9b 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/WebContent.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/WebContent.java
@@ -27,10 +27,12 @@
private final String mContent;
private final Long mExpireTimeMillis;
+ private final int mResponseCode;
- public WebContent(String content, Long expireTimeMillis) {
+ public WebContent(String content, Long expireTimeMillis, int responseCode) {
mContent = content;
mExpireTimeMillis = expireTimeMillis;
+ mResponseCode = responseCode;
}
/**
@@ -46,4 +48,8 @@
public String getContent() {
return mContent;
}
+
+ public int getResponseCode() {
+ return mResponseCode;
+ }
}
diff --git a/packages/StatementService/src/com/android/statementservice/utils/AndroidUtils.kt b/packages/StatementService/src/com/android/statementservice/utils/AndroidUtils.kt
new file mode 100644
index 0000000..7fe0a02
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/utils/AndroidUtils.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.statementservice.utils
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.PackageManager
+import android.content.pm.verify.domain.DomainVerificationInfo
+import android.content.pm.verify.domain.DomainVerificationRequest
+import android.content.pm.verify.domain.DomainVerificationUserState
+import com.android.statementservice.domain.DomainVerificationReceiverV1
+import com.android.statementservice.domain.DomainVerificationReceiverV2
+
+// Top level extensions for models to allow Kotlin deconstructing declarations
+
+operator fun DomainVerificationRequest.component1() = packageNames
+
+operator fun DomainVerificationInfo.component1() = identifier
+operator fun DomainVerificationInfo.component2() = packageName
+operator fun DomainVerificationInfo.component3() = hostToStateMap
+
+operator fun DomainVerificationUserState.component1() = identifier
+operator fun DomainVerificationUserState.component2() = packageName
+operator fun DomainVerificationUserState.component3() = user
+operator fun DomainVerificationUserState.component4() = isLinkHandlingAllowed
+operator fun DomainVerificationUserState.component5() = hostToStateMap
+
+object AndroidUtils {
+
+ fun isReceiverV1Enabled(context: Context): Boolean {
+ val receiver = ComponentName(context, DomainVerificationReceiverV1::class.java)
+ return when (context.packageManager.getComponentEnabledSetting(receiver)) {
+ // Must change this if the manifest ever changes
+ PackageManager.COMPONENT_ENABLED_STATE_DEFAULT -> true
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED -> true
+ else -> false
+ }
+ }
+
+ fun isReceiverV2Enabled(context: Context): Boolean {
+ val receiver = ComponentName(context, DomainVerificationReceiverV2::class.java)
+ return when (context.packageManager.getComponentEnabledSetting(receiver)) {
+ // Must change this if the manifest ever changes
+ PackageManager.COMPONENT_ENABLED_STATE_DEFAULT -> false
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED -> true
+ else -> false
+ }
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/utils/Result.kt b/packages/StatementService/src/com/android/statementservice/utils/Result.kt
new file mode 100644
index 0000000..f23a010
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/utils/Result.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.statementservice.utils
+
+sealed class Result<T> {
+
+ fun successValueOrNull() = (this as? Success<T>)?.value
+
+ data class Success<T>(val value: T) : Result<T>()
+ data class Failure<T>(val message: String? = null, val throwable: Throwable? = null) :
+ Result<T>() {
+
+ constructor(message: String) : this(message = message, throwable = null)
+ constructor(throwable: Throwable) : this(message = null, throwable = throwable)
+
+ @Suppress("UNCHECKED_CAST")
+ fun <T> asType() = this as Result<T>
+ }
+}
diff --git a/packages/StatementService/src/com/android/statementservice/utils/StatementUtils.kt b/packages/StatementService/src/com/android/statementservice/utils/StatementUtils.kt
new file mode 100644
index 0000000..92d752c
--- /dev/null
+++ b/packages/StatementService/src/com/android/statementservice/utils/StatementUtils.kt
@@ -0,0 +1,162 @@
+/*
+ * 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.statementservice.utils
+
+import android.content.Context
+import android.content.pm.PackageManager
+import android.util.Patterns
+import com.android.statementservice.retriever.Relation
+import java.net.URL
+import java.security.MessageDigest
+
+internal object StatementUtils {
+
+ /**
+ * Field name for namespace.
+ */
+ const val NAMESPACE_FIELD = "namespace"
+
+ /**
+ * Supported asset namespaces.
+ */
+ const val NAMESPACE_WEB = "web"
+ const val NAMESPACE_ANDROID_APP = "android_app"
+
+ /**
+ * Field names in a web asset descriptor.
+ */
+ const val WEB_ASSET_FIELD_SITE = "site"
+
+ /**
+ * Field names in a Android app asset descriptor.
+ */
+ const val ANDROID_APP_ASSET_FIELD_PACKAGE_NAME = "package_name"
+ const val ANDROID_APP_ASSET_FIELD_CERT_FPS = "sha256_cert_fingerprints"
+
+ /**
+ * Field names in a statement.
+ */
+ const val ASSET_DESCRIPTOR_FIELD_RELATION = "relation"
+ const val ASSET_DESCRIPTOR_FIELD_TARGET = "target"
+ const val DELEGATE_FIELD_DELEGATE = "include"
+
+ val HEX_DIGITS =
+ charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F')
+
+ val RELATION by lazy { Relation.create("delegate_permission/common.handle_all_urls") }
+ private const val ANDROID_ASSET_FORMAT =
+ """{"namespace": "android_app", "package_name": "%s", "sha256_cert_fingerprints": [%s]}"""
+ private const val WEB_ASSET_FORMAT = """{"namespace": "web", "site": "%s"}"""
+
+ private val digesterSha256 by lazy { tryOrNull { MessageDigest.getInstance("SHA-256") } }
+
+ internal inline fun <T> tryOrNull(block: () -> T) =
+ try {
+ block()
+ } catch (ignored: Exception) {
+ null
+ }
+
+ /**
+ * Returns the normalized sha-256 fingerprints of a given package according to the Android
+ * package manager.
+ */
+ fun getCertFingerprintsFromPackageManager(
+ context: Context,
+ packageName: String
+ ): Result<List<String>> {
+ val signingInfo = try {
+ context.packageManager.getPackageInfo(
+ packageName,
+ PackageManager.GET_SIGNING_CERTIFICATES or PackageManager.MATCH_ANY_USER
+ )
+ .signingInfo
+ } catch (e: Exception) {
+ return Result.Failure(e)
+ }
+ return if (signingInfo.hasMultipleSigners()) {
+ signingInfo.apkContentsSigners
+ } else {
+ signingInfo.signingCertificateHistory
+ }.map {
+ val result = computeNormalizedSha256Fingerprint(it.toByteArray())
+ if (result is Result.Failure) {
+ return result.asType()
+ } else {
+ (result as Result.Success).value
+ }
+ }.let { Result.Success(it) }
+ }
+
+ /**
+ * Computes the hash of the byte array using the specified algorithm, returning a hex string
+ * with a colon between each byte.
+ */
+ fun computeNormalizedSha256Fingerprint(signature: ByteArray) =
+ digesterSha256?.digest(signature)
+ ?.let(StatementUtils::bytesToHexString)
+ ?.let { Result.Success(it) }
+ ?: Result.Failure()
+
+ private fun bytesToHexString(bytes: ByteArray): String {
+ val hexChars = CharArray(bytes.size * 3 - 1)
+ var bufIndex = 0
+ for (index in bytes.indices) {
+ val byte = bytes[index].toInt() and 0xFF
+ if (index > 0) {
+ hexChars[bufIndex++] = ':'
+ }
+
+ hexChars[bufIndex++] = HEX_DIGITS[byte ushr 4]
+ hexChars[bufIndex++] = HEX_DIGITS[byte and 0x0F]
+ }
+ return String(hexChars)
+ }
+
+ fun createAndroidAssetString(context: Context, packageName: String): Result<String> {
+ val result = getCertFingerprintsFromPackageManager(context, packageName)
+ if (result is Result.Failure) {
+ return result.asType()
+ }
+ return Result.Success(
+ ANDROID_ASSET_FORMAT.format(
+ packageName,
+ (result as Result.Success).value.joinToString(separator = "\", \"")
+ )
+ )
+ }
+
+ fun createAndroidAsset(packageName: String, certFingerprints: List<String>) =
+ String.format(
+ ANDROID_ASSET_FORMAT,
+ packageName,
+ certFingerprints.joinToString(separator = ", ") { "\"$it\"" })
+
+ fun createWebAssetString(scheme: String, host: String): Result<String> {
+ if (!Patterns.DOMAIN_NAME.matcher(host).matches()) {
+ return Result.Failure("Input host is not valid.")
+ }
+ if (scheme != "http" && scheme != "https") {
+ return Result.Failure("Input scheme is not valid.")
+ }
+ return Result.Success(WEB_ASSET_FORMAT.format(URL(scheme, host, "").toString()))
+ }
+
+ // Hosts with *. for wildcard subdomain support are verified against their root domain
+ fun createWebAssetString(host: String) =
+ WEB_ASSET_FORMAT.format(URL("https", host.removePrefix("*."), "").toString())
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java b/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
index 457e8e6..659b9fe 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
@@ -94,6 +94,16 @@
}
/**
+ * Similar to {@link #getOvershootInterpolation(float, float, float)} but the overshoot
+ * starts immediately here, instead of first having a section of non-overshooting
+ *
+ * @param progress a progress value going from 0 to 1
+ */
+ public static float getOvershootInterpolation(float progress) {
+ return MathUtils.max(0.0f, (float) (1.0f - Math.exp(-4 * progress)));
+ }
+
+ /**
* Interpolate alpha for notifications background scrim during shade expansion.
* @param fraction Shade expansion fraction
* @param forNotification If we want the alpha of the notification shade or the scrim.
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
index 47a373e..298b7c3 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
@@ -87,7 +87,9 @@
interface OnDismissAction {
/**
- * @return {@code true} if the dismiss should be deferred
+ * @return {@code true} if the dismiss should be deferred. When returning true, make sure to
+ * call {@link com.android.keyguard.ViewMediatorCallback#readyForKeyguardDone()}
+ * *after* returning to start hiding the keyguard.
*/
boolean onDismiss();
}
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 6c06b0a..4adb546 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -10,6 +10,11 @@
public void setGlowScale(float);
}
+-keep class com.android.systemui.settings.brightness.BrightnessSliderView {
+ public float getSliderScaleY();
+ public void setSliderScaleY(float);
+}
+
-keep class com.android.systemui.recents.OverviewProxyRecentsImpl
-keep class com.android.systemui.statusbar.car.CarStatusBar
-keep class com.android.systemui.statusbar.phone.StatusBar
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index 7f645ba..31d848d 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -35,43 +35,11 @@
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
- <TextView
- android:id="@+id/logout"
- android:layout_height="@dimen/logout_button_layout_height"
- android:layout_width="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="@dimen/logout_button_margin_bottom"
- android:gravity="center"
- android:paddingLeft="@dimen/logout_button_padding_horizontal"
- android:paddingRight="@dimen/logout_button_padding_horizontal"
- android:background="@drawable/logout_button_background"
- android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
- android:textAllCaps="true"
- android:textColor="?android:attr/textColorPrimary"
- android:textSize="13sp"
- android:text="@*android:string/global_action_logout" />
-
<include
layout="@layout/keyguard_clock_switch"
android:id="@+id/keyguard_clock_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
-
- <TextView
- android:id="@+id/owner_info"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/date_owner_info_margin"
- android:layout_gravity="center_horizontal"
- android:layout_centerHorizontal="true"
- android:textColor="?attr/wallpaperTextColorSecondary"
- android:textSize="@dimen/widget_label_font_size"
- android:letterSpacing="0.05"
- android:ellipsize="marquee"
- android:singleLine="true" />
<FrameLayout
android:id="@+id/status_view_media_container"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index 76ee66b8..0871767 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -136,6 +136,6 @@
<item quantity="one">സിം ഇപ്പോൾ പ്രവർത്തനരഹിതമാക്കി. തുടരുന്നതിന് PUK കോഡ് നൽകുക. സിം ശാശ്വതമായി ഉപയോഗശൂന്യമാകുന്നതിന് മുമ്പായി <xliff:g id="_NUMBER_0">%d</xliff:g> ശ്രമം കൂടി ശേഷിക്കുന്നു. വിശദാംശങ്ങൾക്ക് കാരിയറുമായി ബന്ധപ്പെടുക.</item>
</plurals>
<string name="clock_title_default" msgid="6342735240617459864">"ഡിഫോൾട്ട്"</string>
- <string name="clock_title_bubble" msgid="2204559396790593213">"ബബ്ൾ"</string>
+ <string name="clock_title_bubble" msgid="2204559396790593213">"ബബിൾ"</string>
<string name="clock_title_analog" msgid="8409262532900918273">"അനലോഗ്"</string>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 4ca4c1b..b307544f 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -89,7 +89,7 @@
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM को PIN कोड गलत छ। तपाईंले अब आफ्नो यन्त्र खोल्न आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नै पर्ने हुन्छ।"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM को PIN कोड गलत छ, तपाईं अझै <xliff:g id="NUMBER_1">%d</xliff:g> पटक प्रयास गर्न सक्नुहुन्छ।</item>
- <item quantity="one">SIM को PIN कोड गलत छ,तपाईंले आफ्नो यन्त्र अनलक गर्न आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नैपर्ने अवस्था आउनु अघि तपाईं अझै <xliff:g id="NUMBER_0">%d</xliff:g> पटक प्रयास गर्न सक्नुहुन्छ।</item>
+ <item quantity="one">SIM को PIN कोड गलत छ,तपाईंले आफ्नो डिभाइस अनलक गर्न आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नैपर्ने अवस्था आउनु अघि तपाईं अझै <xliff:g id="NUMBER_0">%d</xliff:g> पटक प्रयास गर्न सक्नुहुन्छ।</item>
</plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM काम नलाग्ने भएको छ। आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।"</string>
<plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886">
@@ -129,7 +129,7 @@
<string name="kg_face_not_recognized" msgid="7903950626744419160">"पहिचान भएन"</string>
<plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
<item quantity="other">SIM को PIN प्रविष्टि गर्नुहोस्। तपाईंसँग <xliff:g id="NUMBER_1">%d</xliff:g> प्रयासहरू बाँकी छन्।</item>
- <item quantity="one">SIM को PIN प्रविष्टि गर्नुहोस्। तपाईंसँग <xliff:g id="NUMBER_0">%d</xliff:g> प्रयास बाँकी छ, त्यसपछि भने आफ्नो यन्त्र अनलक गर्नका लागि तपाईंले अनिवार्य रूपमा आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नु पर्ने हुन्छ।</item>
+ <item quantity="one">SIM को PIN प्रविष्टि गर्नुहोस्। तपाईंसँग <xliff:g id="NUMBER_0">%d</xliff:g> प्रयास बाँकी छ, त्यसपछि भने आफ्नो डिभाइस अनलक गर्नका लागि तपाईंले अनिवार्य रूपमा आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नु पर्ने हुन्छ।</item>
</plurals>
<plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935">
<item quantity="other">SIM लाई असक्षम पारिएको छ। जारी राख्न PUK कोड प्रविष्टि गर्नुहोस्। तपाईंसँग <xliff:g id="_NUMBER_1">%d</xliff:g> प्रयासहरू बाँकी छन्, त्यसपछि SIM सदाका लागि प्रयोग गर्न नमिल्ने हुन्छ। विवरणहरूका लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।</item>
diff --git a/packages/SystemUI/res-product/values-ky/strings.xml b/packages/SystemUI/res-product/values-ky/strings.xml
index 4eb90caa..00265a1 100644
--- a/packages/SystemUI/res-product/values-ky/strings.xml
+++ b/packages/SystemUI/res-product/values-ky/strings.xml
@@ -26,18 +26,18 @@
<string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Планшетте SIM-карта жок."</string>
<string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Телефондо SIM-карта жок."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-коддор дал келген жок"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул планшет баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул телефон баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул планшет баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет жасадыңыз. Бул телефон баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул планшет баштапкы абалга келтирилип, андагы бардык нерселер өчүрүлөт."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул телефон баштапкы абалга келтирилип, андагы бардык нерселер өчүрүлөт."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул планшет баштапкы абалга келтирилип, андагы бардык нерселер өчүрүлөт."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет жасадыңыз. Бул телефон баштапкы абалга келтирилип, андагы бардык нерселер өчүрүлөт."</string>
<string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
<string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
<string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
<string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
- <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Планшетиңиздин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат өчүрүлөт."</string>
- <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат өчүрүлөт."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат өчүрүлөт."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат өчүрүлөт."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Планшетиңиздин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык нерселер өчүрүлөт."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык нерселер өчүрүлөт."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык нерселер өчүрүлөт."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык нерселер өчүрүлөт."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин планшетиңизди бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин телефонуңузду бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Дагы башка параметрлерди көрүү үчүн телефонуңуздун кулпусун ачыңыз"</string>
diff --git a/packages/SystemUI/res/drawable/people_space_activity_card.xml b/packages/SystemUI/res/drawable/people_space_activity_card.xml
index 338bff8..7e2db63 100644
--- a/packages/SystemUI/res/drawable/people_space_activity_card.xml
+++ b/packages/SystemUI/res/drawable/people_space_activity_card.xml
@@ -14,5 +14,5 @@
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="?android:attr/colorBackgroundFloating" />
+ <solid android:color="@color/people_tile_background" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_content_background.xml b/packages/SystemUI/res/drawable/people_space_content_background.xml
index 30519ae..9704871 100644
--- a/packages/SystemUI/res/drawable/people_space_content_background.xml
+++ b/packages/SystemUI/res/drawable/people_space_content_background.xml
@@ -15,6 +15,6 @@
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/people_tile_background" />
<corners android:radius="@dimen/people_space_image_radius" />
</shape>
diff --git a/packages/SystemUI/res/drawable/people_space_new_story_outline.xml b/packages/SystemUI/res/drawable/people_space_new_story_outline.xml
index a1737f9..4d6249d 100644
--- a/packages/SystemUI/res/drawable/people_space_new_story_outline.xml
+++ b/packages/SystemUI/res/drawable/people_space_new_story_outline.xml
@@ -15,6 +15,6 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/people_tile_background" />
<stroke android:width="2dp" android:color="?android:attr/colorAccent" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_rounded_border.xml b/packages/SystemUI/res/drawable/people_space_rounded_border.xml
index 9956bc2..50560df 100644
--- a/packages/SystemUI/res/drawable/people_space_rounded_border.xml
+++ b/packages/SystemUI/res/drawable/people_space_rounded_border.xml
@@ -15,5 +15,5 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/people_tile_background" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_tile_view_card.xml b/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
index 8fd4388..6e1e5de 100644
--- a/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
+++ b/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
@@ -14,6 +14,6 @@
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/people_tile_background" />
<corners android:radius="@dimen/people_space_widget_radius" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_tile_empty_background.xml b/packages/SystemUI/res/drawable/people_tile_empty_background.xml
index 2dac740..7dbea73 100644
--- a/packages/SystemUI/res/drawable/people_tile_empty_background.xml
+++ b/packages/SystemUI/res/drawable/people_tile_empty_background.xml
@@ -14,8 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <solid android:color="?androidprv:attr/colorSurface" />
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/people_tile_background" />
<corners android:radius="@dimen/people_space_widget_radius" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/screenshot_border.xml b/packages/SystemUI/res/drawable/screenshot_border.xml
index bb858db..c1accdc 100644
--- a/packages/SystemUI/res/drawable/screenshot_border.xml
+++ b/packages/SystemUI/res/drawable/screenshot_border.xml
@@ -19,5 +19,5 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
<solid android:color="?androidprv:attr/colorSurface"/>
- <corners android:radius="20dp"/>
+ <corners android:radius="24dp"/>
</shape>
diff --git a/packages/SystemUI/res/drawable/screenshot_edit_background.xml b/packages/SystemUI/res/drawable/screenshot_edit_background.xml
index 5c3c12c..ff5c62e 100644
--- a/packages/SystemUI/res/drawable/screenshot_edit_background.xml
+++ b/packages/SystemUI/res/drawable/screenshot_edit_background.xml
@@ -20,7 +20,7 @@
android:color="?android:textColorPrimary">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
- <solid android:color="?androidprv:attr/colorAccentSecondary"/>
+ <solid android:color="?androidprv:attr/colorAccentPrimary"/>
<corners android:radius="16dp"/>
</shape>
</item>
diff --git a/packages/SystemUI/res/drawable/screenshot_save_background.xml b/packages/SystemUI/res/drawable/screenshot_save_background.xml
index cfd2dc2..b61b28e 100644
--- a/packages/SystemUI/res/drawable/screenshot_save_background.xml
+++ b/packages/SystemUI/res/drawable/screenshot_save_background.xml
@@ -20,7 +20,7 @@
android:color="?android:textColorPrimary">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
- <solid android:color="?androidprv:attr/colorAccentSecondary"/>
+ <solid android:color="?androidprv:attr/colorAccentPrimary"/>
<corners android:radius="20dp"/>
</shape>
</item>
diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml
index 5f83f45..5d80da8 100644
--- a/packages/SystemUI/res/layout/controls_base_item.xml
+++ b/packages/SystemUI/res/layout/controls_base_item.xml
@@ -25,8 +25,7 @@
android:focusable="true"
android:screenReaderFocusable="true"
android:stateListAnimator="@anim/control_state_list_animator"
- android:layout_marginLeft="@dimen/control_base_item_margin"
- android:layout_marginRight="@dimen/control_base_item_margin"
+ android:layout_marginStart="@dimen/control_spacing"
android:background="@drawable/control_background">
<ImageView
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index 5bd181c..93bd581 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -21,6 +21,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
+ android:id="@+id/screenshot_scrolling_scrim"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"/>
+ <ImageView
android:id="@+id/global_screenshot_actions_background"
android:layout_height="@dimen/screenshot_bg_protection_height"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/global_screenshot_static.xml b/packages/SystemUI/res/layout/global_screenshot_static.xml
index 60dbaf9..ba46edc 100644
--- a/packages/SystemUI/res/layout/global_screenshot_static.xml
+++ b/packages/SystemUI/res/layout/global_screenshot_static.xml
@@ -71,7 +71,7 @@
android:background="@drawable/screenshot_border"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toStartOf="@+id/screenshot_preview_end"
+ app:layout_constraintEnd_toEndOf="@+id/screenshot_preview_end"
app:layout_constraintTop_toTopOf="@+id/screenshot_preview_top"/>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/screenshot_preview_end"
@@ -91,8 +91,7 @@
android:id="@+id/global_screenshot_preview"
android:visibility="invisible"
android:layout_width="@dimen/global_screenshot_x_scale"
- android:layout_marginStart="4dp"
- android:layout_marginBottom="4dp"
+ android:layout_margin="4dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:elevation="@dimen/screenshot_preview_elevation"
@@ -101,7 +100,9 @@
android:background="@drawable/screenshot_preview_background"
android:adjustViewBounds="true"
app:layout_constraintBottom_toBottomOf="@+id/global_screenshot_preview_border"
- app:layout_constraintStart_toStartOf="@+id/global_screenshot_preview_border">
+ app:layout_constraintStart_toStartOf="@+id/global_screenshot_preview_border"
+ app:layout_constraintEnd_toEndOf="@+id/global_screenshot_preview_border"
+ app:layout_constraintTop_toTopOf="@+id/global_screenshot_preview_border">
</ImageView>
<FrameLayout
android:id="@+id/global_screenshot_dismiss_button"
@@ -121,4 +122,12 @@
android:layout_margin="@dimen/screenshot_dismiss_button_margin"
android:src="@drawable/screenshot_cancel"/>
</FrameLayout>
+ <ImageView
+ android:id="@+id/screenshot_scrollable_preview"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="matrix"
+ app:layout_constraintStart_toStartOf="@id/global_screenshot_preview"
+ app:layout_constraintTop_toTopOf="@id/global_screenshot_preview"
+ android:elevation="@dimen/screenshot_preview_elevation"/>
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 80b7d1f..e40138e 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -80,8 +80,8 @@
<ImageView
android:id="@+id/wallet_button"
- android:layout_height="@dimen/keyguard_affordance_height"
- android:layout_width="@dimen/keyguard_affordance_width"
+ android:layout_height="@dimen/keyguard_affordance_wallet_height"
+ android:layout_width="@dimen/keyguard_affordance_wallet_width"
android:layout_gravity="bottom|end"
android:scaleType="center"
android:tint="?android:attr/textColorPrimary"
diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml
index 8e30aec..4765b44 100644
--- a/packages/SystemUI/res/layout/long_screenshot.xml
+++ b/packages/SystemUI/res/layout/long_screenshot.xml
@@ -62,6 +62,7 @@
android:paddingHorizontal="48dp"
android:paddingTop="8dp"
android:paddingBottom="42dp"
+ android:alpha="0"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
app:layout_constraintTop_toBottomOf="@id/save"
@@ -72,6 +73,16 @@
tools:minHeight="100dp"
tools:minWidth="100dp" />
+ <ImageView
+ android:id="@+id/enter_transition"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="matrix"
+ app:layout_constraintTop_toTopOf="@id/preview"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ android:transitionName="screenshot_preview_image"/>
+
<com.android.systemui.screenshot.CropView
android:id="@+id/crop_view"
android:layout_width="0px"
@@ -86,7 +97,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:handleThickness="@dimen/screenshot_crop_handle_thickness"
- app:handleColor="?androidprv:attr/colorAccentSecondary"
+ app:handleColor="?androidprv:attr/colorAccentPrimary"
app:scrimColor="@color/screenshot_crop_scrim"
tools:background="?android:colorBackground"
tools:minHeight="100dp"
@@ -128,7 +139,7 @@
android:id="@+id/transition"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- app:layout_constraintTop_toBottomOf="@id/save"
+ app:layout_constraintTop_toTopOf="@id/preview"
app:layout_constraintStart_toStartOf="parent"
android:scaleType="centerCrop"
android:visibility="invisible"
diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
index 9a57589..645dba4 100644
--- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
+++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
@@ -63,71 +63,107 @@
android:breakStrategy="balanced"
android:hyphenationFrequency="none"/>
- <ImageView
- android:id="@+id/media_cover1"
+ <FrameLayout
+ android:id="@+id/media_cover1_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
+ android:background="@drawable/qs_media_light_source">
+ <ImageView
+ android:id="@+id/media_cover1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:adjustViewBounds="true"
+ android:background="@drawable/bg_smartspace_media_item"
+ style="@style/MediaPlayer.Album"
+ android:clipToOutline="true"
+ android:scaleType="centerCrop"/>
+ </FrameLayout>
- <ImageView
- android:id="@+id/media_cover2"
+ <FrameLayout
+ android:id="@+id/media_cover2_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
+ android:background="@drawable/qs_media_light_source">
+ <ImageView
+ android:id="@+id/media_cover2"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:adjustViewBounds="true"
+ android:background="@drawable/bg_smartspace_media_item"
+ style="@style/MediaPlayer.Album"
+ android:clipToOutline="true"
+ android:scaleType="centerCrop"/>
+ </FrameLayout>
- <ImageView
- android:id="@+id/media_cover3"
+ <FrameLayout
+ android:id="@+id/media_cover3_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
+ android:background="@drawable/qs_media_light_source">
+ <ImageView
+ android:id="@+id/media_cover3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:adjustViewBounds="true"
+ android:background="@drawable/bg_smartspace_media_item"
+ style="@style/MediaPlayer.Album"
+ android:clipToOutline="true"
+ android:scaleType="centerCrop"/>
+ </FrameLayout>
- <ImageView
- android:id="@+id/media_cover4"
+ <FrameLayout
+ android:id="@+id/media_cover4_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
+ android:background="@drawable/qs_media_light_source">
+ <ImageView
+ android:id="@+id/media_cover4"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:adjustViewBounds="true"
+ android:background="@drawable/bg_smartspace_media_item"
+ style="@style/MediaPlayer.Album"
+ android:clipToOutline="true"
+ android:scaleType="centerCrop"/>
+ </FrameLayout>
- <ImageView
- android:id="@+id/media_cover5"
+ <FrameLayout
+ android:id="@+id/media_cover5_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
+ android:background="@drawable/qs_media_light_source">
+ <ImageView
+ android:id="@+id/media_cover5"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:adjustViewBounds="true"
+ android:background="@drawable/bg_smartspace_media_item"
+ style="@style/MediaPlayer.Album"
+ android:clipToOutline="true"
+ android:scaleType="centerCrop"/>
+ </FrameLayout>
- <ImageView
- android:id="@+id/media_cover6"
+ <FrameLayout
+ android:id="@+id/media_cover6_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
+ android:background="@drawable/qs_media_light_source">
+ <ImageView
+ android:id="@+id/media_cover6"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:adjustViewBounds="true"
+ android:background="@drawable/bg_smartspace_media_item"
+ style="@style/MediaPlayer.Album"
+ android:clipToOutline="true"
+ android:scaleType="centerCrop"/>
+ </FrameLayout>
<!-- Long press menu -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="20dp"
+ android:layout_marginTop="@dimen/qs_media_padding"
android:layout_marginStart="@dimen/qs_media_padding"
android:layout_marginEnd="@dimen/qs_media_padding"
android:id="@+id/remove_text"
@@ -150,7 +186,6 @@
android:layout_marginStart="@dimen/qs_media_padding"
android:layout_marginEnd="@dimen/qs_media_info_spacing"
android:layout_marginBottom="@dimen/qs_media_padding"
- android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
@@ -164,6 +199,7 @@
android:id="@+id/settings_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center|bottom"
style="@style/MediaPlayer.OutlineButton"
android:text="@string/controls_media_settings_button" />
</FrameLayout>
@@ -176,7 +212,6 @@
android:layout_marginStart="@dimen/qs_media_info_spacing"
android:layout_marginEnd="@dimen/qs_media_info_spacing"
android:layout_marginBottom="@dimen/qs_media_padding"
- android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
@@ -188,6 +223,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center|bottom"
style="@style/MediaPlayer.OutlineButton"
android:text="@string/cancel" />
</FrameLayout>
@@ -200,7 +236,6 @@
android:layout_marginStart="@dimen/qs_media_info_spacing"
android:layout_marginEnd="@dimen/qs_media_padding"
android:layout_marginBottom="@dimen/qs_media_padding"
- android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
@@ -212,6 +247,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center|bottom"
style="@style/MediaPlayer.OutlineButton"
android:text="@string/controls_media_dismiss_button"
/>
diff --git a/packages/SystemUI/res/layout/media_view.xml b/packages/SystemUI/res/layout/media_view.xml
index 10bdaaa..c341f73 100644
--- a/packages/SystemUI/res/layout/media_view.xml
+++ b/packages/SystemUI/res/layout/media_view.xml
@@ -135,7 +135,8 @@
android:forceHasOverlappingRendering="false">
<LinearLayout
android:layout_width="wrap_content"
- android:layout_height="@dimen/qs_seamless_height"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/qs_seamless_height"
android:theme="@style/MediaPlayer.SolidButton"
android:background="@drawable/qs_media_seamless_background"
android:orientation="horizontal"
@@ -153,11 +154,12 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="4dp"
- android:fontFamily="@*android:string/config_headlineFontFamily"
+ android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:singleLine="true"
android:text="@*android:string/ext_media_seamless_action"
android:textDirection="locale"
- android:textSize="12sp" />
+ android:textSize="12sp"
+ android:lineHeight="16sp" />
</LinearLayout>
</LinearLayout>
@@ -215,7 +217,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="20dp"
+ android:layout_marginTop="@dimen/qs_media_padding"
android:layout_marginStart="@dimen/qs_media_padding"
android:layout_marginEnd="@dimen/qs_media_padding"
android:id="@+id/remove_text"
@@ -238,7 +240,6 @@
android:layout_marginStart="@dimen/qs_media_padding"
android:layout_marginEnd="@dimen/qs_media_info_spacing"
android:layout_marginBottom="@dimen/qs_media_padding"
- android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
@@ -252,6 +253,7 @@
android:id="@+id/settings_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center|bottom"
style="@style/MediaPlayer.OutlineButton"
android:text="@string/controls_media_settings_button" />
</FrameLayout>
@@ -264,7 +266,6 @@
android:layout_marginStart="@dimen/qs_media_info_spacing"
android:layout_marginEnd="@dimen/qs_media_info_spacing"
android:layout_marginBottom="@dimen/qs_media_padding"
- android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
@@ -276,6 +277,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center|bottom"
style="@style/MediaPlayer.OutlineButton"
android:text="@string/cancel" />
</FrameLayout>
@@ -288,7 +290,6 @@
android:layout_marginStart="@dimen/qs_media_info_spacing"
android:layout_marginEnd="@dimen/qs_media_padding"
android:layout_marginBottom="@dimen/qs_media_padding"
- android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
@@ -300,6 +301,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center|bottom"
style="@style/MediaPlayer.OutlineButton"
android:text="@string/controls_media_dismiss_button"
/>
diff --git a/packages/SystemUI/res/layout/people_space_initial_layout.xml b/packages/SystemUI/res/layout/people_space_initial_layout.xml
index ec29d18..c57ec34 100644
--- a/packages/SystemUI/res/layout/people_space_initial_layout.xml
+++ b/packages/SystemUI/res/layout/people_space_initial_layout.xml
@@ -47,7 +47,7 @@
android:id="@+id/name"
android:paddingTop="2dp"
android:text="@string/empty_user_name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp"
android:maxLines="1"
@@ -59,7 +59,7 @@
<TextView
android:text="@string/status_before_loading"
android:textColor="?android:attr/textColorPrimary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textSize="12sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/people_space_placeholder_layout.xml b/packages/SystemUI/res/layout/people_space_placeholder_layout.xml
index abb771b..061b0d9 100644
--- a/packages/SystemUI/res/layout/people_space_placeholder_layout.xml
+++ b/packages/SystemUI/res/layout/people_space_placeholder_layout.xml
@@ -34,7 +34,7 @@
<LinearLayout
android:orientation="vertical"
android:paddingEnd="20dp"
- android:gravity="bottom"
+ android:gravity="start|bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
@@ -47,7 +47,7 @@
android:id="@+id/name"
android:paddingTop="2dp"
android:text="@string/empty_user_name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp"
android:maxLines="1"
@@ -59,7 +59,7 @@
<TextView
android:text="@string/empty_status"
android:textColor="?android:attr/textColorPrimary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textSize="12sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/people_space_widget_item.xml b/packages/SystemUI/res/layout/people_space_widget_item.xml
index 170386f..17d0c56 100644
--- a/packages/SystemUI/res/layout/people_space_widget_item.xml
+++ b/packages/SystemUI/res/layout/people_space_widget_item.xml
@@ -68,7 +68,7 @@
<TextView
android:id="@+id/name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
android:maxLines="1"
@@ -79,7 +79,7 @@
<TextView
android:id="@+id/status"
android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:paddingVertical="2dp"
android:textSize="12sp"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/people_tile_large_empty.xml b/packages/SystemUI/res/layout/people_tile_large_empty.xml
index 2c6acbc..d4a8e15 100644
--- a/packages/SystemUI/res/layout/people_tile_large_empty.xml
+++ b/packages/SystemUI/res/layout/people_tile_large_empty.xml
@@ -41,14 +41,14 @@
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/name_text_size_for_large" />
<TextView
android:id="@+id/last_interaction"
android:text="@string/empty_status"
android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textSize="@dimen/content_text_size_for_large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/people_tile_large_with_content.xml b/packages/SystemUI/res/layout/people_tile_large_with_content.xml
index b7e86a3..3f78fe7 100644
--- a/packages/SystemUI/res/layout/people_tile_large_with_content.xml
+++ b/packages/SystemUI/res/layout/people_tile_large_with_content.xml
@@ -52,7 +52,7 @@
android:layout_alignParentEnd="true"
android:paddingStart="8dp"
android:paddingEnd="8dp"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?androidprv:attr/textColorOnAccent"
android:background="@drawable/people_space_messages_count_background"
android:textSize="14sp"
@@ -81,9 +81,9 @@
android:singleLine="true"
android:ellipsize="end"
android:text="@string/empty_user_name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorPrimary"
- android:textSize="@dimen/name_text_size_for_content" />
+ android:textSize="@dimen/name_text_size_for_large_content" />
<LinearLayout
android:id="@+id/content"
@@ -102,7 +102,7 @@
<ImageView
android:id="@+id/predefined_icon"
- android:tint="?android:attr/textColorTertiary"
+ android:tint="?android:attr/textColorSecondary"
android:gravity="start|center_vertical"
android:layout_width="@dimen/regular_predefined_icon"
android:layout_height="@dimen/regular_predefined_icon" />
@@ -117,11 +117,10 @@
android:ellipsize="end"
android:singleLine="true"
android:text="@string/empty_user_name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorSecondary"
android:textSize="12sp" />
</LinearLayout>
-
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
@@ -139,7 +138,7 @@
android:maxLines="2"
android:singleLine="false"
android:text="@string/empty_status"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/content_text_size_for_large" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/people_tile_medium_empty.xml b/packages/SystemUI/res/layout/people_tile_medium_empty.xml
index 8b2fddc..ebb61c9 100644
--- a/packages/SystemUI/res/layout/people_tile_medium_empty.xml
+++ b/packages/SystemUI/res/layout/people_tile_medium_empty.xml
@@ -53,7 +53,7 @@
<TextView
android:id="@+id/name"
android:text="@string/empty_user_name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/empty_name_text_size_for_medium"
android:maxLines="1"
@@ -64,7 +64,7 @@
android:id="@+id/last_interaction"
android:text="@string/empty_status"
android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textSize="@dimen/content_text_size_for_medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
index 1086a13..0a5bf1d 100644
--- a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
+++ b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
@@ -70,7 +70,7 @@
<TextView
android:id="@+id/subtext"
android:text="@string/empty_user_name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorSecondary"
android:textSize="12sp"
android:paddingBottom="8dp"
@@ -90,7 +90,7 @@
<TextView
android:id="@+id/text_content"
android:text="@string/empty_status"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/content_text_size_for_medium"
android:layout_width="match_parent"
@@ -113,22 +113,25 @@
android:id="@+id/name"
android:layout_gravity="start|center_vertical"
android:gravity="start|center_vertical"
- android:layout_weight="1"
android:text="@string/empty_user_name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorPrimary"
- android:textSize="@dimen/name_text_size_for_content"
+ android:textSize="@dimen/name_text_size_for_medium_content"
android:singleLine="true"
android:ellipsize="end"
android:paddingEnd="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
+ android:layout_weight="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <TextView
android:id="@+id/messages_count"
android:gravity="end"
android:paddingStart="8dp"
android:paddingEnd="8dp"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?androidprv:attr/textColorOnAccent"
android:background="@drawable/people_space_messages_count_background"
android:textSize="14sp"
@@ -140,7 +143,7 @@
/>
<ImageView
android:id="@+id/predefined_icon"
- android:tint="?android:attr/textColorTertiary"
+ android:tint="?android:attr/textColorSecondary"
android:gravity="end|center_vertical"
android:layout_width="@dimen/regular_predefined_icon"
android:layout_height="@dimen/regular_predefined_icon" />
diff --git a/packages/SystemUI/res/layout/people_tile_small.xml b/packages/SystemUI/res/layout/people_tile_small.xml
index 22fcd3b..553b8a43 100644
--- a/packages/SystemUI/res/layout/people_tile_small.xml
+++ b/packages/SystemUI/res/layout/people_tile_small.xml
@@ -40,7 +40,7 @@
<ImageView
android:id="@+id/predefined_icon"
- android:tint="?android:attr/textColorTertiary"
+ android:tint="?android:attr/textColorSecondary"
android:layout_gravity="center"
android:layout_width="18dp"
android:layout_height="22dp" />
@@ -50,7 +50,7 @@
android:layout_gravity="center"
android:gravity="center"
android:paddingHorizontal="8dp"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?androidprv:attr/textColorOnAccent"
android:background="@drawable/people_space_messages_count_background"
android:textSize="@dimen/name_text_size_for_small"
@@ -69,7 +69,7 @@
android:ellipsize="end"
android:maxLines="1"
android:paddingHorizontal="4dp"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/name_text_size_for_small" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 0a9feb8..317dbc0 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -106,11 +106,25 @@
android:scaleType="centerInside" />
</com.android.systemui.statusbar.phone.MultiUserSwitch>
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/pm_lite"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
+ android:layout_weight="1"
+ android:background="@drawable/qs_footer_action_chip_background"
+ android:clickable="true"
+ android:clipToPadding="false"
+ android:focusable="true"
+ android:padding="@dimen/qs_footer_icon_padding"
+ android:src="@*android:drawable/ic_lock_power_off"
+ android:contentDescription="@string/accessibility_quick_settings_power_menu"
+ android:tint="?android:attr/textColorPrimary" />
+
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/settings_button_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
android:background="@drawable/qs_footer_action_chip_background"
android:layout_weight="1"
android:clipChildren="false"
@@ -140,20 +154,6 @@
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/pm_lite"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_weight="1"
- android:background="@drawable/qs_footer_action_chip_background"
- android:clickable="true"
- android:clipToPadding="false"
- android:focusable="true"
- android:padding="@dimen/qs_footer_icon_padding"
- android:src="@*android:drawable/ic_lock_power_off"
- android:contentDescription="@string/accessibility_quick_settings_power_menu"
- android:tint="?android:attr/textColorPrimary" />
-
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
index d0e3d3c..51cab0a 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
@@ -29,12 +29,12 @@
android:paddingTop="@dimen/status_bar_padding_top"
android:minHeight="48dp">
- <LinearLayout
+ <FrameLayout
+ android:id="@+id/date_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:minHeight="48dp"
android:layout_weight="1"
- android:orientation="horizontal"
android:gravity="center_vertical|start" >
<com.android.systemui.statusbar.policy.DateView
@@ -46,7 +46,7 @@
android:singleLine="true"
android:textAppearance="@style/TextAppearance.QS.Status"
systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
- </LinearLayout>
+ </FrameLayout>
<android.widget.Space
android:id="@+id/space"
@@ -59,21 +59,22 @@
<FrameLayout
android:id="@+id/header_text_container"
android:layout_height="match_parent"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:gravity="center"
/>
- <LinearLayout
+ <FrameLayout
+ android:id="@+id/privacy_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:minHeight="48dp"
android:layout_weight="1"
- android:orientation="horizontal"
android:gravity="center_vertical|end" >
<include layout="@layout/ongoing_privacy_chip" />
- </LinearLayout>
+ </FrameLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/udfps_enroll_view.xml b/packages/SystemUI/res/layout/udfps_enroll_view.xml
index a55653e..f1ff6d6 100644
--- a/packages/SystemUI/res/layout/udfps_enroll_view.xml
+++ b/packages/SystemUI/res/layout/udfps_enroll_view.xml
@@ -24,5 +24,6 @@
<ImageView
android:id="@+id/udfps_enroll_animation_fp_view"
android:layout_width="match_parent"
- android:layout_height="match_parent"/>
+ android:layout_height="match_parent"
+ android:contentDescription="@string/accessibility_fingerprint_label"/>
</com.android.systemui.biometrics.UdfpsEnrollView>
diff --git a/packages/SystemUI/res/layout/udfps_view.xml b/packages/SystemUI/res/layout/udfps_view.xml
index e5e8fe6..687830d 100644
--- a/packages/SystemUI/res/layout/udfps_view.xml
+++ b/packages/SystemUI/res/layout/udfps_view.xml
@@ -20,7 +20,7 @@
android:id="@+id/udfps_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- systemui:sensorTouchAreaCoefficient="0.5"
+ systemui:sensorTouchAreaCoefficient="0.75"
android:contentDescription="@string/accessibility_fingerprint_label">
<ViewStub
diff --git a/packages/SystemUI/res/layout/volume_ringer_drawer.xml b/packages/SystemUI/res/layout/volume_ringer_drawer.xml
index 9b6c92c..1112bcd 100644
--- a/packages/SystemUI/res/layout/volume_ringer_drawer.xml
+++ b/packages/SystemUI/res/layout/volume_ringer_drawer.xml
@@ -59,7 +59,7 @@
android:id="@+id/volume_drawer_vibrate"
android:layout_width="@dimen/volume_ringer_drawer_item_size"
android:layout_height="@dimen/volume_ringer_drawer_item_size"
- android:description="@string/volume_ringer_hint_vibrate"
+ android:contentDescription="@string/volume_ringer_hint_vibrate"
android:gravity="center">
<ImageView
@@ -76,7 +76,7 @@
android:id="@+id/volume_drawer_mute"
android:layout_width="@dimen/volume_ringer_drawer_item_size"
android:layout_height="@dimen/volume_ringer_drawer_item_size"
- android:description="@string/volume_ringer_hint_mute"
+ android:contentDescription="@string/volume_ringer_hint_mute"
android:gravity="center">
<ImageView
@@ -93,7 +93,7 @@
android:id="@+id/volume_drawer_normal"
android:layout_width="@dimen/volume_ringer_drawer_item_size"
android:layout_height="@dimen/volume_ringer_drawer_item_size"
- android:description="@string/volume_ringer_hint_unmute"
+ android:contentDescription="@string/volume_ringer_hint_unmute"
android:gravity="center">
<ImageView
@@ -117,7 +117,7 @@
android:layout_width="@dimen/volume_ringer_drawer_item_size"
android:layout_height="@dimen/volume_ringer_drawer_item_size"
android:layout_gravity="bottom|right"
- android:description="@string/volume_ringer_change"
+ android:contentDescription="@string/volume_ringer_change"
android:background="@drawable/volume_drawer_selection_bg">
<ImageView
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index aa99744..2149371 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Wekker"</string>
<string name="wallet_title" msgid="5369767670735827105">"Beursie"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Stel op om vinniger, veiliger aankope met jou foon te doen"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Wys alles"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Ontsluit om te betaal"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nie opgestel nie"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Maak toe"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Hervat"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Instellings"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> deur <xliff:g id="ARTIST_NAME">%2$s</xliff:g> speel tans vanaf <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Speel"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Maak <xliff:g id="APP_LABEL">%1$s</xliff:g> oop"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Speel <xliff:g id="SONG_NAME">%1$s</xliff:g> deur <xliff:g id="ARTIST_NAME">%2$s</xliff:g> vanaf <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Speel <xliff:g id="SONG_NAME">%1$s</xliff:g> vanaf <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Onaktief, gaan program na"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fout, probeer tans weer …"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nie gekry nie"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 3d2e6b2..fe3cc8e 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ኤተርኔት"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"ማንቂያ"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"በስልክዎ በመጠቀም ፈጣን እና የበለጠ ደህንነቱ በተጠበቀ መንገድ ግዢዎችን ለመፈጸም ዝግጁ ይሁኑ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ሁሉንም አሳይ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ለመክፈል ይክፈቱ"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"አልተዋቀረም"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"አሰናብት"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ከቆመበት ቀጥል"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ቅንብሮች"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> በ<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ከ<xliff:g id="APP_LABEL">%3$s</xliff:g> እየተጫወተ ነው"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"አጫውት"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ክፈት"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> በ<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ከ<xliff:g id="APP_LABEL">%3$s</xliff:g> ያጫውቱ"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ከ<xliff:g id="APP_LABEL">%2$s</xliff:g> ያጫውቱ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ንቁ ያልኾነ፣ መተግበሪያን ይፈትሹ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ስህተት፣ እንደገና በመሞከር ላይ…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"አልተገኘም"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index bd9e64b..83b483e 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -117,7 +117,7 @@
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"إلغاء"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"مشاركة"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"تمّ إلغاء تسجيل الشاشة."</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"تم حفظ تسجيل الشاشة."</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"تم حفظ تسجيل الشاشة"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"انقر لعرض التسجيل."</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"حدث خطأ أثناء حذف تسجيل الشاشة."</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"تعذّر الحصول على أذونات."</string>
@@ -621,7 +621,7 @@
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"يؤدي هذا الإجراء إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. لإلغاء تثبيت الشاشة على هذا التطبيق، اسحب بسرعة للأعلى مع إبقاء الإصبع على الشاشة."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار زر \"نظرة عامة\" لإزالة التثبيت."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار زر \"الشاشة الرئيسية\" لإزالة التثبيت."</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"يمكن الوصول إلى البيانات الشخصية (مثلاً جهات الاتصال ومحتوى الرسائل الإلكترونية)"</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"يمكن الوصول إلى البيانات الشخصية (مثلاً جهات الاتصال ومحتوى الرسائل الإلكترونية)."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"عند تثبيت الشاشة على تطبيق معيّن، سيظل بإمكان التطبيق فتح تطبيقات أخرى."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"لإلغاء تثبيت الشاشة على هذا التطبيق، المس مع الاستمرار زرّي \"الرجوع\" و\"لمحة عامة\" (رمز المربّع)."</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"لإلغاء تثبيت الشاشة على هذا التطبيق، المس مع الاستمرار زرّي \"الرجوع\" و\"الشاشة الرئيسية\"."</string>
@@ -678,6 +678,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"إيثرنت"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"المنبّه"</string>
<string name="wallet_title" msgid="5369767670735827105">"المحفظة"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"يمكنك إعداد طريقة دفع لإجراء عمليات شراء بسرعة وأمان أكبر باستخدام هاتفك."</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"عرض الكل"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"فتح القفل للدفع"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"لم يتم الإعداد."</string>
@@ -744,7 +745,7 @@
<string name="notification_automatic_title" msgid="3745465364578762652">"تلقائي"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"بدون صوت أو اهتزاز"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"بدون صوت أو اهتزاز وتظهر في موضع أسفل في قسم المحادثات"</string>
- <string name="notification_channel_summary_default" msgid="3282930979307248890">"يمكن إصدار رنين أو اهتزاز بناءً على إعدادات الهاتف"</string>
+ <string name="notification_channel_summary_default" msgid="3282930979307248890">"يمكن إصدار رنين أو اهتزاز بناءً على إعدادات الهاتف."</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"يمكن إصدار رنين أو اهتزاز بناءً على إعدادات الهاتف. تظهر المحادثات من <xliff:g id="APP_NAME">%1$s</xliff:g> كفقاعات تلقائيًا."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"يلفِت هذا الإشعار انتباهك لهذا المحتوى باستخدام اختصار عائم."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"السماح للنظام بتحديد ما إذا يجب اهتزاز الجهاز أو إصدار رنين عند تلقّي هذا الإشعار"</string>
@@ -1079,7 +1080,7 @@
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"إزالة من المفضّلة"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"نقل إلى الموضع <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"عناصر التحكّم"</string>
- <string name="controls_favorite_subtitle" msgid="6481675111056961083">"اختيار عناصر التحكّم التي يتم الوصول إليها من \"الإعدادات السريعة\"."</string>
+ <string name="controls_favorite_subtitle" msgid="6481675111056961083">"اختَر عناصر التحكّم التي يتم الوصول إليها من \"الإعدادات السريعة\"."</string>
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"اضغط مع الاستمرار واسحب لإعادة ترتيب عناصر التحكّم."</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"تمت إزالة كل عناصر التحكّم."</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"لم يتم حفظ التغييرات."</string>
@@ -1108,7 +1109,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"إغلاق"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"استئناف التشغيل"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"الإعدادات"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"يتم تشغيل <xliff:g id="SONG_NAME">%1$s</xliff:g> للفنان <xliff:g id="ARTIST_NAME">%2$s</xliff:g> من تطبيق <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"تشغيل"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"فتح <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"تشغيل <xliff:g id="SONG_NAME">%1$s</xliff:g> للفنان <xliff:g id="ARTIST_NAME">%2$s</xliff:g> من تطبيق <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"تشغيل <xliff:g id="SONG_NAME">%1$s</xliff:g> من تطبيق <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غير نشط، تحقّق من التطبيق."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"حدث خطأ، جارٍ إعادة المحاولة…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"لم يتم العثور عليه."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 5f3e20f..50d866d 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ইথাৰনেট"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"এলাৰ্ম"</string>
<string name="wallet_title" msgid="5369767670735827105">"ৱালেট"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"আপোনাৰ ফ’নটোৰে দ্ৰুত তথা অধিক সুৰক্ষিত ক্ৰয় কৰিবলৈ ছেট আপ পাওক"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"আটাইবোৰ দেখুৱাওক"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"পৰিশোধ কৰিবলৈ আনলক কৰক"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ছেট আপ কৰা হোৱা নাই"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"অগ্ৰাহ্য কৰক"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"পুনৰ আৰম্ভ কৰক"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ছেটিংসমূহ"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ত <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ৰ <xliff:g id="SONG_NAME">%1$s</xliff:g> গীতটো প্লে’ হৈ আছে"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"প্লে’ কৰক"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> খোলক"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ত <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ৰ <xliff:g id="SONG_NAME">%1$s</xliff:g> গীতটো প্লে’ কৰক"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g>ত <xliff:g id="SONG_NAME">%1$s</xliff:g> গীতটো প্লে’ কৰক"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"সক্ৰিয় নহয়, এপ্টো পৰীক্ষা কৰক"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"আসোঁৱাহ, পুনৰ চেষ্টা কৰি আছে…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"বিচাৰি পোৱা নগ’ল"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 0beb96c..9784d53 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -39,7 +39,7 @@
<string name="battery_saver_start_action" msgid="4553256017945469937">"Batareya Qənaətini aktiv edin"</string>
<string name="status_bar_settings_settings_button" msgid="534331565185171556">"Ayarlar"</string>
<string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"Wi-Fi"</string>
- <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ekran avtodönüşü"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ekranın avtomatik dönməsi"</string>
<string name="status_bar_settings_mute_label" msgid="914392730086057522">"SUSDUR"</string>
<string name="status_bar_settings_auto_brightness_label" msgid="2151934479226017725">"AVTO"</string>
<string name="status_bar_settings_notifications" msgid="5285316949980621438">"Bildirişlər"</string>
@@ -61,7 +61,7 @@
<string name="usb_debugging_message" msgid="5794616114463921773">"Kompüterin RSA barmaq izi: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
<string name="usb_debugging_always" msgid="4003121804294739548">"Bu kompüterdən həmişə icazə verilsin"</string>
<string name="usb_debugging_allow" msgid="1722643858015321328">"İcazə verin"</string>
- <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"USB debaq prosesinə icazə verilmir"</string>
+ <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"USB ilə sazlama qadağandır"</string>
<string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"Hazırda bu cihaza daxil olmuş istifadəçi USB sazlama prosesini aktiv edə bilməz. Bu funksiyadan istifadə etmək üçün əsas istifadəçi hesaba daxil olmalıdır."</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Bu şəbəkədə WiFi sazlamasına icazə verilsin?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Şəbəkə Adı (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi Ünvanı (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
@@ -339,11 +339,11 @@
<string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
<string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Qulaqlıq"</string>
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Giriş"</string>
- <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Eşitmə Aparatı"</string>
+ <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Eşitmə cihazları"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aktiv edilir..."</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"Parlaqlıq"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Avtodönüş"</string>
- <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Ekran avtodönüşü"</string>
+ <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Ekranın avtomatik dönməsi"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"<xliff:g id="ID_1">%s</xliff:g> rejimi"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"Fırlanma kilidlidir"</string>
<string name="quick_settings_rotation_locked_portrait_label" msgid="1194988975270484482">"Portret"</string>
@@ -381,7 +381,7 @@
<string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi qoşulu deyil"</string>
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Parlaqlıq"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="2325362583903258677">"AVTO"</string>
- <string name="quick_settings_inversion_label" msgid="5078769633069667698">"Rəngləri çevirin"</string>
+ <string name="quick_settings_inversion_label" msgid="5078769633069667698">"Rəng inversiyası"</string>
<string name="quick_settings_color_space_label" msgid="537528291083575559">"Rəng korreksiyası rejimi"</string>
<string name="quick_settings_more_settings" msgid="2878235926753776694">"Digər ayarlar"</string>
<string name="quick_settings_more_user_settings" msgid="1064187451100861954">"İstifadəçi ayarları"</string>
@@ -509,7 +509,7 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Bu funksiyanı təmin edən xidmətin yazma və ya yayım zamanı ekranda görünən və ya cihazdan oxudulan bütün bilgilərə girişi olacaq. Buraya parollar, ödəniş detalları, fotolar, mesajlar və oxudulan audio kimi məlumatlar daxildir."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Yazma və ya yayımlama başladılsın?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilə yazma və ya yayımlama başladılsın?"</string>
- <string name="media_projection_remember_text" msgid="6896767327140422951">"Daha göstərmə"</string>
+ <string name="media_projection_remember_text" msgid="6896767327140422951">"Göstərilməsin"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Hamısını silin"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"İdarə edin"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Tarixçə"</string>
@@ -660,12 +660,13 @@
<string name="quick_settings" msgid="6211774484997470203">"Sürətli Ayarlar"</string>
<string name="status_bar" msgid="4357390266055077437">"Status paneli"</string>
<string name="overview" msgid="3522318590458536816">"İcmal"</string>
- <string name="demo_mode" msgid="263484519766901593">"Sistem İİ demo rejimi"</string>
+ <string name="demo_mode" msgid="263484519766901593">"Sistem interfeysi: demorejim"</string>
<string name="enable_demo_mode" msgid="3180345364745966431">"Demo rejimini aktiv edin"</string>
<string name="show_demo_mode" msgid="3677956462273059726">"Demo rejimini göstərin"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Zəngli saat"</string>
<string name="wallet_title" msgid="5369767670735827105">"Pulqabı"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Telefonunuzla daha sürətli və təhlükəsiz satınalmalar etmək üçün ayarlayın"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Hamısını göstər"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Ödəmək üçün kiliddən çıxarın"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Quraşdırılmayıb"</string>
@@ -929,7 +930,7 @@
<string name="accessibility_quick_settings_not_available" msgid="6860875849497473854">"<xliff:g id="REASON">%s</xliff:g> səbəbi ilə əlçatan deyil"</string>
<string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> ayarlarını açın."</string>
<string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"Ayarların sıralanmasını redaktə edin."</string>
- <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Yandırıb-söndürmə menyusu"</string>
+ <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Qidalanma düyməsi menyusu"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> səhifədən <xliff:g id="ID_1">%1$d</xliff:g> səhifə"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Ekran kilidi"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"İstiliyə görə telefon söndü"</string>
@@ -967,7 +968,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> işləyir"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Quraşdırılmadan açılan tətbiq."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Quraşdırılmadan açılan tətbiq. Ətraflı məlumat üçün klikləyin."</string>
- <string name="app_info" msgid="5153758994129963243">"Tətbiq infosu"</string>
+ <string name="app_info" msgid="5153758994129963243">"Tətbiq haqqında"</string>
<string name="go_to_web" msgid="636673528981366511">"Brauzerə daxil edin"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobil data"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -1030,7 +1031,7 @@
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Sağa köçürün"</string>
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Böyütmə dəyişdiricisi"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Tam ekranı böyüdün"</string>
- <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekranın bir hissəsini böyüdün"</string>
+ <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_docking_tooltip" msgid="6814897496767461517">"Düyməni müvəqqəti gizlətmək üçün kənara çəkin"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"İmtina edin"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Davam edin"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> tərəfindən <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%3$s</xliff:g> tətbiqindən oxudulur"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Oxudun"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> tətbiqini açın"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> tərəfindən <xliff:g id="SONG_NAME">%1$s</xliff:g> mahnısını <xliff:g id="APP_LABEL">%3$s</xliff:g> tətbiqindən oxudun"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> mahnısını <xliff:g id="APP_LABEL">%2$s</xliff:g> tətbiqindən oxudun"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Aktiv deyil, tətbiqi yoxlayın"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Xəta, yenidən cəhd edilir…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tapılmadı"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index ef524b8..677bfb2 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -669,6 +669,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Eternet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Novčanik"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Obavite konfigurisanje da biste mogli brže i sigurnije da kupujete pomoću telefona"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Prikaži sve"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Otključaj radi plaćanja"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nije podešeno"</string>
@@ -1011,7 +1012,7 @@
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
<string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Koristi <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
- <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Nedavno koristio <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Nedavno koristio/la <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(posao)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonski poziv"</string>
<string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(preko: <xliff:g id="APPLICATION_NAME_S_">%s</xliff:g>)"</string>
@@ -1090,7 +1091,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Podešavanja"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> se pušta iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Pusti"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvorite <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno. Vidite aplikaciju"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Greška, pokušava se ponovo…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index f1f238c..6576a92 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -672,6 +672,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Будзільнік"</string>
<string name="wallet_title" msgid="5369767670735827105">"Кашалёк"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Наладзьце картку, каб рабіць больш хуткія і бяспечныя куплі з дапамогай тэлефона"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Паказаць усе"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Разблакіраваць для аплаты"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Не наладжана"</string>
@@ -1096,7 +1097,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Адхіліць"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Узнавіць"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Налады"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"У праграме \"<xliff:g id="APP_LABEL">%3$s</xliff:g>\" прайграецца кампазіцыя \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\", выканаўца – <xliff:g id="ARTIST_NAME">%2$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Прайграць"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Адкрыйце праграму \"<xliff:g id="APP_LABEL">%1$s</xliff:g>\""</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Прайграйце кампазіцыю \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" (выканаўца – <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) з дапамогай праграмы \"<xliff:g id="APP_LABEL">%3$s</xliff:g>\""</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Прайграйце кампазіцыю \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" з дапамогай праграмы \"<xliff:g id="APP_LABEL">%2$s</xliff:g>\""</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактыўна, праверце праграму"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Памылка, паўторная спроба…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не знойдзена"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a86532d..d51bc7b 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -117,7 +117,7 @@
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Отказ"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Споделяне"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Записването на екрана е анулирано"</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"Записът на екрана е запазен"</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"Записът е запазен"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"Докоснете за преглед"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"При изтриването на записа на екрана възникна грешка"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Извличането на разрешенията не бе успешно."</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Будилник"</string>
<string name="wallet_title" msgid="5369767670735827105">"Портфейл"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Купувайте по-бързо и по-сигурно с телефона си"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Показване на всички"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Отключване с цел плащане"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Не е настроено"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Отхвърляне"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Възобновяване"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> на <xliff:g id="ARTIST_NAME">%2$s</xliff:g> се възпроизвежда от <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Google Play"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Отваряне на <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Пускане на <xliff:g id="SONG_NAME">%1$s</xliff:g> на <xliff:g id="ARTIST_NAME">%2$s</xliff:g> от <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Пускане на <xliff:g id="SONG_NAME">%1$s</xliff:g> от <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, проверете прилож."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Грешка. Извършва се нов опит…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не е намерено"</string>
@@ -1129,7 +1134,7 @@
<string name="new_story_status" msgid="9012195158584846525">"Нова история"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> сподели нова история"</string>
<string name="video_status" msgid="4548544654316843225">"Гледате"</string>
- <string name="audio_status" msgid="4237055636967709208">"Слуша се"</string>
+ <string name="audio_status" msgid="4237055636967709208">"Слушате"</string>
<string name="game_status" msgid="1340694320630973259">"Играете"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Приятели"</string>
<string name="empty_status" msgid="5938893404951307749">"Да поговорим!"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index b72381a..b402402 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ইথারনেট"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"অ্যালার্ম"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"ফোন ব্যবহার করে আরও দ্রুত ও আরও নিরাপদে কেনাকাটা করার জন্য সেট-আপ করুন"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"সবকটি দেখুন"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"পেমেন্ট করতে ডিভাইস আনলক করুন"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"সেট আপ করা নেই"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"খারিজ করুন"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"আবার চালু করুন"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"সেটিংস"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>-এর <xliff:g id="SONG_NAME">%1$s</xliff:g> গানটি <xliff:g id="APP_LABEL">%3$s</xliff:g> অ্যাপে চলছে"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"চালান"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> অ্যাপ খুলুন"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>-এর <xliff:g id="SONG_NAME">%1$s</xliff:g> গানটি <xliff:g id="APP_LABEL">%3$s</xliff:g> অ্যাপে চালান"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> গানটি <xliff:g id="APP_LABEL">%2$s</xliff:g> অ্যাপে চালান"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"বন্ধ আছে, অ্যাপ চেক করুন"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"সমস্যা, আবার চেষ্টা করা হচ্ছে…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"খুঁজে পাওয়া যায়নি"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 6595589..cfcceb69 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -669,6 +669,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Novčanik"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Postavite aplikaciju za brže i sigurnije kupovine putem telefona"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Prikaži sve"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Otključaj za plaćanje"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nije postavljeno"</string>
@@ -748,7 +749,7 @@
<string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Prikazuje se na vrhu obavještenja u razgovorima i kao slika profila na zaključanom ekranu, prekida funkciju Ne ometaj"</string>
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Prikazuje se na vrhu obavještenja u razgovorima i kao slika profila na zaključanom ekranu, izgleda kao oblačić, prekida funkciju Ne ometaj"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Postavke"</string>
- <string name="notification_priority_title" msgid="2079708866333537093">"Prioritetni"</string>
+ <string name="notification_priority_title" msgid="2079708866333537093">"Prioritetno"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava funkcije razgovora"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ta obavještenja se ne mogu izmijeniti."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ovu grupu obavještenja nije moguće konfigurirati ovdje"</string>
@@ -1090,7 +1091,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Pjesma <xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> se reproducira pomoću aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Pokrenite"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvorite aplikaciju <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reproducirajte pjesmu <xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> pomoću aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproducirajte pjesmu <xliff:g id="SONG_NAME">%1$s</xliff:g> pomoću aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, vidite aplikaciju"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Greška, ponovni pokušaj…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index ba3a3f4..925a293 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configura una manera més ràpida i segura de fer compres amb el telèfon"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Mostra-ho tot"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Desbloqueja per pagar"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"No s\'ha configurat"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignora"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reprèn"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuració"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) s\'està reproduint des de l\'aplicació <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reprodueix"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Obre <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reprodueix <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) des de l\'aplicació <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reprodueix <xliff:g id="SONG_NAME">%1$s</xliff:g> des de l\'aplicació <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiu; comprova l\'aplicació"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error. S\'està tornant a provar…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No s\'ha trobat"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2a9d7f5..f3d64ab 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -101,7 +101,7 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Trvalé oznámení o relaci nahrávání"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Spustit nahrávání?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Při nahrávání může systém Android zaznamenávat citlivé údaje, které jsou viditelné na obrazovce nebo které jsou přehrávány na zařízení. Týká se to hesel, údajů o platbě, fotek, zpráv a zvuků."</string>
- <string name="screenrecord_audio_label" msgid="6183558856175159629">"Nahrát zvuk"</string>
+ <string name="screenrecord_audio_label" msgid="6183558856175159629">"Nahrávat zvuk"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk zařízení"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk ze zařízení, například hudba, hovory a vyzvánění"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Mikrofon"</string>
@@ -117,8 +117,8 @@
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Zrušit"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Sdílet"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Nahrávání obrazovky bylo zrušeno"</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"Nahrávka obrazovky byla uložena"</string>
- <string name="screenrecord_save_text" msgid="3008973099800840163">"Nahrávku zobrazíte klepnutím"</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"Nahrávka obrazovky se uložila"</string>
+ <string name="screenrecord_save_text" msgid="3008973099800840163">"Klepnutím nahrávku zobrazíte"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Při mazání záznamu obrazovky došlo k chybě"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Nepodařilo se načíst oprávnění"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Při spouštění nahrávání obrazovky došlo k chybě"</string>
@@ -617,9 +617,9 @@
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Obsah bude připnut v zobrazení, dokud ho neuvolníte. Uvolníte ho podržením tlačítka Plocha."</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Může mít přístup k soukromým datům (například kontaktům a obsahu e-mailů)."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Připnutá aplikace může otevírat další aplikace."</string>
- <string name="screen_pinning_toast" msgid="8177286912533744328">"Chcete-li tuto aplikaci odepnout, podržte tlačítka Zpět a Přehled"</string>
- <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Chcete-li tuto aplikaci odepnout, podržte tlačítka Zpět a Plocha"</string>
- <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Chcete-li tuto aplikaci odepnout, přejeďte prstem nahoru a podržte"</string>
+ <string name="screen_pinning_toast" msgid="8177286912533744328">"Aplikaci odepnete podržením tlačítek Zpět a Přehled"</string>
+ <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Aplikaci odepnete podržením tlačítek Zpět a Plocha"</string>
+ <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Aplikaci odepnete přejetím prstem nahoru a podržením"</string>
<string name="screen_pinning_positive" msgid="3285785989665266984">"Rozumím"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"Ne, děkuji"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"Aplikace byla připnuta"</string>
@@ -672,6 +672,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Budík"</string>
<string name="wallet_title" msgid="5369767670735827105">"Peněženka"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Nastavte si rychlejší a bezpečnější platby pomocí telefonu"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Zobrazit vše"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Odemknout a zaplatit"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Není nastaveno"</string>
@@ -739,7 +740,7 @@
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Žádný zvuk ani vibrace"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"Žádný zvuk ani vibrace a zobrazuje se níže v sekci konverzací"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Vyzvání nebo vibruje podle nastavení telefonu"</string>
- <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Může vyzvánět nebo vibrovat v závislosti na nastavení telefonu. Konverzace z aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> ve výchozím nastavení bublají."</string>
+ <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Vyzvání nebo vibruje podle nastavení telefonu. Konverzace z aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> mají ve výchozím nastavení podobu bublin."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Přitahuje pozornost pomocí plovoucí zkratky k tomuto obsahu."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Nechat systém rozhodnout, zda má toto oznámení vydat zvuk či zavibrovat"</string>
<string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"<b>Stav:</b> priorita zvýšena na Výchozí"</string>
@@ -1015,8 +1016,8 @@
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikace využívají tato oprávnění: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" a "</string>
- <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Používáno aplikací <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
- <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Nedávno použito aplikací <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Právě používá aplikace <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Nedávno použila aplikace <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(práce)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonní hovor"</string>
<string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(prostřednictvím aplikace <xliff:g id="APPLICATION_NAME_S_">%s</xliff:g>)"</string>
@@ -1096,7 +1097,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Zavřít"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Pokračovat"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavení"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Skladba <xliff:g id="SONG_NAME">%1$s</xliff:g> od interpreta <xliff:g id="ARTIST_NAME">%2$s</xliff:g> hrajte z aplikace <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Přehrát"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otevřít aplikaci <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Přehrát skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> od interpreta <xliff:g id="ARTIST_NAME">%2$s</xliff:g> z aplikace <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Přehrát skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> z aplikace <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivní, zkontrolujte aplikaci"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Chyba. Nový pokus…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nenalezeno"</string>
@@ -1142,7 +1147,7 @@
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> sdílí nový příběh"</string>
<string name="video_status" msgid="4548544654316843225">"Sleduje"</string>
<string name="audio_status" msgid="4237055636967709208">"Poslouchá"</string>
- <string name="game_status" msgid="1340694320630973259">"Hraje"</string>
+ <string name="game_status" msgid="1340694320630973259">"Hraji hru"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Přátelé"</string>
<string name="empty_status" msgid="5938893404951307749">"Pojďme chatovat."</string>
<string name="status_before_loading" msgid="1500477307859631381">"Obsah se brzy zobrazí"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 4301f88..0c7a743 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -609,7 +609,7 @@
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Dette fastholder appen på skærmen, indtil du frigør den. Stryg opad, og hold fingeren nede for at frigøre den."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Dette fastholder skærmen i visningen, indtil du frigør den. Tryk på Tilbage, og hold fingeren nede for at frigøre skærmen."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Dette fastholder skærmen i visningen, indtil du frigør den. Hold Startskærm nede for at frigøre skærmen."</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Der kan stadig være adgang til personoplysninger (f.eks. kontakter og mailindhold)."</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personoplysninger kan muligvis tilgås (f.eks. kontakter og mailindhold)."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"En fastgjort app kan åbne andre apps."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"Du kan frigøre denne app ved at holde knapperne Tilbage og Oversigt nede"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Du kan frigøre denne app ved at holde knapperne Tilbage og Hjem nede"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Bliv klar til at foretage hurtigere og mere sikre køb med din telefon"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Vis alle"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Lås op for at betale"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ikke konfigureret"</string>
@@ -1055,7 +1056,7 @@
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"fjern fra favoritter"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"Flyt til position <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"Betjeningselementer"</string>
- <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Vælg, hvilke indstillinger du vil have adgang til i kvikmenuen"</string>
+ <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Vælg, hvilke styringselementer du vil have adgang til i kvikmenuen"</string>
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Flyt et felt ved at holde det nede og trække"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Alle styringselementerne blev fjernet"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Ændringerne blev ikke gemt"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Luk"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Genoptag"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Indstillinger"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> af <xliff:g id="ARTIST_NAME">%2$s</xliff:g> afspilles via <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Afspil"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Åbn <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Afspil <xliff:g id="SONG_NAME">%1$s</xliff:g> af <xliff:g id="ARTIST_NAME">%2$s</xliff:g> via <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Afspil <xliff:g id="SONG_NAME">%1$s</xliff:g> via <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Tjek appen"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fejl. Prøver igen…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke fundet"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 8ebfeba..0f18757 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -105,7 +105,7 @@
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio des Geräts"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Audioinhalte auf deinem Gerät, wie Musik, Anrufe und Klingeltöne"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Mikrofon"</string>
- <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Audio des Geräts und über externes Mikrofon aufnehmen"</string>
+ <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Audio des Geräts und über Mikrofon"</string>
<string name="screenrecord_start" msgid="330991441575775004">"Start"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Bildschirm wird aufgezeichnet"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Bildschirm und Ton werden aufgezeichnet"</string>
@@ -616,7 +616,7 @@
<string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Zum Loslösen der App nach oben wischen und halten"</string>
<string name="screen_pinning_positive" msgid="3285785989665266984">"Ok"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"Nein danke"</string>
- <string name="screen_pinning_start" msgid="7483998671383371313">"App angepinnt"</string>
+ <string name="screen_pinning_start" msgid="7483998671383371313">"Bildschirm wurde fixiert"</string>
<string name="screen_pinning_exit" msgid="4553787518387346893">"App vom Bildschirm losgelöst"</string>
<string name="quick_settings_reset_confirmation_title" msgid="463533331480997595">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ausblenden?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"Sie wird wieder eingeblendet, wenn du sie in den Einstellungen erneut aktivierst."</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Weckruf"</string>
<string name="wallet_title" msgid="5369767670735827105">"Geldbörse"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Füge eine Zahlungsmethode hinzu, um noch schneller und sicherer mit deinem Smartphone zu bezahlen"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Alle anzeigen"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Zum Bezahlen entsperren"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nicht eingerichtet"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ablehnen"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Fortsetzen"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Einstellungen"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> von <xliff:g id="ARTIST_NAME">%2$s</xliff:g> wird gerade über <xliff:g id="APP_LABEL">%3$s</xliff:g> wiedergegeben"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Wiedergeben"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> öffnen"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> von <xliff:g id="ARTIST_NAME">%2$s</xliff:g> über <xliff:g id="APP_LABEL">%3$s</xliff:g> wiedergeben"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> über <xliff:g id="APP_LABEL">%2$s</xliff:g> wiedergeben"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv – sieh in der App nach"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fehler. Neuer Versuch…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nicht gefunden"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 3b23c35..9525f99 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -63,7 +63,7 @@
<string name="usb_debugging_allow" msgid="1722643858015321328">"Να επιτρέπεται"</string>
<string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Δεν επιτρέπεται ο εντοπισμός σφαλμάτων USB"</string>
<string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"Ο χρήστης που είναι συνδεδεμένος αυτήν τη στιγμή σε αυτήν τη συσκευή δεν μπορεί να ενεργοποιήσει τον εντοπισμό σφαλμάτων USB. Για να χρησιμοποιήσετε αυτήν τη λειτουργία, κάντε εναλλαγή στον κύριο χρήστη."</string>
- <string name="wifi_debugging_title" msgid="7300007687492186076">"Να επιτρέπεται ο ασύρματος εντοπισμός σφαλμάτων σε αυτό το δίκτυο;"</string>
+ <string name="wifi_debugging_title" msgid="7300007687492186076">"Να επιτρέπεται ασύρματος εντοπ. σφαλ. στο δίκτυο;"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Όνομα δικτύου (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nΔιεύθυνση Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Να επιτρέπεται πάντα σε αυτό το δίκτυο"</string>
<string name="wifi_debugging_allow" msgid="4573224609684957886">"Να επιτρέπεται"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Ξυπνητήρι"</string>
<string name="wallet_title" msgid="5369767670735827105">"Πορτοφόλι"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Ολοκληρώστε τη ρύθμιση για να κάνετε πιο γρήγορες και πιο ασφαλείς αγορές με το τηλέφωνό σας"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Εμφάνιση όλων"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Ξεκλείδωμα για πληρωμή"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Δεν έχει ρυθμιστεί"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Παράβλεψη"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Συνέχιση"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ρυθμίσεις"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Γίνεται αναπαραγωγή του <xliff:g id="SONG_NAME">%1$s</xliff:g> από <xliff:g id="ARTIST_NAME">%2$s</xliff:g> στην εφαρμογή <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Play"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Άνοιγμα της εφαρμογής <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Αναπαραγωγή του <xliff:g id="SONG_NAME">%1$s</xliff:g> από <xliff:g id="ARTIST_NAME">%2$s</xliff:g> στην εφαρμογή <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Αναπαραγωγή του <xliff:g id="SONG_NAME">%1$s</xliff:g> στην εφαρμογή <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Ανενεργό, έλεγχος εφαρμογής"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Προέκυψε σφάλμα. Επανάληψη…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Δεν βρέθηκε."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 8f5bf75..c346bbe 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -609,7 +609,7 @@
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"This keeps it in view until you unpin. Swipe up and hold to unpin."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"This keeps it in view until you unpin. Touch & hold Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personal data may be accessible (such as contacts and email content)."</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personal data may be accessible, such as contacts and email content."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Pinned app may open other apps."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"To unpin this app, touch and hold Back and Overview buttons"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"To unpin this app, touch and hold Back and Home buttons"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Get set up to make faster, more secure purchases with your phone"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Show all"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Unlock to pay"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Not set up"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> is playing from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Play"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Open <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index d47a4e9..b588e86 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -609,7 +609,7 @@
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"This keeps it in view until you unpin. Swipe up and hold to unpin."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"This keeps it in view until you unpin. Touch & hold Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personal data may be accessible (such as contacts and email content)."</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personal data may be accessible, such as contacts and email content."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Pinned app may open other apps."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"To unpin this app, touch and hold Back and Overview buttons"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"To unpin this app, touch and hold Back and Home buttons"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Get set up to make faster, more secure purchases with your phone"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Show all"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Unlock to pay"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Not set up"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> is playing from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Play"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Open <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 8f5bf75..c346bbe 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -609,7 +609,7 @@
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"This keeps it in view until you unpin. Swipe up and hold to unpin."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"This keeps it in view until you unpin. Touch & hold Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personal data may be accessible (such as contacts and email content)."</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personal data may be accessible, such as contacts and email content."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Pinned app may open other apps."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"To unpin this app, touch and hold Back and Overview buttons"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"To unpin this app, touch and hold Back and Home buttons"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Get set up to make faster, more secure purchases with your phone"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Show all"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Unlock to pay"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Not set up"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> is playing from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Play"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Open <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 8f5bf75..c346bbe 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -609,7 +609,7 @@
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"This keeps it in view until you unpin. Swipe up and hold to unpin."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"This keeps it in view until you unpin. Touch & hold Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personal data may be accessible (such as contacts and email content)."</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personal data may be accessible, such as contacts and email content."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Pinned app may open other apps."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"To unpin this app, touch and hold Back and Overview buttons"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"To unpin this app, touch and hold Back and Home buttons"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Get set up to make faster, more secure purchases with your phone"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Show all"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Unlock to pay"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Not set up"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> is playing from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Play"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Open <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 79400fe..a73c387 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Get set up to make faster, more secure purchases with your phone"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Show all"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Unlock to pay"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Not set up"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> is playing from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Play"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Open <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 94b8d59..051c0dd 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Prepárate para realizar compras rápidas y seguras con tu teléfono"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar todo"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Desbloquear para pagar"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Sin configurar"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Descartar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Se está reproduciendo <xliff:g id="SONG_NAME">%1$s</xliff:g>, de <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reproducir"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abre <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reproduce <xliff:g id="SONG_NAME">%1$s</xliff:g>, de <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproducir <xliff:g id="SONG_NAME">%1$s</xliff:g> en <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hubo un error. Reintentando…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No se encontró"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a2db1f1..d04fd45 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configura un método de pago para comprar de forma más rápida y segura con tu teléfono"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar todo"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Desbloquear para pagar"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Sin configurar"</string>
@@ -798,7 +799,7 @@
<item quantity="other">%d minutos</item>
<item quantity="one">%d minuto</item>
</plurals>
- <string name="battery_panel_title" msgid="5931157246673665963">"Uso de la batería"</string>
+ <string name="battery_panel_title" msgid="5931157246673665963">"Uso de batería"</string>
<string name="battery_detail_charging_summary" msgid="8821202155297559706">"Ahorro de batería no disponible mientras se carga el dispositivo"</string>
<string name="battery_detail_switch_title" msgid="6940976502957380405">"Ahorro de batería"</string>
<string name="battery_detail_switch_summary" msgid="3668748557848025990">"Reduce el rendimiento y los datos en segundo plano"</string>
@@ -1005,7 +1006,7 @@
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hay aplicaciones que usan tu <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" y "</string>
- <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"En uso en <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Se está usando en <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Uso reciente en <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(trabajo)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Llamada telefónica"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Cerrar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ajustes"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Se está reproduciendo <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reproducir"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abrir <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Poner <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Poner <xliff:g id="SONG_NAME">%1$s</xliff:g> en <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, comprobar aplicación"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error; reintentando…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No se ha encontrado"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 0ff64cb..00d98c2 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Äratus"</string>
<string name="wallet_title" msgid="5369767670735827105">"Rahakott"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Seadistage kiirem ja turvalisem viis telefoniga ostmiseks"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Kuva kõik"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Avage maksmiseks"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Pole seadistatud"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Loobu"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Jätka"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Seaded"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> esitajalt <xliff:g id="ARTIST_NAME">%2$s</xliff:g> esitatakse rakenduses <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Esitamine"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Rakenduse <xliff:g id="APP_LABEL">%1$s</xliff:g> avamine"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Esita lugu <xliff:g id="SONG_NAME">%1$s</xliff:g> esitajalt <xliff:g id="ARTIST_NAME">%2$s</xliff:g> rakenduses <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Esita lugu <xliff:g id="SONG_NAME">%1$s</xliff:g> rakenduses <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Passiivne, vaadake rakendust"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Viga, proovitakse uuesti …"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ei leitud"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 2517960..78eb728 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -63,9 +63,9 @@
<string name="usb_debugging_allow" msgid="1722643858015321328">"Eman baimena"</string>
<string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Ez da onartzen USB bidezko arazketa"</string>
<string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"Gailu honetan saioa hasita daukan erabiltzaileak ezin du aktibatu USB bidezko arazketa. Eginbide hori erabiltzeko, aldatu erabiltzaile nagusira."</string>
- <string name="wifi_debugging_title" msgid="7300007687492186076">"Hari gabeko arazketa onartu nahi duzu sare honetan?"</string>
+ <string name="wifi_debugging_title" msgid="7300007687492186076">"Hari gabeko arazketa sare honetan erabiltzeko baimena eman nahi duzu?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Sarearen izena (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWifi-helbidea (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
- <string name="wifi_debugging_always" msgid="2968383799517975155">"Baimendu beti sare honetan"</string>
+ <string name="wifi_debugging_always" msgid="2968383799517975155">"Eman baimena beti sare honetan"</string>
<string name="wifi_debugging_allow" msgid="4573224609684957886">"Eman baimena"</string>
<string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"Ez da onartzen hari gabeko arazketa"</string>
<string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"Gailu honetan saioa hasita daukan erabiltzaileak ezin du aktibatu hari gabeko arazketa. Eginbide hori erabiltzeko, aldatu erabiltzaile nagusira."</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Konfiguratu erosketa bizkorrago eta seguruagoak egiteko telefonoarekin"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Erakutsi guztiak"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Desblokeatu ordaintzeko"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Konfiguratu gabe"</string>
@@ -721,14 +722,14 @@
<string name="inline_block_button" msgid="479892866568378793">"Blokeatu"</string>
<string name="inline_keep_button" msgid="299631874103662170">"Jarraitu erakusten"</string>
<string name="inline_minimize_button" msgid="1474436209299333445">"Minimizatu"</string>
- <string name="inline_silent_button_silent" msgid="525243786649275816">"Soinurik gabe"</string>
+ <string name="inline_silent_button_silent" msgid="525243786649275816">"Isila"</string>
<string name="inline_silent_button_stay_silent" msgid="2129254868305468743">"Jarraitu isilik"</string>
<string name="inline_silent_button_alert" msgid="5705343216858250354">"Alertak"</string>
<string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Jarraitu jakinarazpenak bidaltzen"</string>
<string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desaktibatu jakinarazpenak"</string>
<string name="inline_keep_showing_app" msgid="4393429060390649757">"Aplikazio honen jakinarazpenak erakusten jarraitzea nahi duzu?"</string>
<string name="notification_silence_title" msgid="8608090968400832335">"Isila"</string>
- <string name="notification_alert_title" msgid="3656229781017543655">"Balio lehenetsia"</string>
+ <string name="notification_alert_title" msgid="3656229781017543655">"Lehenetsia"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Automatikoa"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Ez du tonurik jotzen edo dar-dar egiten"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"Ez du tonurik jotzen edo dar-dar egiten, eta elkarrizketaren atalaren behealdean agertzen da"</string>
@@ -1005,7 +1006,7 @@
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikazio batzuk <xliff:g id="TYPES_LIST">%s</xliff:g> erabiltzen ari dira."</string>
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" eta "</string>
- <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> erabiltzen ari da"</string>
+ <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> aplikazioak darabil"</string>
<string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> aplikazioak erabili du azkenaldian"</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(lanekoa)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefono-deia"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Baztertu"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Berrekin"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ezarpenak"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) ari da erreproduzitzen <xliff:g id="APP_LABEL">%3$s</xliff:g> bidez"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Erreproduzitu"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Ireki <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Erreproduzitu <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) <xliff:g id="APP_LABEL">%3$s</xliff:g> bidez"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Erreproduzitu <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%2$s</xliff:g> bidez"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktibo; egiaztatu aplikazioa"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Errorea. Berriro saiatzen…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ez da aurkitu"</string>
@@ -1130,7 +1135,7 @@
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzaileak istorio berri bat partekatu du"</string>
<string name="video_status" msgid="4548544654316843225">"Ikusten"</string>
<string name="audio_status" msgid="4237055636967709208">"Entzuten"</string>
- <string name="game_status" msgid="1340694320630973259">"Erreproduzitzen"</string>
+ <string name="game_status" msgid="1340694320630973259">"Jolasten"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Lagunak"</string>
<string name="empty_status" msgid="5938893404951307749">"Txatea dezagun gaur gauean!"</string>
<string name="status_before_loading" msgid="1500477307859631381">"Laster agertuko da edukia"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 476f6d2..10e95f4 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -423,7 +423,7 @@
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC غیرفعال است"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC فعال است"</string>
- <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ضبط کردن صفحهنمایش"</string>
+ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ضبط صفحهنمایش"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"شروع"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"توقف"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"میکروفون دستگاه لغو انسداد شود؟"</string>
@@ -604,7 +604,7 @@
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"غیرفعال کردن"</string>
<string name="accessibility_output_chooser" msgid="7807898688967194183">"تغییر دستگاه خروجی"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"برنامه سنجاق شده است"</string>
- <string name="screen_pinning_description" msgid="8699395373875667743">"تا زمانی که پین را بردارید، در نما نگهداشته میشود. برای برداشتن سنجاق، «برگشت» و «نمای کلی» را لمس کنید و نگهدارید."</string>
+ <string name="screen_pinning_description" msgid="8699395373875667743">"تا زمانی که سنجاق را برندارید، در نما نگهداشته میشود. برای برداشتن سنجاق، «برگشت» و «نمای کلی» را لمس کنید و نگهدارید."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"تا برداشتن سنجاق، در نما نگهداشته میشود. برای برداشتن سنجاق، «برگشت» و «صفحه اصلی» را لمس کنید و نگهدارید."</string>
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"به این ترتیب تا زمانی پین آن را برندارید قابلمشاهده است. برای برداشتن سنجاق، از پایین صفحه تند بهطرف بالا بکشید و نگه دارید."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"تا زمانی که پین را بردارید، در نما نگهداشته میشود. برای برداشتن سنجاق، «نمای کلی» را لمس کنید و نگهدارید."</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"اترنت"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"زنگ"</string>
<string name="wallet_title" msgid="5369767670735827105">"کیفپول"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"برای خرید سریعتر و امنتر با تلفن، راهاندازی کنید"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"نمایش همه"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"باز کردن قفل برای پرداخت"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"تنظیمنشده"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"رد کردن"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ازسرگیری"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"تنظیمات"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> از <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ازطریق <xliff:g id="APP_LABEL">%3$s</xliff:g> پخش میشود"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"پخش"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"باز کردن <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> از <xliff:g id="ARTIST_NAME">%2$s</xliff:g> را ازطریق <xliff:g id="APP_LABEL">%3$s</xliff:g> پخش کنید"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> را ازطریق <xliff:g id="APP_LABEL">%2$s</xliff:g> پخش کنید"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غیرفعال، برنامه را بررسی کنید"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"خطا، درحال تلاش مجدد…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"پیدا نشد"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 3f3831f..51b73df 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Herätys"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Lisää maksutapa, niin voit maksaa nopeasti ja turvallisesti puhelimella"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Näytä kaikki"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Avaa lukitus ja maksa"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ei otettu käyttöön"</string>
@@ -1055,7 +1056,7 @@
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"poista suosikeista"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"Siirrä kohtaan <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"Säätimet"</string>
- <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Valitse ohjaimet, joita käytetään pika-asetuksista"</string>
+ <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Valitse säätimet, joita käytetään pika-asetuksista"</string>
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Järjestele säätimiä koskettamalla pitkään ja vetämällä"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Kaikki säätimet poistettu"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Muutoksia ei tallennettu"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ohita"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Jatka"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Asetukset"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> soittaa nyt tätä: <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>)"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Toista"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Avaa <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Soita <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) sovelluksessa <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Soita <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="APP_LABEL">%2$s</xliff:g>)"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Epäaktiivinen, tarkista sovellus"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Virhe, yritetään uudelleen…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ei löydy"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 6f8eea60..e657308 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Préparez-vous à faire des achats plus rapidement et de façon plus sûre avec votre téléphone"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Tout afficher"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Déverrouiller pour payer"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Non configuré"</string>
@@ -765,7 +766,7 @@
<string name="feedback_silenced" msgid="9116540317466126457">"La notification a été automatiquement <b>abaissée à la catégorie Silencieux</b> par le système."</string>
<string name="feedback_promoted" msgid="2125562787759780807">"La notification a été automatiquement <b>élevée d\'un niveau</b> dans votre volet."</string>
<string name="feedback_demoted" msgid="951884763467110604">"La notification a été automatiquement <b>abaissée d\'un niveau</b> dans votre volet."</string>
- <string name="feedback_prompt" msgid="3656728972307896379">"Faites part de vos commentaires au concepteur. Était-ce correct?"</string>
+ <string name="feedback_prompt" msgid="3656728972307896379">"Faites part de vos commentaires au développeur. Était-ce correct?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Merci de vos commentaires!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Les paramètres des notifications pour <xliff:g id="APP_NAME">%1$s</xliff:g> sont ouverts"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Fermer"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> est en cours de lecteur à partir de <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Faire jouer"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Ouvrez <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Lecture de <xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> à partir de <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Lecture de <xliff:g id="SONG_NAME">%1$s</xliff:g> à partir de <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifiez l\'appli"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erreur, nouvelle tentative…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index f279268..04f7692 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -107,10 +107,10 @@
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Micro"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Appareil et micro"</string>
<string name="screenrecord_start" msgid="330991441575775004">"Démarrer"</string>
- <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Enregistrement de l\'écran"</string>
+ <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Enregistrement de l\'écran…"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Enregistrement de l\'écran et de l\'audio…"</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Afficher les points touchés sur l\'écran"</string>
- <string name="screenrecord_stop_text" msgid="6549288689506057686">"Appuyez ici pour arrêter"</string>
+ <string name="screenrecord_stop_text" msgid="6549288689506057686">"Appuyez pour arrêter"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Arrêter"</string>
<string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Reprendre"</string>
@@ -408,7 +408,7 @@
<string name="quick_settings_cellular_detail_data_used" msgid="6798849610647988987">"<xliff:g id="DATA_USED">%s</xliff:g> utilisés"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> au maximum"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Avertissement : <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Applis professionnelles"</string>
+ <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Applis pro"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Éclairage nocturne"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Activé la nuit"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Jusqu\'à l\'aube"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configurez pour régler vos achats de façon sûre et rapide via votre téléphone"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Tout afficher"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Déverrouiller pour payer"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Non configuré"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Fermer"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> est en cours de lecture depuis <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Lire"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Ouvre <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Mets <xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> depuis <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Mets <xliff:g id="SONG_NAME">%1$s</xliff:g> depuis <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifier l\'appli"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erreur. Nouvelle tentative…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
@@ -1122,14 +1127,14 @@
<string name="birthday_status_content_description" msgid="682836371128282925">"C\'est l\'anniversaire de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="upcoming_birthday_status" msgid="2005452239256870351">"Anniversaire à venir"</string>
<string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"C\'est bientôt l\'anniversaire de <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="anniversary_status" msgid="1790034157507590838">"Fête"</string>
+ <string name="anniversary_status" msgid="1790034157507590838">"Anniversaire"</string>
<string name="anniversary_status_content_description" msgid="8212171790843327442">"C\'est l\'anniversaire de mariage de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="location_status" msgid="1294990572202541812">"Partage sa position"</string>
<string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> partage sa position"</string>
<string name="new_story_status" msgid="9012195158584846525">"Nouvelle story"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> a partagé une story"</string>
<string name="video_status" msgid="4548544654316843225">"Regarde une vidéo"</string>
- <string name="audio_status" msgid="4237055636967709208">"Écoute"</string>
+ <string name="audio_status" msgid="4237055636967709208">"Écoute du contenu"</string>
<string name="game_status" msgid="1340694320630973259">"Joue"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Amis"</string>
<string name="empty_status" msgid="5938893404951307749">"Chattez ce soir !"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 07a691c..52c6e33 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -342,7 +342,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Audiófonos"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activando…"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"Brillo"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Xirar automaticamente"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Xirar automat."</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Xirar pantalla automaticamente"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"Modo <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"Rotación bloqueada"</string>
@@ -423,7 +423,7 @@
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"A opción NFC está desactivada"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"A opción NFC está activada"</string>
- <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Gravación da pantalla"</string>
+ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Gravar pant."</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Deter"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Queres desbloquear o micrófono do dispositivo?"</string>
@@ -487,7 +487,7 @@
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Comezar de novo"</string>
<string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Si, continuar"</string>
<string name="guest_notification_title" msgid="4434456703930764167">"Usuario convidado"</string>
- <string name="guest_notification_text" msgid="4202692942089571351">"Para eliminar aplicacións e datos, quita o usuario invitado"</string>
+ <string name="guest_notification_text" msgid="4202692942089571351">"Para eliminar aplicacións e datos, quita o usuario convidado"</string>
<string name="guest_notification_remove_action" msgid="4153019027696868099">"QUITAR CONVIDADO"</string>
<string name="user_logout_notification_title" msgid="3644848998053832589">"Pechar sesión do usuario"</string>
<string name="user_logout_notification_text" msgid="7441286737342997991">"Pechar sesión do usuario actual"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configura un método de pago para comprar de xeito máis rápido e seguro co teléfono"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Amosar todo"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Desbloquear para pagar"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Sen configurar"</string>
@@ -732,8 +733,8 @@
<string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Sen son nin vibración"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sen son nin vibración, e aparecen máis abaixo na sección de conversas"</string>
- <string name="notification_channel_summary_default" msgid="3282930979307248890">"Poderían soar ou vibrar en función da configuración do teléfono"</string>
- <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Podería soar ou vibrar en función da configuración do teléfono. Conversas desde a burbulla da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
+ <string name="notification_channel_summary_default" msgid="3282930979307248890">"Poderían facer que o teléfono soe ou vibre en función da súa configuración"</string>
+ <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Poderían facer que o teléfono soe ou vibre en función da súa configuración. Conversas desde a burbulla da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantén a túa atención cun atallo flotante a este contido."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Fai que o sistema determine se a notificación debe emitir un son ou unha vibración"</string>
<string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"<b>Estado:</b> ascendeuse a Predeterminada"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignorar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Estase reproducindo <xliff:g id="SONG_NAME">%1$s</xliff:g>, de <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reproducir"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abre <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reproduce <xliff:g id="SONG_NAME">%1$s</xliff:g>, de <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproduce <xliff:g id="SONG_NAME">%1$s</xliff:g> en <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Comproba a app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando de novo…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Non se atopou"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index f7a1c8e..c06826b 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -387,7 +387,7 @@
<string name="quick_settings_more_user_settings" msgid="1064187451100861954">"વપરાશકર્તા સેટિંગ"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"થઈ ગયું"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"બંધ કરો"</string>
- <string name="quick_settings_connected" msgid="3873605509184830379">"કનેક્ટ થયેલ"</string>
+ <string name="quick_settings_connected" msgid="3873605509184830379">"કનેક્ટ થયેલું"</string>
<string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"કનેક્ટ કરેલ, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
<string name="quick_settings_connecting" msgid="2381969772953268809">"કનેક્ટ કરી રહ્યું છે..."</string>
<string name="quick_settings_tethering_label" msgid="5257299852322475780">"ટિથરિંગ"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ઇથરનેટ"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"અલાર્મ"</string>
<string name="wallet_title" msgid="5369767670735827105">"વૉલેટ"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"તમારા ફોન વડે વધુ ઝડપી તેમજ સુરક્ષિત ખરીદીઓ કરવાની રીત સેટઅપ કરી લો"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"બધું બતાવો"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ચુકવણી કરવા માટે અનલૉક કરો"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"કોઈ સેટઅપ કર્યું નથી"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"છોડી દો"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ફરી શરૂ કરો"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"સેટિંગ"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> પર <xliff:g id="ARTIST_NAME">%2$s</xliff:g>નું <xliff:g id="SONG_NAME">%1$s</xliff:g> ગીત ચાલી રહ્યું છે"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ચલાવો"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ખોલો"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> પર <xliff:g id="ARTIST_NAME">%2$s</xliff:g>નું <xliff:g id="SONG_NAME">%1$s</xliff:g> ગીત ચલાવો"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> પર <xliff:g id="SONG_NAME">%1$s</xliff:g> ગીત ચલાવો"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"નિષ્ક્રિય, ઍપને ચેક કરો"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ભૂલ, ફરી પ્રયાસ કરી રહ્યા છીએ…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"મળ્યું નથી"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index d73be92..cdead41 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -342,7 +342,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"कान की मशीन"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ब्लूटूथ चालू हो रहा है…"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"स्क्रीन की रोशनी"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"अपने-आप घूमना"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"स्क्रीन का अपने-आप दिशा बदलना"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"स्क्रीन का अपने-आप दिशा बदलना (ऑटो-रोटेट)"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"<xliff:g id="ID_1">%s</xliff:g> मोड"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"घुमाना लॉक किया गया"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ईथरनेट"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
<string name="wallet_title" msgid="5369767670735827105">"वॉलेट"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"फ़ोन के ज़रिए तेज़ी से और सुरक्षित तरीके से खरीदारी करने के लिए सेट अप करें"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"सभी दिखाएं"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"पैसे चुकाने के लिए, डिवाइस अनलॉक करें"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"सेट अप नहीं किया गया है"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"खारिज करें"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"फिर से शुरू करें"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> पर, <xliff:g id="ARTIST_NAME">%2$s</xliff:g> का <xliff:g id="SONG_NAME">%1$s</xliff:g> चल रहा है"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"चलाएं"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> खोलें"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> पर, <xliff:g id="ARTIST_NAME">%2$s</xliff:g> का <xliff:g id="SONG_NAME">%1$s</xliff:g> चलाएं"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> पर, <xliff:g id="SONG_NAME">%1$s</xliff:g> चलाएं"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"काम नहीं कर रहा, ऐप जांचें"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"कोई गड़बड़ी हुई, फिर से कोशिश की जा रही है…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"कंट्रोल नहीं है"</string>
@@ -1110,7 +1115,7 @@
<string name="select_conversation_title" msgid="6716364118095089519">"बातचीत विजेट"</string>
<string name="select_conversation_text" msgid="3376048251434956013">"किसी बातचीत को होम स्क्रीन पर जोड़ने के लिए, उस बातचीत पर टैप करें"</string>
<string name="no_conversations_text" msgid="7362374212649891057">"नए मैसेज आने पर यहां देखें"</string>
- <string name="priority_conversations" msgid="3967482288896653039">"अहम बातचीत"</string>
+ <string name="priority_conversations" msgid="3967482288896653039">"प्राथमिकता वाली बातचीत"</string>
<string name="recent_conversations" msgid="8531874684782574622">"हाल ही में की गई बातचीत"</string>
<string name="okay" msgid="6490552955618608554">"ठीक है"</string>
<string name="days_timestamp" msgid="5821854736213214331">"<xliff:g id="DURATION">%1$s</xliff:g> दिन पहले"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index fd1592d..14250a7 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -63,7 +63,7 @@
<string name="usb_debugging_allow" msgid="1722643858015321328">"Dopusti"</string>
<string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Otklanjanje pogrešaka putem USB-a nije dopušteno"</string>
<string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"Korisnik koji je trenutačno prijavljen na ovaj uređaj ne može uključiti otklanjanje pogrešaka putem USB-a. Da biste upotrebljavali tu značajku, prijeđite na primarnog korisnika."</string>
- <string name="wifi_debugging_title" msgid="7300007687492186076">"Želite li dopustiti bežično otklanjanje pogrešaka na ovoj mreži?"</string>
+ <string name="wifi_debugging_title" msgid="7300007687492186076">"Dopustiti bežično otklanjanje pogrešaka na ovoj mreži?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Naziv mreže (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresa Wi‑Fija (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Uvijek dopusti na ovoj mreži"</string>
<string name="wifi_debugging_allow" msgid="4573224609684957886">"Dopusti"</string>
@@ -669,6 +669,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Novčanik"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Postavite aplikaciju za bržu i sigurniju kupnju telefonom"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Prikaži sve"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Otključajte da biste platili"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nije postavljeno"</string>
@@ -1090,7 +1091,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g>, <xliff:g id="ARTIST_NAME">%2$s</xliff:g> reproducira se putem aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reprodukcija"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvori <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g>, <xliff:g id="ARTIST_NAME">%2$s</xliff:g> putem aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g> putem aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, provjerite aplik."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Pogreška, pokušavamo ponovo…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
@@ -1109,7 +1114,7 @@
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Odabrano uređaja: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nije povezano)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije bilo moguće. Pokušajte ponovo."</string>
- <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj međuverzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj međuverzije kopiran je u međuspremnik."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 0fe63af..2022281 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Ébresztés"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Végezze el a beállítást a telefonjával való gyorsabb és biztonságosabb vásárláshoz"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Összes mutatása"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Feloldás a fizetéshez"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nincs beállítva"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Elvetés"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Folytatás"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Beállítások"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> <xliff:g id="SONG_NAME">%1$s</xliff:g> című száma hallható itt: <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Játék"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> megnyitása"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> <xliff:g id="SONG_NAME">%1$s</xliff:g> című számának lejátszása innen: <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> lejátszása innen: <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktív, ellenőrizze az appot"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hiba, újrapróbálkozás…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nem található"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 73a32d3..4fb191f 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -536,7 +536,7 @@
<string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Այս սարքը պատկանում է «<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>» կազմակերպությանը և միացված է վիրտուալ մասնավոր ցանցերի"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Ձեր կազմակերպությունը կարող է վերահսկել ձեր աշխատանքային պրոֆիլի ցանցային թրաֆիկը"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> կազմակերպությունը կարող է վերահսկել ձեր աշխատանքային պրոֆիլի ցանցային թրաֆիկը"</string>
- <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"Աշխատանքային պրոֆիլով կատարված գործողությունները տեսանելի են ձեր ՏՏ ադմինիստրատորին"</string>
+ <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"Աշխատանքային պրոֆիլով կատարված գործողությունները տեսանելի են ՏՏ ադմինիստրատորին"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Ցանցը կարող է վերահսկվել"</string>
<string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Այս սարքը միացված է վիրտուալ մասնավոր ցանցերի"</string>
<string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Ձեր աշխատանքային պրոֆիլը միացված է <xliff:g id="VPN_APP">%1$s</xliff:g> ցանցին"</string>
@@ -605,10 +605,10 @@
<string name="accessibility_output_chooser" msgid="7807898688967194183">"Փոխել արտածման սարքը"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Հավելվածն ամրացված է"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար հպեք և պահեք Հետ և Համատեսք կոճակները:"</string>
- <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև չապամրացնեք այն: Ապամրացնելու համար հպեք և պահեք «Հետ» և «Գլխավոր էկրան» կոճակները"</string>
- <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև որ չապամրացնեք այն: Ապամրացնելու համար մատը սահեցրեք վեր և պահեք։"</string>
+ <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև չեղարկեք ամրացումը: Չեղարկելու համար հպեք և պահեք «Հետ» և «Գլխավոր էկրան» կոճակները"</string>
+ <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Էկրանը կցուցադրվի, մինչև չեղարկեք ամրացումը: Չեղարկելու համար մատը սահեցրեք վեր և պահեք։"</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար հպեք և պահեք Համատեսք կոճակը:"</string>
- <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև որ չապամրացնեք այն: Ապամրացնելու համար հպեք և պահեք գլխավոր էկրանի կոճակը:"</string>
+ <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Էկրանը կցուցադրվի, մինչև չեղարկեք ամրացումը: Չեղարկելու համար հպեք և պահեք գլխավոր էկրանի կոճակը:"</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Ձեր անձնական տվյալները (օր․՝ կոնտակտները և նամակների բովանդակությունը) կարող են հասանելի դառնալ։"</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Ամրացված հավելվածը կարող է այլ հավելվածներ գործարկել։"</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"Հավելվածն ապամրացնելու համար հպեք և պահեք «Հետ» և «Համատեսք» կոճակները"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Զարթուցիչ"</string>
<string name="wallet_title" msgid="5369767670735827105">"Դրամապանակ"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Վճարեք հեռախոսով՝ ավելի արագ և ապահով"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Ցույց տալ բոլորը"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Ապակողպել՝ վճարելու համար"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Կարգավորված չէ"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Փակել"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Շարունակել"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Կարգավորումներ"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Այժմ նվագարկվում է <xliff:g id="SONG_NAME">%1$s</xliff:g> երգը <xliff:g id="ARTIST_NAME">%2$s</xliff:g>-ի կատարմամբ <xliff:g id="APP_LABEL">%3$s</xliff:g> հավելվածից"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Նվագարկել"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Բացեք <xliff:g id="APP_LABEL">%1$s</xliff:g> հավելվածը"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Նվագարկել <xliff:g id="SONG_NAME">%1$s</xliff:g> երգը <xliff:g id="ARTIST_NAME">%2$s</xliff:g>-ի կատարմամբ <xliff:g id="APP_LABEL">%3$s</xliff:g> հավելվածից"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Նվագարկել <xliff:g id="SONG_NAME">%1$s</xliff:g> երգը <xliff:g id="APP_LABEL">%2$s</xliff:g> հավելվածից"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Ակտիվ չէ, ստուգեք հավելվածը"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Սխալ. նորից ենք փորձում…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Չի գտնվել"</string>
@@ -1126,7 +1131,7 @@
<string name="anniversary_status_content_description" msgid="8212171790843327442">"Այսօր <xliff:g id="NAME">%1$s</xliff:g>-ի տարեդարձն է"</string>
<string name="location_status" msgid="1294990572202541812">"Տեղադրության ցուցադրում"</string>
<string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> օգտատերը հայտնում է իր տեղադրության մասին տվյալները"</string>
- <string name="new_story_status" msgid="9012195158584846525">"Նոր հոդված"</string>
+ <string name="new_story_status" msgid="9012195158584846525">"Նոր պատմություն"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> օգտատերը նոր պատմություն է հրապարակել"</string>
<string name="video_status" msgid="4548544654316843225">"Տեսանյութ եմ դիտում"</string>
<string name="audio_status" msgid="4237055636967709208">"Բան եմ լսում"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 1bae009..7e4ba76 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Siapkan metode pembayaran untuk melakukan pembelian dengan lebih cepat dan aman menggunakan ponsel Anda"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Tampilkan semua"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Buka kunci untuk membayar"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Belum disiapkan"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Tutup"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Lanjutkan"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Setelan"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> oleh <xliff:g id="ARTIST_NAME">%2$s</xliff:g> sedang diputar dari <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Putar"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Buka <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Putar <xliff:g id="SONG_NAME">%1$s</xliff:g> oleh <xliff:g id="ARTIST_NAME">%2$s</xliff:g> dari <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Putar <xliff:g id="SONG_NAME">%1$s</xliff:g> dari <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nonaktif, periksa aplikasi"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, mencoba lagi..."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemukan"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 719c16d..229bcbb 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Vekjari"</string>
<string name="wallet_title" msgid="5369767670735827105">"Veski"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Stilltu hlutina þannig að þú getir verslað með símanum á hraðari og öruggari hátt"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Sýna allt"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Taka úr lás til að greiða"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ekki uppsett"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Hunsa"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Halda áfram"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Stillingar"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> með <xliff:g id="ARTIST_NAME">%2$s</xliff:g> er í spilun á <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Spila"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Opna <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Spila <xliff:g id="SONG_NAME">%1$s</xliff:g> með <xliff:g id="ARTIST_NAME">%2$s</xliff:g> í <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Spila <xliff:g id="SONG_NAME">%1$s</xliff:g> í <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Óvirkt, athugaðu forrit"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Villa, reynir aftur…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Fannst ekki"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index c838ca0..6c1ef8a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -100,7 +100,7 @@
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Elaboraz. registraz. schermo"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifica costante per una sessione di registrazione dello schermo"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Avviare la registrazione?"</string>
- <string name="screenrecord_description" msgid="1123231719680353736">"Durante la registrazione, il sistema Android può acquisire informazioni sensibili visibili sullo schermo o riprodotti sul tuo dispositivo, tra cui password, dati di pagamento, foto, messaggi e audio."</string>
+ <string name="screenrecord_description" msgid="1123231719680353736">"Durante la registrazione, il sistema Android può acquisire informazioni sensibili visibili sullo schermo o riprodotte sul tuo dispositivo, tra cui password, dati di pagamento, foto, messaggi e audio."</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Registra audio"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio del dispositivo"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Suoni del dispositivo, come musica, chiamate e suonerie"</string>
@@ -117,7 +117,7 @@
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Annulla"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Condividi"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Registrazione dello schermo annullata"</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"Registrazione dello schermo salvata"</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"Registrazione schermo salvata"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"Tocca per visualizzare"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Errore durante l\'eliminazione della registrazione dello schermo"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Impossibile ottenere le autorizzazioni"</string>
@@ -646,7 +646,7 @@
<string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"riattiva l\'audio"</string>
<string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrazione"</string>
<string name="volume_dialog_title" msgid="6502703403483577940">"Controlli del volume %s"</string>
- <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Chiamate e notifiche faranno suonare il dispositivo (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
+ <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"La suoneria sarà attiva per chiamate e notifiche (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
<string name="output_title" msgid="3938776561655668350">"Uscita contenuti multimediali"</string>
<string name="output_calls_title" msgid="7085583034267889109">"Uscita telefonate"</string>
<string name="output_none_found" msgid="5488087293120982770">"Nessun dispositivo trovato"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Sveglia"</string>
<string name="wallet_title" msgid="5369767670735827105">"Portafoglio"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Imposta un metodo di pagamento per effettuare acquisti in modo più rapido e sicuro con il telefono"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Espandi"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Sblocca per pagare"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nessuna configurazione"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignora"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Riprendi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Impostazioni"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> di <xliff:g id="ARTIST_NAME">%2$s</xliff:g> è in riproduzione da <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Riproduci"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Apri <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Riproduci <xliff:g id="SONG_NAME">%1$s</xliff:g> di <xliff:g id="ARTIST_NAME">%2$s</xliff:g> da <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Riproduci <xliff:g id="SONG_NAME">%1$s</xliff:g> da <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inattivo, controlla l\'app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Errore. Nuovo tentativo…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Controllo non trovato"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ce2a991..aae58cb 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -65,7 +65,7 @@
<string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"למשתמש המחובר לחשבון במכשיר הזה אין אפשרות להפעיל ניפוי באגים ב-USB. כדי להשתמש בתכונה הזו יש לעבור אל המשתמש הראשי."</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"לאשר ניפוי באגים אלחוטי ברשת הזו?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"שם הרשת (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nכתובת Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
- <string name="wifi_debugging_always" msgid="2968383799517975155">"אפשר תמיד ברשת הזו"</string>
+ <string name="wifi_debugging_always" msgid="2968383799517975155">"לאשר תמיד ברשת הזו"</string>
<string name="wifi_debugging_allow" msgid="4573224609684957886">"אישור"</string>
<string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"אין הרשאה לניפוי באגים אלחוטי"</string>
<string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"למשתמש המחובר לחשבון במכשיר הזה אין אפשרות להפעיל ניפוי באגים אלחוטי. כדי להשתמש בתכונה הזו, יש לעבור אל המשתמש הראשי."</string>
@@ -672,6 +672,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"אתרנט"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"התראה"</string>
<string name="wallet_title" msgid="5369767670735827105">"ארנק"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"מגדירים אמצעי תשלום ונהנים מביצוע מהיר ומאובטח יותר של רכישות באמצעות הטלפון"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"הצגת הכול"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"לביטול הנעילה ולתשלום"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"לא מוגדר"</string>
@@ -747,11 +748,11 @@
<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>
- <string name="notification_priority_title" msgid="2079708866333537093">"עדיפות"</string>
+ <string name="notification_priority_title" msgid="2079708866333537093">"בעדיפות גבוהה"</string>
<string name="no_shortcut" msgid="8257177117568230126">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לא תומכת בתכונות השיחה"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"לא ניתן לשנות את ההתראות האלה."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"לא ניתן להגדיר כאן את קבוצת ההתראות הזו"</string>
@@ -899,8 +900,8 @@
<string name="right_keycode" msgid="2480715509844798438">"קוד מפתח ימני"</string>
<string name="left_icon" msgid="5036278531966897006">"סמל שמאלי"</string>
<string name="right_icon" msgid="1103955040645237425">"סמל ימני"</string>
- <string name="drag_to_add_tiles" msgid="8933270127508303672">"יש ללחוץ ולגרור כדי להוסיף אריחים"</string>
- <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"יש ללחוץ ולגרור כדי לסדר מחדש את האריחים"</string>
+ <string name="drag_to_add_tiles" msgid="8933270127508303672">"יש ללחוץ ולגרור כדי להוסיף כרטיסי מידע"</string>
+ <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"יש ללחוץ ולגרור כדי לסדר מחדש את כרטיסי המידע"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"אפשר לגרור לכאן כדי להסיר"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"יש צורך ב-<xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> אריחים לפחות"</string>
<string name="qs_edit" msgid="5583565172803472437">"עריכה"</string>
@@ -1096,7 +1097,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"סגירה"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"המשך"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"הגדרות"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> של <xliff:g id="ARTIST_NAME">%2$s</xliff:g> מופעל מ-<xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"הפעלה"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"פתיחה של <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"הפעלת <xliff:g id="SONG_NAME">%1$s</xliff:g> של <xliff:g id="ARTIST_NAME">%2$s</xliff:g> מ-<xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"הפעלת <xliff:g id="SONG_NAME">%1$s</xliff:g> מ-<xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"לא פעיל, יש לבדוק את האפליקציה"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"שגיאה, מתבצע ניסיון חוזר…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"לא נמצא"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index ad55398..2ba73b3 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"イーサネット"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"アラーム"</string>
<string name="wallet_title" msgid="5369767670735827105">"ウォレット"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"スマートフォンを使ってよりすばやく安全に購入できるように設定しましょう"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"すべて表示"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ロックを解除して支払う"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"未設定"</string>
@@ -730,7 +731,7 @@
<string name="notification_silence_title" msgid="8608090968400832335">"サイレント"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"デフォルト"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"自動"</string>
- <string name="notification_channel_summary_low" msgid="4860617986908931158">"着信音もバイブレーションも無効です"</string>
+ <string name="notification_channel_summary_low" msgid="4860617986908931158">"着信音もバイブレーションも無効になります"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"着信音もバイブレーションも無効になり会話セクションの下に表示されます"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"スマートフォンの設定を基に着信音またはバイブレーションが有効になります"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"スマートフォンの設定を基に着信音またはバイブレーションが有効になります。デフォルトでは <xliff:g id="APP_NAME">%1$s</xliff:g> からの会話がバブルとして表示されます。"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"閉じる"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"再開"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g>(アーティスト名: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>)が <xliff:g id="APP_LABEL">%3$s</xliff:g> で再生中"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"再生"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> を開く"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g>(アーティスト名: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>)を <xliff:g id="APP_LABEL">%3$s</xliff:g> で再生"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> を <xliff:g id="APP_LABEL">%2$s</xliff:g> で再生"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"無効: アプリをご確認ください"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"エラー。再試行しています…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"見つかりませんでした"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index fae5977..1f071a2 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ეთერნეტი"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"მაღვიძარა"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"დააყენეთ შესყიდვების თქვენი ტელეფონით უფრო სწრაფად და უსაფრთხოდ შესასრულებლად"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ყველას ჩვენება"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"გადასახდელად განბლოკვა"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"არ არის დაყენებული"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"დახურვა"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"გაგრძელება"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"პარამეტრები"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g>, <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, უკრავს <xliff:g id="APP_LABEL">%3$s</xliff:g>-დან"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"დაკვრა"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"გახსენით <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"დაუკარით <xliff:g id="SONG_NAME">%1$s</xliff:g>, <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, <xliff:g id="APP_LABEL">%3$s</xliff:g>-დან"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"დაუკარით <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%2$s</xliff:g>-დან"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"არააქტიურია, გადაამოწმეთ აპი"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"შეცდომა, ხელახალი მცდელობა…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ვერ მოიძებნა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index d12c4dc..9ab5d80 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -107,17 +107,17 @@
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Микрофон"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Құрылғыдан шығатын дыбыс және микрофон"</string>
<string name="screenrecord_start" msgid="330991441575775004">"Бастау"</string>
- <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Экрандағы бейне жазылуда."</string>
+ <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Экран жазылып жатыр."</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Экрандағы бейне және аудио жазылуда."</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Экранды түрткенде көрсету"</string>
- <string name="screenrecord_stop_text" msgid="6549288689506057686">"Тоқтату үшін түртіңіз"</string>
+ <string name="screenrecord_stop_text" msgid="6549288689506057686">"Тоқтату үшін түртіңіз."</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Тоқтату"</string>
<string name="screenrecord_pause_label" msgid="6004054907104549857">"Тоқтата тұру"</string>
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Жалғастыру"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Бас тарту"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Бөлісу"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Экранды бейнеге жазудан бас тартылды"</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"Экран жазғыш бейнесі сақталды."</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"Экран жазбасы сақталды."</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"Көру үшін түртіңіз."</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Экран бейне жазбасын жою кезінде қате кетті"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Рұқсаттар алынбады"</string>
@@ -326,7 +326,7 @@
<string name="dessert_case" msgid="9104973640704357717">"Десерт жағдайы"</string>
<string name="start_dreams" msgid="9131802557946276718">"Скринсейвер"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Этернет"</string>
- <string name="quick_settings_header_onboarding_text" msgid="1918085351115504765">"Басқа опцияларды көру үшін белгішелерді түртіп ұстап тұрыңыз"</string>
+ <string name="quick_settings_header_onboarding_text" msgid="1918085351115504765">"Басқа опцияларды көру үшін белгішелерді басып тұрыңыз"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Мазаламау"</string>
<string name="quick_settings_dnd_priority_label" msgid="6251076422352664571">"Маңыздылары ғана"</string>
<string name="quick_settings_dnd_alarms_label" msgid="1241780970469630835">"Оятқыштар ғана"</string>
@@ -604,16 +604,16 @@
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"өшіру"</string>
<string name="accessibility_output_chooser" msgid="7807898688967194183">"Шығыс құрылғыны ауыстыру"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Қолданба бекітілді"</string>
- <string name="screen_pinning_description" msgid="8699395373875667743">"Экран босатылғанға дейін көрсетіліп тұрады. Оны босату үшін \"Артқа\" және \"Шолу\" түймелерін басып тұрыңыз."</string>
- <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Экран босатылғанға дейін көрсетіліп тұрады. Оны босату үшін \"Артқа\" және \"Негізгі бет\" түймелерін түртіп, ұстап тұрыңыз"</string>
- <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Экран босатылғанға дейін көрсетіліп тұрады. Экранды босату үшін жоғары сырғытып, ұстап тұрыңыз."</string>
- <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Экран босатылғанға дейін көрсетіліп тұрады. Оны босату үшін \"Кері\" түймесін басып тұрыңыз."</string>
- <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Экран босатылғанға дейін көрсетіліп тұрады. Оны босату үшін \"Негізгі бет\" түймесін түртіп, ұстап тұрыңыз."</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Жеке деректер (мысалы, контактілер мен электрондық хаттар) ашық болуы мүмкін."</string>
+ <string name="screen_pinning_description" msgid="8699395373875667743">"Өзіңіз босатқаша ашық тұрады. Босату үшін \"Артқа\" және \"Шолу\" түймелерін басып тұрыңыз."</string>
+ <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Өзіңіз босатқаша ашық тұрады. Босату үшін \"Артқа\" және \"Негізгі бет\" түймелерін басып тұрыңыз"</string>
+ <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Өзіңіз босатқанша ашық тұрады. Босату үшін экранды жоғары сырғытып, ұстап тұрыңыз."</string>
+ <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Өзіңіз босатқаша ашық тұрады. Босату үшін \"Шолу\" түймесін басып тұрыңыз."</string>
+ <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Өзіңіз босатқаша ашық тұрады. Босату үшін \"Негізгі бет\" түймесін басып тұрыңыз."</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Жеке деректер (мысалы, контактілер мен электрондық хаттар) көрінуі мүмкін."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Бекітілген қолданба басқа қолданбаларды ашуы мүмкін."</string>
- <string name="screen_pinning_toast" msgid="8177286912533744328">"Бұл қолданбаны босату үшін \"Артқа\" және \"Шолу\" түймелерін түртіп, ұстап тұрыңыз."</string>
- <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Бұл қолданбаны босату үшін \"Артқа\" және \"Негізгі бет\" түймелерін түртіп, ұстап тұрыңыз."</string>
- <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Бұл қолданбаны босату үшін жоғары сырғытып, ұстап тұрыңыз."</string>
+ <string name="screen_pinning_toast" msgid="8177286912533744328">"Бұл қолданбаны босату үшін \"Артқа\" және \"Шолу\" түймелерін басып тұрыңыз."</string>
+ <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Бұл қолданбаны босату үшін \"Артқа\" және \"Негізгі бет\" түймелерін басып тұрыңыз."</string>
+ <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Бұл қолданбаны босату үшін экранды жоғары сырғытып, ұстап тұрыңыз."</string>
<string name="screen_pinning_positive" msgid="3285785989665266984">"Түсінікті"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"Жоқ, рақмет"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"Қолданба бекітілді."</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Дабыл"</string>
<string name="wallet_title" msgid="5369767670735827105">"Әмиян"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Телефоныңызбен бұрынғыдан да жылдам әрі қауіпсіз сатып алу үшін параметрлерді орнатыңыз."</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Барлығын көрсету"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Төлеу үшін құлыпты ашу"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Реттелмеген"</string>
@@ -741,12 +742,12 @@
<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_channel_summary_priority_all" msgid="7151752959650048285">"Әңгіме туралы хабарландырулардың жоғарғы жағында тұрады және құлыптаулы экранда профиль суреті болып көрсетіледі, қалқыма хабар түрінде шығады, Мазаламау режимін тоқтатады."</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Параметрлер"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Маңызды"</string>
- <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> әңгімелесу функцияларын қолдамайды."</string>
+ <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> әңгіме функцияларын қолдамайды."</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Бұл хабарландыруларды өзгерту мүмкін емес."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Мұндай хабарландырулар бұл жерде конфигурацияланбайды."</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"Прокси-сервер арқылы жіберілген хабарландыру"</string>
@@ -1005,8 +1006,8 @@
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Қолданбаларда <xliff:g id="TYPES_LIST">%s</xliff:g> пайдаланылуда."</string>
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" және "</string>
- <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> қолданбасы пайдаланып жатыр."</string>
- <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Соңғы рет <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> қолданбасы пайдаланды."</string>
+ <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> пайдаланып жатыр."</string>
+ <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Соңғы рет <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> пайдаланды."</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(жұмыс)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефон қоңырауы"</string>
<string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(<xliff:g id="APPLICATION_NAME_S_">%s</xliff:g> арқылы)"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Жабу"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Жалғастыру"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Параметрлер"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> қолданбасында <xliff:g id="ARTIST_NAME">%2$s</xliff:g> орындайтын \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" әні ойнатылуда."</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Ойнату"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> қолданбасын ашу"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> қолданбасында <xliff:g id="ARTIST_NAME">%2$s</xliff:g> орындайтын \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" әнін ойнату"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> қолданбасында \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" әнін ойнату"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Өшірулі. Қолданба тексеріңіз."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Қате, әрекет қайталануда…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Табылмады"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 8aeab28..6ce7300 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"អ៊ីសឺរណិត"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"ម៉ោងរោទ៍"</string>
<string name="wallet_title" msgid="5369767670735827105">"កាបូប"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"ធ្វើការរៀបចំ ដើម្បីធ្វើការទិញកាន់តែលឿនជាងមុន សុវត្ថិភាពជាងមុន ដោយប្រើទូរសព្ទរបស់អ្នក"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"បង្ហាញទាំងអស់"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ដោះសោដើម្បីបង់ប្រាក់"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"មិនបានរៀបចំទេ"</string>
@@ -750,7 +751,7 @@
<string name="notification_unblockable_desc" msgid="2073030886006190804">"មិនអាចកែប្រែការជូនដំណឹងទាំងនេះបានទេ។"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"មិនអាចកំណត់រចនាសម្ព័ន្ធក្រុមការជូនដំណឹងនេះនៅទីនេះបានទេ"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"ការជូនដំណឹងជាប្រូកស៊ី"</string>
- <string name="notification_channel_dialog_title" msgid="6856514143093200019">"ការជូនដំណឹងទាំងអស់របស់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="notification_channel_dialog_title" msgid="6856514143093200019">"ការជូនដំណឹងទាំងអស់ពី <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="see_more_title" msgid="7409317011708185729">"មើលច្រើនទៀត"</string>
<string name="appops_camera" msgid="5215967620896725715">"កម្មវិធីនេះកំពុងប្រើកាមេរ៉ា។"</string>
<string name="appops_microphone" msgid="8805468338613070149">"កម្មវិធីនេះកំពុងប្រើមីក្រូហ្វូន។"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ច្រានចោល"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"បន្ត"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ការកំណត់"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ច្រៀងដោយ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> កំពុងចាក់ពី <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ចាក់"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"បើក <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"ចាក់ <xliff:g id="SONG_NAME">%1$s</xliff:g> ច្រៀងដោយ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ពី <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"ចាក់ <xliff:g id="SONG_NAME">%1$s</xliff:g> ពី <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"អសកម្ម ពិនិត្យមើលកម្មវិធី"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"បញ្ហា កំពុងព្យាយាមម្ដងទៀត…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"រកមិនឃើញទេ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index d5557b9..78d086f 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ಇಥರ್ನೆಟ್"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"ಅಲಾರಮ್"</string>
<string name="wallet_title" msgid="5369767670735827105">"ವಾಲೆಟ್"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ವೇಗವಾದ, ಹೆಚ್ಚು ಸುರಕ್ಷಿತ ಖರೀದಿಗಳನ್ನು ಮಾಡಲು ಸೆಟಪ್ ಮಾಡಿಕೊಳ್ಳಿ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ಎಲ್ಲವನ್ನೂ ತೋರಿಸಿ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ಪಾವತಿಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ಇನ್ನೂ ಸೆಟಪ್ ಮಾಡಿಲ್ಲ"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ವಜಾಗೊಳಿಸಿ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ಪುನರಾರಂಭಿಸಿ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ಅವರ <xliff:g id="SONG_NAME">%1$s</xliff:g> ಹಾಡನ್ನು <xliff:g id="APP_LABEL">%3$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ಪ್ಲೇ ಮಾಡಿ"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ಅವರ <xliff:g id="SONG_NAME">%1$s</xliff:g> ಹಾಡನ್ನು <xliff:g id="APP_LABEL">%3$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಿ"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ಹಾಡನ್ನು <xliff:g id="APP_LABEL">%2$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಿ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ನಿಷ್ಕ್ರಿಯ, ಆ್ಯಪ್ ಪರಿಶೀಲಿಸಿ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ದೋಷ, ಮರುಪ್ರಯತ್ನಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ಕಂಡುಬಂದಿಲ್ಲ"</string>
@@ -1128,7 +1133,7 @@
<string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> ಅವರು ಸ್ಥಳವನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿದ್ದಾರೆ"</string>
<string name="new_story_status" msgid="9012195158584846525">"ಹೊಸ ಸುದ್ದಿ"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> ಅವರು ಹೊಸ ಸ್ಟೋರಿಯನ್ನು ಹಂಚಿಕೊಂಡಿದ್ದಾರೆ"</string>
- <string name="video_status" msgid="4548544654316843225">"ವೀಕ್ಷಿಸುತ್ತಿರುವವರು"</string>
+ <string name="video_status" msgid="4548544654316843225">"ವೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="audio_status" msgid="4237055636967709208">"ಆಲಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="game_status" msgid="1340694320630973259">"ಪ್ಲೇ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="empty_user_name" msgid="3389155775773578300">"ಸ್ನೇಹಿತರು"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 908eaf5..819250c4 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -412,7 +412,7 @@
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"야간 조명"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"일몰에"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"일출까지"</string>
- <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>에"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>에 켜짐"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g>에 꺼짐"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"어두운 테마"</string>
<string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"절전 모드"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"이더넷"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"알람"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"설정하여 휴대전화로 더욱 빠르고 안전하게 구매하세요."</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"모두 표시"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"잠금 해제하여 결제"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"설정되지 않음"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"닫기"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"다시 시작"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"설정"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g>에서 <xliff:g id="ARTIST_NAME">%2$s</xliff:g>의 <xliff:g id="SONG_NAME">%1$s</xliff:g> 재생 중"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"재생"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> 열기"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g>에서 <xliff:g id="ARTIST_NAME">%2$s</xliff:g>의 <xliff:g id="SONG_NAME">%1$s</xliff:g> 재생"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g>에서 <xliff:g id="SONG_NAME">%1$s</xliff:g> 재생"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"비활성. 앱을 확인하세요."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"오류 발생, 다시 시도 중…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"찾을 수 없음"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index ab53dd3..b5bbf21 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -102,10 +102,10 @@
<string name="screenrecord_start_label" msgid="1750350278888217473">"Жаздырып баштайсызбы?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Жаздыруу учурунда Android системасы экраныңызда көрүнүп турган жана түзмөктө ойноп жаткан бардык купуя маалыматты жаздырып алат. Буга сырсөздөр, төлөм маалыматы, сүрөттөр, билдирүүлөр жана аудио файлдар кирет."</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Аудио жаздыруу"</string>
- <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Түзмөктүн аудиосу"</string>
+ <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Түзмөктөгү аудиолор"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Музыка, чалуулар жана шыңгырлар сыяктуу түзмөгүңүздөгү добуштар"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Микрофон"</string>
- <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Түзмөктүн аудиосу жана микрофон"</string>
+ <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Түзмөктөгү аудиолор жана микрофон"</string>
<string name="screenrecord_start" msgid="330991441575775004">"Баштадык"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Экран жаздырылууда"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Экран жана аудио жаздырылууда"</string>
@@ -131,7 +131,7 @@
<string name="accessibility_menu" msgid="2701163794470513040">"Меню"</string>
<string name="accessibility_accessibility_button" msgid="4089042473497107709">"Атайын мүмкүнчүлүктөр"</string>
<string name="accessibility_rotate_button" msgid="1238584767612362586">"Экранды буруу"</string>
- <string name="accessibility_recent" msgid="901641734769533575">"Көз жүгүртүү"</string>
+ <string name="accessibility_recent" msgid="901641734769533575">"Назар"</string>
<string name="accessibility_search_light" msgid="524741790416076988">"Издөө"</string>
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
@@ -248,7 +248,7 @@
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Тез тууралоолор."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Кулпуланган экран."</string>
<string name="accessibility_desc_settings" msgid="6728577365389151969">"Жөндөөлөр"</string>
- <string name="accessibility_desc_recent_apps" msgid="1748675199348914194">"Көз жүгүртүү."</string>
+ <string name="accessibility_desc_recent_apps" msgid="1748675199348914194">"Назар"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Жумуштун кулпуланган экраны"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Жабуу"</string>
<string name="accessibility_quick_settings_wifi" msgid="167707325133803052">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
@@ -435,7 +435,7 @@
<string name="media_seamless_remote_device" msgid="177033467332920464">"Түзмөк"</string>
<string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Башка колдонмого которулуу үчүн өйдө сүрүңүз"</string>
<string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Колдонмолорду тез которуштуруу үчүн, оңго сүйрөңүз"</string>
- <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Сереп салууну өчүрүү/күйгүзүү"</string>
+ <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Назар режимин өчүрүү/күйгүзүү"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Кубатталды"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Кубатталууда"</string>
<string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"<xliff:g id="CHARGING_TIME">%s</xliff:g> толгонго чейин"</string>
@@ -604,10 +604,10 @@
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"өчүрүү"</string>
<string name="accessibility_output_chooser" msgid="7807898688967194183">"Аудио түзмөктү которуштуруу"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Колдонмо кадалды"</string>
- <string name="screen_pinning_description" msgid="8699395373875667743">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Артка\" жана \"Карап чыгуу\" баскычтарын басып, кармап туруңуз."</string>
+ <string name="screen_pinning_description" msgid="8699395373875667743">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн \"Артка\" жана \"Назар\" баскычтарын басып, кармап туруңуз."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Артка\" жана \"Башкы бет\" баскычтарын басып, кармап туруңуз."</string>
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн өйдө сүрүп, коё бербей басып туруңуз."</string>
- <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Карап чыгуу\" баскычын басып, кармап туруңуз."</string>
+ <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн \"Назар\" баскычын басып, кармап туруңуз."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Башкы бет\" баскычын басып, кармап туруңуз."</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Жеке маалыматтар көрүнүп калышы мүмкүн (байланыштар жана электрондук каттардын мазмуну сыяктуу)."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Кадалган колдонмо башка колдонмолорду ача алат."</string>
@@ -659,13 +659,14 @@
<string name="show_battery_percentage_summary" msgid="9053024758304102915">"Түзмөк кубатталбай турганда, батареянын деңгээли статус тилкесинде көрүнүп турат"</string>
<string name="quick_settings" msgid="6211774484997470203">"Ыкчам жөндөөлөр"</string>
<string name="status_bar" msgid="4357390266055077437">"Абал тилкеси"</string>
- <string name="overview" msgid="3522318590458536816">"Көз жүгүртүү"</string>
+ <string name="overview" msgid="3522318590458536816">"Назар"</string>
<string name="demo_mode" msgid="263484519766901593">"Тутум интерфейсинин демо режими"</string>
<string name="enable_demo_mode" msgid="3180345364745966431">"Демо режимин иштетүү"</string>
<string name="show_demo_mode" msgid="3677956462273059726">"Демо режимин көрсөтүү"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Ойготкуч"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Телефонуңуз менен тез жана коопсуз сатып алуу үчүн жөндөңүз"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Баарын көрсөтүү"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Төлөө үчүн кулпусун ачыңыз"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Жөндөлгөн эмес"</string>
@@ -740,7 +741,7 @@
<string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"<b>Абалы:</b> Үнсүз абалга төмөндөдү"</string>
<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_baseline" msgid="46674690072551234">"Сүйлөшүүлөр тууралуу билдирмелердин жогору жагында, ошондой эле кулпуланган экранда профилдин сүрөтү түрүндө көрүнөт"</string>
<string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Cүйлөшүүлөр тууралуу билдирмелердин жогору жагында жана кулпуланган экранда профилдин сүрөтү, ошондой эле калкып чыкма билдирме катары көрсөтүлөт"</string>
<string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Cүйлөшүүлөр тууралуу билдирмелердин жогору жагында жана кулпуланган экранда профилдин сүрөтү катары көрсөтүлүп, \"Тынчымды алба\" режимин үзгүлтүккө учуратат"</string>
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Cүйлөшүүлөр тууралуу билдирмелердин жогору жагында жана кулпуланган экранда профилдин сүрөтү, ошондой эле калкып чыкма билдирме катары көрсөтүлүп, \"Тынчымды алба\" режимин үзгүлтүккө учуратат"</string>
@@ -768,8 +769,8 @@
<string name="feedback_prompt" msgid="3656728972307896379">"Иштеп чыгуучуга пикириңизди билдириңиз. Бул туурабы?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Пикириңиз үчүн рахмат!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Жарайт"</string>
- <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу үчүн эскертмени көзөмөлдөө функциялары ачылды"</string>
- <string name="notification_channel_controls_closed_accessibility" msgid="1561909368876911701">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу үчүн эскертмени көзөмөлдөө функциялары жабылды"</string>
+ <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу үчүн эскертмени башкаруу элементтери ачылды"</string>
+ <string name="notification_channel_controls_closed_accessibility" msgid="1561909368876911701">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу үчүн эскертмени башкаруу элементтери жабылды"</string>
<string name="notification_channel_switch_accessibility" msgid="8979885820432540252">"Бул каналдан келген эскертмелерге уруксат берүү"</string>
<string name="notification_more_settings" msgid="4936228656989201793">"Дагы жөндөөлөр"</string>
<string name="notification_app_settings" msgid="8963648463858039377">"Ыңгайлаштыруу"</string>
@@ -1041,11 +1042,11 @@
<string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Ичине жылдырып, көрсөтүңүз"</string>
<string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Сыртка жылдырып, көрсөтүңүз"</string>
<string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"өчүрүү/күйгүзүү"</string>
- <string name="quick_controls_title" msgid="7095074621086860062">"Үйдү көзөмөлдөө каражаттары"</string>
+ <string name="quick_controls_title" msgid="7095074621086860062">"Үйдү башкаруу элементтери"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Башкаруу элементтери кошула турган колдонмону тандоо"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
- <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> көзөмөл кошулду.</item>
- <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> көзөмөл кошулду.</item>
+ <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> башкаруу элементи кошулду.</item>
+ <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> башкаруу элементи кошулду.</item>
</plurals>
<string name="controls_removed" msgid="3731789252222856959">"Өчүрүлдү"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Сүйүктүүлөргө кошулду"</string>
@@ -1055,13 +1056,13 @@
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"сүйүктүүлөрдөн чыгаруу"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g>-позицияга жылдыруу"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"Башкаруу элементтери"</string>
- <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Ыкчам жөндөөлөрдөн кирүү үчүн көзөмөлдөө каражаттарын тандаңыз"</string>
+ <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Ыкчам жөндөөлөрдө жеткиликтүү боло турган башкаруу элементтерин тандаңыз"</string>
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Башкаруу элементтеринин иретин өзгөртүү үчүн кармап туруп, сүйрөңүз"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Бардык башкаруу элементтери өчүрүлдү"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Өзгөртүүлөр сакталган жок"</string>
<string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Башка колдонмолорду көрүү"</string>
- <string name="controls_favorite_load_error" msgid="5126216176144877419">"Көзөмөлдөр жүктөлгөн жок. <xliff:g id="APP">%s</xliff:g> колдонмосуна өтүп, колдонмонун жөндөөлөрү өзгөрбөгөнүн текшериңиз."</string>
- <string name="controls_favorite_load_none" msgid="7687593026725357775">"Шайкеш көзөмөлдөр жеткиликсиз"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Башкаруу элементтери жүктөлгөн жок. <xliff:g id="APP">%s</xliff:g> колдонмосуна өтүп, колдонмонун жөндөөлөрү өзгөрбөгөнүн текшериңиз."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Шайкеш башкаруу элементтери жеткиликсиз"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Башка"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Түзмөктү башкаруу элементтерине кошуу"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Кошуу"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Жабуу"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Улантуу"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Жөндөөлөр"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ыры (аткаруучу: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) <xliff:g id="APP_LABEL">%3$s</xliff:g> колдонмосунан ойнотулуп жатат"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Ойнотуу"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> колдонмосун ачуу"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ырын (аткаруучу: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) <xliff:g id="APP_LABEL">%3$s</xliff:g> колдонмосунан ойнотуу"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ырын <xliff:g id="APP_LABEL">%2$s</xliff:g> колдонмосунан ойнотуу"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Жигерсиз. Колдонмону текшериңиз"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Ката, дагы аракет жасалууда…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Табылган жок"</string>
@@ -1094,7 +1099,7 @@
<string name="controls_error_generic" msgid="352500456918362905">"Абалы жүктөлгөн жок"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Ката, кайталап көрүңүз"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Аткарылууда"</string>
- <string name="controls_added_tooltip" msgid="5866098408470111984">"Жаңы көзөмөлдөө каражаттарын көрүү үчүн Ыкчам жөндөөлөрдү ачыңыз"</string>
+ <string name="controls_added_tooltip" msgid="5866098408470111984">"Жаңы башкаруу элементтерин көрүү үчүн Ыкчам жөндөөлөрдү ачыңыз"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Башкаруу элементтерин кошуу"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Башкаруу элементтерин түзөтүү"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Медиа түзмөктөрдү кошуу"</string>
diff --git a/packages/SystemUI/res/values-land/integers.xml b/packages/SystemUI/res/values-land/integers.xml
new file mode 100644
index 0000000..5937a07
--- /dev/null
+++ b/packages/SystemUI/res/values-land/integers.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <integer name="qs_security_footer_maxLines">1</integer>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 2c42d8f..ca4122e 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ອີເທເນັດ"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"ໂມງປຸກ"</string>
<string name="wallet_title" msgid="5369767670735827105">"ກະເປົາ"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"ຕັ້ງຄ່າເພື່ອຊື້ດ້ວຍໂທລະສັບຂອງທ່ານໄດ້ໄວຂຶ້ນ ແລະ ປອດໄພຂຶ້ນ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ສະແດງທັງໝົດ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ປົດລັອກເພື່ອຈ່າຍ"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ບໍ່ໄດ້ຕັ້ງຄ່າ"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ປິດໄວ້"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ສືບຕໍ່"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ການຕັ້ງຄ່າ"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ໂດຍ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ກຳລັງຫຼິ້ນຈາກ <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ຫຼິ້ນ"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"ເປີດ <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"ຫຼິ້ນ <xliff:g id="SONG_NAME">%1$s</xliff:g> ໂດຍ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ຈາກ <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"ຫຼິ້ນ <xliff:g id="SONG_NAME">%1$s</xliff:g> ຈາກ <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ບໍ່ເຮັດວຽກ, ກະລຸນາກວດສອບແອັບ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ຜິດພາດ, ກໍາລັງລອງໃໝ່…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ບໍ່ພົບ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 6447a3f..65a41bb 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -672,6 +672,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Eternetas"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Signalas"</string>
<string name="wallet_title" msgid="5369767670735827105">"Piniginė"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Nustatykite, kad galėtumėte greičiau ir saugiau pirkti telefonu"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Rodyti viską"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Atrakinti, kad būtų galima mokėti"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nenustatyta"</string>
@@ -747,7 +748,7 @@
<string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"<b>Būsenos:</b> reitingas padidintas"</string>
<string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>Būsenos:</b> reitingas sumažintas"</string>
<string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Rodoma pokalbių pranešimų viršuje ir kaip profilio nuotrauka užrakinimo ekrane"</string>
- <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Rodoma pokalbių pranešimų viršuje ir kaip profilio nuotrauka užrakinimo ekrane, debesėlyje"</string>
+ <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Rodoma pokalbių pranešimų viršuje ir kaip profilio nuotrauka užrakinimo ekrane, burbule"</string>
<string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Rodoma pokalbių pranešimų viršuje ir kaip profilio nuotrauka užrakinimo ekrane, pertraukia netrukdymo režimą"</string>
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Rodoma pokalbių pranešimų viršuje ir kaip profilio nuotrauka užrakinimo ekrane, debesėlyje, pertraukia netrukdymo režimą"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nustatymai"</string>
@@ -1015,8 +1016,8 @@
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Programos naudoja: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ir "</string>
- <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Naudojama <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
- <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Neseniai naudota <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Naudoja <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Neseniai naudojo <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(darbas)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefono skambutis"</string>
<string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(naud. <xliff:g id="APPLICATION_NAME_S_">%s</xliff:g>)"</string>
@@ -1096,7 +1097,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Atsisakyti"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Tęsti"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nustatymai"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> – „<xliff:g id="SONG_NAME">%1$s</xliff:g>“ leidžiama iš „<xliff:g id="APP_LABEL">%3$s</xliff:g>“"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Leisti"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Atidaryti „<xliff:g id="APP_LABEL">%1$s</xliff:g>“"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Leisti <xliff:g id="ARTIST_NAME">%2$s</xliff:g> – „<xliff:g id="SONG_NAME">%1$s</xliff:g>“ iš „<xliff:g id="APP_LABEL">%3$s</xliff:g>“"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Leisti „<xliff:g id="SONG_NAME">%1$s</xliff:g>“ iš „<xliff:g id="APP_LABEL">%2$s</xliff:g>“"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktyvu, patikrinkite progr."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Klaida, bandoma iš naujo…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nerasta"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 4157862..13de036 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -669,6 +669,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Tīkls Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Signāls"</string>
<string name="wallet_title" msgid="5369767670735827105">"Maks"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Iestatiet, lai ātrāk un drošāk veiktu pirkumus, izmantojot tālruni"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Rādīt visu"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Lai maksātu, atbloķējiet ekrānu"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nav iestatīts"</string>
@@ -1090,7 +1091,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Nerādīt"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Atsākt"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Iestatījumi"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Tiek atskaņots fails “<xliff:g id="SONG_NAME">%1$s</xliff:g>” (izpildītājs: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) no lietotnes <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Atskaņot"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Atveriet lietotni <xliff:g id="APP_LABEL">%1$s</xliff:g>."</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Atskaņojiet failu “<xliff:g id="SONG_NAME">%1$s</xliff:g>” (izpildītājs: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) no lietotnes <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Atskaņojiet failu “<xliff:g id="SONG_NAME">%1$s</xliff:g>” no lietotnes <xliff:g id="APP_LABEL">%2$s</xliff:g>."</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktīva, pārbaudiet lietotni"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Radās kļūda. Mēģina vēlreiz…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Netika atrasta"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index b7862d9..b70e2e5 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Етернет"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Аларм"</string>
<string name="wallet_title" msgid="5369767670735827105">"Паричник"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Поставете за да купувате побрзо и побезбедно преку вашиот телефон"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Прикажи ги сите"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Отклучете за да платите"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Не е поставено"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Отфрли"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Продолжи"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Поставки"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> од <xliff:g id="ARTIST_NAME">%2$s</xliff:g> е пуштено на <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Пушти"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Отворете <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Пуштете <xliff:g id="SONG_NAME">%1$s</xliff:g> од <xliff:g id="ARTIST_NAME">%2$s</xliff:g> на <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Пуштете <xliff:g id="SONG_NAME">%1$s</xliff:g> на <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивна, провери апликација"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Грешка, повторен обид…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не е најдено"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 8a4499f..746d6f4 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ഇതർനെറ്റ്"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"അലാറം"</string>
<string name="wallet_title" msgid="5369767670735827105">"വാലറ്റ്"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"നിങ്ങളുടെ ഫോൺ ഉപയോഗിച്ച് വാങ്ങലുകൾ വേഗത്തിലും സുരക്ഷിതമായും നടത്താനുള്ള സജ്ജീകരണം നടത്തുക"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"എല്ലാം കാണിക്കുക"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"പണമടയ്ക്കാൻ അൺലോക്ക് ചെയ്യുക"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"സജ്ജീകരിച്ചിട്ടില്ല"</string>
@@ -733,7 +734,7 @@
<string name="notification_channel_summary_low" msgid="4860617986908931158">"ശബ്ദമോ വൈബ്രേഷനോ ഇല്ല"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"ശബ്ദമോ വൈബ്രേഷനോ ഇല്ല, സംഭാഷണ വിഭാഗത്തിന് താഴെയായി ദൃശ്യമാകും"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"ഫോൺ ക്രമീകരണം അടിസ്ഥാനമാക്കി റിംഗ്/വൈബ്രേറ്റ് ചെയ്യും"</string>
- <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ഫോൺ ക്രമീകരണം അടിസ്ഥാനമാക്കി റിംഗ് ചെയ്തേക്കാം അല്ലെങ്കിൽ വൈബ്രേറ്റ് ചെയ്തേക്കാം. <xliff:g id="APP_NAME">%1$s</xliff:g>-ൽ നിന്നുള്ള സംഭാഷണങ്ങൾ ഡിഫോൾട്ടായി ബബ്ൾ ആവുന്നു."</string>
+ <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ഫോൺ ക്രമീകരണം അടിസ്ഥാനമാക്കി റിംഗ് ചെയ്തേക്കാം അല്ലെങ്കിൽ വൈബ്രേറ്റ് ചെയ്തേക്കാം. <xliff:g id="APP_NAME">%1$s</xliff:g>-ൽ നിന്നുള്ള സംഭാഷണങ്ങൾ ഡിഫോൾട്ടായി ബബിൾ ആവുന്നു."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ഈ ഉള്ളടക്കത്തിലേക്ക് ഒരു ഫ്ലോട്ടിംഗ് കുറുക്കുവഴി ഉപയോഗിച്ച് നിങ്ങളുടെ ശ്രദ്ധ നിലനിർത്തുന്നു."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ഈ അറിയിപ്പ് വരുമ്പോൾ ശബ്ദിക്കുകയാണോ വൈബ്രേറ്റ് ചെയ്യുകയാണോ വേണ്ടതെന്ന് നിർണ്ണയിക്കാൻ സിസ്റ്റത്തെ അനുവദിക്കുക"</string>
<string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"<b>നില:</b> ഡിഫോൾട്ടാക്കി പ്രമോട്ട് ചെയ്തു"</string>
@@ -746,7 +747,7 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"സംഭാഷണ അറിയിപ്പുകളുടെ മുകളിലും സ്ക്രീൻ ലോക്കായിരിക്കുമ്പോൾ ഒരു പ്രൊഫൈൽ ചിത്രമായും കാണിക്കുന്നു, ഒരു ബബിൾ രൂപത്തിൽ ദൃശ്യമാകുന്നു, ശല്യപ്പെടുത്തരുത് മോഡ് തടസ്സപ്പെടുത്തുന്നു"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ക്രമീകരണം"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"മുൻഗണന"</string>
- <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> സംഭാഷണ ഫീച്ചറുകളെ പിന്തുണയ്ക്കുന്നില്ല"</string>
+ <string name="no_shortcut" msgid="8257177117568230126">"സംഭാഷണ ഫീച്ചറുകളെ <xliff:g id="APP_NAME">%1$s</xliff:g> പിന്തുണയ്ക്കുന്നില്ല"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ഈ അറിയിപ്പുകൾ പരിഷ്ക്കരിക്കാനാവില്ല."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"അറിയിപ്പുകളുടെ ഈ ഗ്രൂപ്പ് ഇവിടെ കോണ്ഫിഗര് ചെയ്യാൻ കഴിയില്ല"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"പ്രോക്സി അറിയിപ്പ്"</string>
@@ -780,7 +781,7 @@
<string name="notification_conversation_unfavorite" msgid="181383708304763807">"പ്രധാനപ്പെട്ട സംഭാഷണമല്ല"</string>
<string name="notification_conversation_mute" msgid="268951550222925548">"നിശബ്ദമാക്കി"</string>
<string name="notification_conversation_unmute" msgid="2692255619510896710">"മുന്നറിയിപ്പ് നൽകൽ"</string>
- <string name="notification_conversation_bubble" msgid="2242180995373949022">"ബബ്ൾ ആയി കാണിക്കുക"</string>
+ <string name="notification_conversation_bubble" msgid="2242180995373949022">"ബബിൾ ആയി കാണിക്കുക"</string>
<string name="notification_conversation_unbubble" msgid="6908427185031099868">"ബബിളുകൾ നീക്കം ചെയ്യുക"</string>
<string name="notification_conversation_home_screen" msgid="8347136037958438935">"ഹോം സ്ക്രീനിലേക്ക് ചേർക്കുക"</string>
<string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ഡിസ്മിസ് ചെയ്യുക"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"പുനരാരംഭിക്കുക"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ക്രമീകരണം"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> എന്ന ആർട്ടിസ്റ്റിന്റെ <xliff:g id="SONG_NAME">%1$s</xliff:g> എന്ന ഗാനം <xliff:g id="APP_LABEL">%3$s</xliff:g> ആപ്പിൽ പ്ലേ ചെയ്യുന്നു"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"പ്ലേ ചെയ്യുക"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> തുറക്കുക"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> എന്ന ആർട്ടിസ്റ്റിന്റെ <xliff:g id="SONG_NAME">%1$s</xliff:g> എന്ന ഗാനം <xliff:g id="APP_LABEL">%3$s</xliff:g> ആപ്പിൽ പ്ലേ ചെയ്യുക"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> എന്ന ഗാനം <xliff:g id="APP_LABEL">%2$s</xliff:g> ആപ്പിൽ പ്ലേ ചെയ്യുക"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"നിഷ്ക്രിയം, ആപ്പ് പരിശോധിക്കൂ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"പിശക്, വീണ്ടും ശ്രമിക്കുന്നു…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"കണ്ടെത്തിയില്ല"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index c9b8495..9732fbd 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -606,18 +606,18 @@
<string name="screen_pinning_title" msgid="9058007390337841305">"Аппыг бэхэлсэн"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Таныг тогтоосныг болиулах хүртэл үүнийг харуулна. Тогтоосныг болиулахын тулд Буцах, Тоймыг дараад хүлээнэ үү."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Таныг тогтоосныг болиулах хүртэл үүнийг харуулсан хэвээр байна. Тогтоосныг болиулахын тулд Буцах, Нүүр хуудас товчлуурыг дараад хүлээнэ үү."</string>
- <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Та тогтоосныг болиулах хүртэл үүнийг харуулсан хэвээр байна. Тогтоосныг болиулахын тулд дээш удаан шударна уу."</string>
+ <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Та бэхэлснийг болиулах хүртэл үүнийг харуулсан хэвээр байна. Бэхэлснийг болиулахын тулд дээш удаан шударна уу."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Таныг тогтоосныг болиулах хүртэл харагдах болно. Тогтоосныг болиулахын тулд Буцах товчлуурыг дараад, хүлээнэ үү."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Таныг тогтоосныг болиулах хүртэл үүнийг харуулсан хэвээр байна. Тогтоосныг болиулахын тулд Нүүр хуудас товчлуурыг дараад хүлээнэ үү."</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Хувийн мэдээлэлд хандах боломжтой байж магадгүй (харилцагчид, имэйлийн контент зэрэг)."</string>
- <string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Тогтоосон апп бусад аппыг нээж магадгүй."</string>
+ <string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Бэхэлсэн апп бусад аппыг нээж магадгүй."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"Энэ аппыг тогтоосныг болиулахын тулд Буцах, Тойм товчлуурыг дараад хүлээнэ үү"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Энэ аппыг тогтоосныг болиулахын тулд Буцах, Нүүр хуудасны товчлуурыг дараад хүлээнэ үү"</string>
- <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Энэ аппыг тогтоосныг болиулахын тулд дээш шударч барина уу"</string>
+ <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Энэ аппыг бэхэлснийг болиулахын тулд дээш шударч барина уу"</string>
<string name="screen_pinning_positive" msgid="3285785989665266984">"Ойлголоо"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"Үгүй"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"Аппыг бэхэлсэн"</string>
- <string name="screen_pinning_exit" msgid="4553787518387346893">"Аппыг тогтоосныг болиулсан"</string>
+ <string name="screen_pinning_exit" msgid="4553787518387346893">"Аппыг бэхэлснийг болиулсан"</string>
<string name="quick_settings_reset_confirmation_title" msgid="463533331480997595">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>-ийг нуух уу?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"Тохируулгын хэсэгт үүнийг асаахад энэ дахин харагдана."</string>
<string name="quick_settings_reset_confirmation_button" msgid="3341477479055016776">"Нуух"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Этернет"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Сэрүүлэг"</string>
<string name="wallet_title" msgid="5369767670735827105">"Түрийвч"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Утсаараа илүү хурдан, аюулгүй худалдан авалт хийхийн тулд тохируулгыг авна уу"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Бүгдийг харуулах"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Төлөхийн тулд түгжээг тайлна уу"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Тохируулаагүй"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Хаах"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Үргэлжлүүлэх"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Тохиргоо"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> дээр тоглуулж буй <xliff:g id="ARTIST_NAME">%2$s</xliff:g>-н <xliff:g id="SONG_NAME">%1$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Тоглуулах"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g>-г нээх"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>-н <xliff:g id="SONG_NAME">%1$s</xliff:g>-г <xliff:g id="APP_LABEL">%3$s</xliff:g> дээр тоглуулах"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g>-г <xliff:g id="APP_LABEL">%2$s</xliff:g> дээр тоглуулах"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Идэвхгүй байна, аппыг шалгана уу"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Алдаа, дахин оролдож байна…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Олдсонгүй"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 2a1506f..cc7f740 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"इथरनेट"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"तुमचा फोन वापरून जलदरीत्या, अधिक सुरक्षित खरेदी करण्यासाठी सेट करा"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"सर्व दाखवा"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"पैसे देण्यासाठी अनलॉक करा"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"सेट केलेले नाही"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"डिसमिस करा"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"पुन्हा सुरू करा"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग्ज"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> मध्ये <xliff:g id="ARTIST_NAME">%2$s</xliff:g> चे <xliff:g id="SONG_NAME">%1$s</xliff:g> प्ले होत आहे"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"प्ले करणे"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> उघडा"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> मध्ये <xliff:g id="ARTIST_NAME">%2$s</xliff:g> चे <xliff:g id="SONG_NAME">%1$s</xliff:g> प्ले करा"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> मध्ये <xliff:g id="SONG_NAME">%1$s</xliff:g> प्ले करा"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय, ॲप तपासा"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"एरर, पुन्हा प्रयत्न करत आहे…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"आढळले नाही"</string>
@@ -1096,7 +1101,7 @@
<string name="controls_in_progress" msgid="4421080500238215939">"प्रगतीपथावर आहे"</string>
<string name="controls_added_tooltip" msgid="5866098408470111984">"नवीन नियंत्रणे पाहण्यासाठी क्विक सेटिंग्ज उघडा"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"नियंत्रणे जोडा"</string>
- <string name="controls_menu_edit" msgid="890623986951347062">"नियंत्रणे व्यवस्थापित करा"</string>
+ <string name="controls_menu_edit" msgid="890623986951347062">"नियंत्रणे संपादित करा"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट जोडा"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"गट"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिव्हाइस निवडले"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 24bafa8..1f97ef6 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Penggera"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Buat persediaan untuk membuat pembelian yang lebih pantas dan selamat dengan telefon anda"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Tunjukkan semua"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Buka kunci untuk membayar"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Tidak disediakan"</string>
@@ -889,7 +890,7 @@
<string name="right_keycode" msgid="2480715509844798438">"Kod kunci kanan"</string>
<string name="left_icon" msgid="5036278531966897006">"Ikon kiri"</string>
<string name="right_icon" msgid="1103955040645237425">"Ikon kanan"</string>
- <string name="drag_to_add_tiles" msgid="8933270127508303672">"Tahan dan seret untuk menambah jubin"</string>
+ <string name="drag_to_add_tiles" msgid="8933270127508303672">"Tahan dan seret untuk menambahkan jubin"</string>
<string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Tahan dan seret untuk mengatur semula jubin"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"Seret ke sini untuk mengalih keluar"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"Anda memerlukan sekurang-kurangnya <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> jubin"</string>
@@ -1042,7 +1043,7 @@
<string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Alihkan ke tepi dan tunjukkan"</string>
<string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"togol"</string>
<string name="quick_controls_title" msgid="7095074621086860062">"Kawalan rumah"</string>
- <string name="controls_providers_title" msgid="6879775889857085056">"Pilih apl untuk menambah kawalan"</string>
+ <string name="controls_providers_title" msgid="6879775889857085056">"Pilih apl untuk menambahkan kawalan"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
<item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> kawalan ditambah.</item>
<item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> kawalan ditambah.</item>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Tolak"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Sambung semula"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Tetapan"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> oleh <xliff:g id="ARTIST_NAME">%2$s</xliff:g> dimainkan daripada <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Main"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Buka <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Mainkan <xliff:g id="SONG_NAME">%1$s</xliff:g> oleh <xliff:g id="ARTIST_NAME">%2$s</xliff:g> daripada <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Mainkan <xliff:g id="SONG_NAME">%1$s</xliff:g> daripada <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Tidak aktif, semak apl"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Ralat, mencuba semula…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemukan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 11e497d..78bc991 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4811759950673118541">"စနစ်၏UI"</string>
+ <string name="app_label" msgid="4811759950673118541">"စနစ်၏ UI"</string>
<string name="status_bar_clear_all_button" msgid="2491321682873657397">"ရှင်းရန်"</string>
<string name="status_bar_no_notifications_title" msgid="7812479124981107507">"အကြောင်းကြားချက်များ မရှိ"</string>
<string name="status_bar_ongoing_events_title" msgid="3986169317496615446">"လက်ရှိအသုံးပြုမှု"</string>
@@ -117,7 +117,7 @@
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"မလုပ်တော့"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"မျှဝေရန်"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"ဖန်သားပြင် ရိုက်ကူးမှု ပယ်ဖျက်လိုက်ပါပြီ"</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"ဖန်သားပြင် ရိုက်ကူးမှုကို သိမ်းပြီးပါပြီ"</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"စကရင်ရိုက်ကူးမှု သိမ်းပြီးပြီ"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"ကြည့်ရှုရန် တို့ပါ"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"ဖန်သားပြင် ရိုက်ကူးမှု ဖျက်ရာတွင် အမှားအယွင်းရှိနေသည်"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"ခွင့်ပြုချက် မရယူနိုင်ပါ"</string>
@@ -423,7 +423,7 @@
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ကို ပိတ်ထားသည်"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ကို ဖွင့်ထားသည်"</string>
- <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ဖန်သားပြင် ရိုက်ကူးရန်"</string>
+ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"စကရင် ရိုက်ကူးရန်"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"စတင်ရန်"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ရပ်ရန်"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"စက်၏မိုက်ခရိုဖုန်းကို ပြန်ဖွင့်မလား။"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"အီသာနက်"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"နှိုးစက်"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"သင့်ဖုန်းဖြင့် ပိုမိုမြန်ဆန်၊ ပိုမိုစိတ်ချရသော ဝယ်ယူမှုများ ပြုလုပ်ရန် စတင်သတ်မှတ်ပါ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"အားလုံးပြရန်"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ငွေပေးချေရန် လော့ခ်ဖွင့်ပါ"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"စနစ် ထည့်သွင်းမထားပါ"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ပယ်ရန်"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ဆက်လုပ်ရန်"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ဆက်တင်များ"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ၏ <xliff:g id="SONG_NAME">%1$s</xliff:g> ကို <xliff:g id="APP_LABEL">%3$s</xliff:g> တွင် ဖွင့်ထားသည်"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ဖွင့်ခြင်း"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ကို ဖွင့်ပါ"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ၏ <xliff:g id="SONG_NAME">%1$s</xliff:g> ကို <xliff:g id="APP_LABEL">%3$s</xliff:g> တွင် ဖွင့်ပါ"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ကို <xliff:g id="APP_LABEL">%2$s</xliff:g> တွင် ဖွင့်ပါ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ရပ်နေသည်၊ အက်ပ်ကို စစ်ဆေးပါ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"မှားသွားသည်၊ ပြန်စမ်းနေသည်…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"မတွေ့ပါ"</string>
@@ -1096,7 +1101,7 @@
<string name="controls_in_progress" msgid="4421080500238215939">"ဆောင်ရွက်နေသည်"</string>
<string name="controls_added_tooltip" msgid="5866098408470111984">"ထိန်းချုပ်မှုအသစ်များ ကြည့်ရန် အမြန် ဆက်တင်များကို ဖွင့်ပါ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"ထိန်းချုပ်မှုများ ထည့်ရန်"</string>
- <string name="controls_menu_edit" msgid="890623986951347062">"ထိန်းချုပ်မှုများ တည်းဖြတ်ရန်"</string>
+ <string name="controls_menu_edit" msgid="890623986951347062">"ထိန်းချုပ်မှုများ ပြင်ရန်"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"မီဒီယာအထွက်များ ထည့်ရန်"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"အုပ်စု"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"စက်ပစ္စည်း ၁ ခုကို ရွေးချယ်ထားသည်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index c23e479..c181089 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4811759950673118541">"Sys.gr.snitt"</string>
+ <string name="app_label" msgid="4811759950673118541">"System-UI"</string>
<string name="status_bar_clear_all_button" msgid="2491321682873657397">"Fjern"</string>
<string name="status_bar_no_notifications_title" msgid="7812479124981107507">"Ingen varslinger"</string>
<string name="status_bar_ongoing_events_title" msgid="3986169317496615446">"Aktiviteter"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Legg til en betalingsmåte for å gjennomføre kjøp raskere og sikrere med telefonen"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Vis alle"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Lås opp for å betale"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ikke konfigurert"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Lukk"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Gjenoppta"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Innstillinger"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> av <xliff:g id="ARTIST_NAME">%2$s</xliff:g> spilles av fra <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Spill av"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Åpne <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Spill av <xliff:g id="SONG_NAME">%1$s</xliff:g> av <xliff:g id="ARTIST_NAME">%2$s</xliff:g> fra <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Spill av <xliff:g id="SONG_NAME">%1$s</xliff:g> fra <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Sjekk appen"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Feil. Prøver igjen …"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke funnet"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d25b38a..a69be5d 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -83,7 +83,7 @@
<string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रिनसट सेभ गरियो"</string>
<string name="screenshot_saved_text" msgid="7778833104901642442">"आफ्नो स्क्रिनसट हेर्न ट्याप गर्नुहोस्"</string>
<string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रिनसट सुरक्षित गर्न सकिएन"</string>
- <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"यन्त्र अनलक गरेपछि मात्र स्क्रिनसट सुरक्षित गर्न सकिन्छ"</string>
+ <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"डिभाइस अनलक गरेपछि मात्र स्क्रिनसट सुरक्षित गर्न सकिन्छ"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रिनसट फेरि लिएर हेर्नुहोस्"</string>
<string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"स्क्रिनसट सुरक्षित गर्न सकिएन"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"उक्त एप वा तपाईंको संगठनले स्क्रिनसटहरू लिन दिँदैन"</string>
@@ -103,11 +103,11 @@
<string name="screenrecord_description" msgid="1123231719680353736">"रेकर्ड गर्दा, Android सिस्टमले तपाईंको स्क्रिनमा देखिने वा तपाईंको डिभाइसमा प्ले गरिने सबै संवेदनशील जानकारी रेकर्ड गर्न सक्छ। यो जानकारीमा पासवर्ड, भुक्तानीसम्बन्धी जानकारी, फोटो, सन्देश र अडियो समावेश हुन्छ।"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"अडियो रेकर्ड गरियोस्"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"डिभाइसको अडियो"</string>
- <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"तपाईंको डिभाइसका सङ्गीत, कल र रिङटोन जस्ता आवाज"</string>
+ <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"तपाईंको डिभाइसका सङ्गीत, कल र रिङटोन जस्ता साउन्ड"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"माइक्रोफोन"</string>
- <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"डिभाइसको अडियो र माइक्रोफोनको आवाज"</string>
+ <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"डिभाइस र माइक्रोफोनको अडियो"</string>
<string name="screenrecord_start" msgid="330991441575775004">"सुरु गर्नुहोस्"</string>
- <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"स्क्रिन रेकर्ड गर्दै"</string>
+ <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"स्क्रिन रेकर्ड गरिँदै छ"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"स्क्रिन र अडियो रेकर्ड गरिँदै छ"</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"स्पर्श गरिएका स्थानहरू देखाइयोस्"</string>
<string name="screenrecord_stop_text" msgid="6549288689506057686">"रोक्न ट्याप गर्नुहोस्"</string>
@@ -400,7 +400,7 @@
</plurals>
<string name="quick_settings_notifications_label" msgid="3379631363952582758">"अधिसूचनाहरू"</string>
<string name="quick_settings_flashlight_label" msgid="4904634272006284185">"फ्ल्यासलाइट"</string>
- <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"क्यामेरा प्रयोगमा छ"</string>
+ <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"क्यामेरा प्रयोग भइरहेको छ"</string>
<string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"मोबाइल डेटा"</string>
<string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"डेटाको प्रयोग"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="1136599216568805644">"बाँकी डेटा"</string>
@@ -609,7 +609,7 @@
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"तपाईंले यो एप अनपिन नगरेसम्म यो एप यहाँ देखिइरहने छ। अनपिन गर्न माथितिर स्वाइप गरी होल्ड गर्नुहोस्।"</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न परिदृश्य बटनलाई टच एण्ड होल्ड गर्नुहोस्।"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न गृह नामक बटनलाई टच एण्ड होल्ड गर्नुहोस्।"</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"स्क्रिनमा व्यक्तिगत डेटा (जस्तै सम्पर्क ठेगाना र इमेलको सामग्री) देखिन सक्छ।"</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"स्क्रिनमा सम्पर्क ठेगाना र इमेलको सामग्री जस्ता व्यक्तिगत जानकारी देखिन सक्छ।"</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"पिन गरिएको एपले अन्य एप खोल्न सक्छ।"</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"यो एप अनपनि गर्न पछाडि र विवरण नामक बटनहरूलाई टच एण्ड होल्ड गर्नुहोस्"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"यो एप अनपनि गर्न पछाडि र होम बटनलाई टच एण्ड होल्ड गर्नुहोस्"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"इथरनेट"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
<string name="wallet_title" msgid="5369767670735827105">"वालेट"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"फोनमार्फत अझ छिटो र थप सुरक्षित तरिकाले खरिद गर्न भुक्तानी विधि सेटअप गर्नुहोस्"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"सबै देखाइयोस्"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"भुक्तानी गर्न अनलक गर्नुहोस्"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"सेटअप गरिएको छैन"</string>
@@ -730,8 +731,8 @@
<string name="notification_silence_title" msgid="8608090968400832335">"साइलेन्ट"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"डिफल्ट"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"स्वचालित"</string>
- <string name="notification_channel_summary_low" msgid="4860617986908931158">"न घन्टी बज्छ न त कम्पन नै हुन्छ"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"न घन्टी बज्छ न त कम्पन नै हुन्छ र वार्तालाप खण्डको तलतिर देखा पर्छ"</string>
+ <string name="notification_channel_summary_low" msgid="4860617986908931158">"बज्दैन पनि, भाइब्रेट पनि हुँदैन"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"बज्दैन पनि, भाइब्रेट पनि हुँदैन र वार्तालाप खण्डको तलतिर देखा पर्छ"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"फोनको सेटिङका आधारमा घन्टी बज्न वा भाइब्रेट हुन सक्छ"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फोनको सेटिङका आधारमा घन्टी बज्न वा भाइब्रेट हुन सक्छ। <xliff:g id="APP_NAME">%1$s</xliff:g> का वार्तालापहरू डिफल्ट रूपमा बबलमा देखाइन्छन्।"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ्लोटिङ सर्टकटमार्फत यो सामग्रीतर्फ तपाईंको ध्यान आकर्षित गर्दछ।"</string>
@@ -1005,8 +1006,8 @@
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"एपहरूले तपाईंको <xliff:g id="TYPES_LIST">%s</xliff:g> प्रयोग गर्दै छन्।"</string>
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" र "</string>
- <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ले प्रयोग गरिरहेको छ"</string>
- <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ले हालसालै प्रयोग गरेको थियो"</string>
+ <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>ले प्रयोग गरिरहेको छ"</string>
+ <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>ले हालसालै प्रयोग गरेको थियो"</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(कार्यालय)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"फोन कल"</string>
<string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(<xliff:g id="APPLICATION_NAME_S_">%s</xliff:g> मार्फत)"</string>
@@ -1042,7 +1043,7 @@
<string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"किनाराबाट सार्नुहोस् र देखिने पार्नु…"</string>
<string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"टगल गर्नुहोस्"</string>
<string name="quick_controls_title" msgid="7095074621086860062">"घरायसी उपकरणका नियन्त्रणहरू"</string>
- <string name="controls_providers_title" msgid="6879775889857085056">"नियन्त्रणहरू थप्नु पर्ने एप छान्नुहोस्"</string>
+ <string name="controls_providers_title" msgid="6879775889857085056">"कन्ट्रोल थप्नु पर्ने एप छान्नुहोस्"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
<item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> वटा नियन्त्र थपियो।</item>
<item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> नियन्त्र थपियो</item>
@@ -1055,9 +1056,9 @@
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"मन पर्ने कुराहरूको सूचीमा नराख्नुहोस्"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g>ले निर्देश गर्ने ठाउँमा सार्नुहोस्"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"नियन्त्रणहरू"</string>
- <string name="controls_favorite_subtitle" msgid="6481675111056961083">"आफूले द्रुत सेटिङबाट प्रयोग गर्न चाहेका नियन्त्रणहरू छान्नुहोस्"</string>
- <string name="controls_favorite_rearrange" msgid="5616952398043063519">"नियन्त्रणहरूको क्रम मिलाउन तिनलाई थिचेर ड्र्याग गर्नुहोस्"</string>
- <string name="controls_favorite_removed" msgid="5276978408529217272">"सबै नियन्त्रणहरू हटाइए"</string>
+ <string name="controls_favorite_subtitle" msgid="6481675111056961083">"आफूले द्रुत सेटिङबाट प्रयोग गर्न चाहेका कन्ट्रोल छान्नुहोस्"</string>
+ <string name="controls_favorite_rearrange" msgid="5616952398043063519">"कन्ट्रोललाई होल्ड एण्ड ड्र्याग गरी कन्ट्रोलको क्रम मिलाउनुहोस्"</string>
+ <string name="controls_favorite_removed" msgid="5276978408529217272">"सबै कन्ट्रोल हटाइए"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"परिवर्तनहरू सुरक्षित गरिएका छैनन्"</string>
<string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"अन्य एपहरू हेर्नुहोस्"</string>
<string name="controls_favorite_load_error" msgid="5126216176144877419">"नियन्त्रण सुविधाहरू लोड गर्न सकिएन। <xliff:g id="APP">%s</xliff:g> एपका सेटिङ परिवर्तन गरिएका छैनन् भन्ने कुरा सुनिश्चित गर्न उक्त एप जाँच्नुहोस्।"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"हटाउनुहोस्"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"सुचारु गर्नुहोस्"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिङ"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> को <xliff:g id="SONG_NAME">%1$s</xliff:g> बोलको गीत <xliff:g id="APP_LABEL">%3$s</xliff:g> मा बज्दै छ"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"प्ले गर्नुहोस्"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> खोल्नुहोस्"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> को <xliff:g id="SONG_NAME">%1$s</xliff:g> बोलको गीत <xliff:g id="APP_LABEL">%3$s</xliff:g> मा बजाउनुहोस्"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> बोलको गीत <xliff:g id="APP_LABEL">%2$s</xliff:g> मा बजाउनुहोस्"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय छ, एप जाँच गर्नु…"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"त्रुटि भयो, फेरि प्रयास गर्दै…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"फेला परेन"</string>
@@ -1095,8 +1100,8 @@
<string name="controls_error_failed" msgid="960228639198558525">"त्रुटि भयो, फेरि प्रयास गर्नु…"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"कार्य हुँदै छ"</string>
<string name="controls_added_tooltip" msgid="5866098408470111984">"नयाँ नियन्त्रणहरू हेर्न द्रुत सेटिङ खोल्नुहोस्"</string>
- <string name="controls_menu_add" msgid="4447246119229920050">"नियन्त्रण सुविधाहरू थप्नुहोस्"</string>
- <string name="controls_menu_edit" msgid="890623986951347062">"नियन्त्रण सुविधाहरू सम्पादन गर्नु…"</string>
+ <string name="controls_menu_add" msgid="4447246119229920050">"कन्ट्रोल थप्नुहोस्"</string>
+ <string name="controls_menu_edit" msgid="890623986951347062">"कन्ट्रोल सम्पादन गर्नुहोस्"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट यन्त्रहरू थप्नुहोस्"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"समूह"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"१ यन्त्र चयन गरियो"</string>
@@ -1124,7 +1129,7 @@
<string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"<xliff:g id="NAME">%1$s</xliff:g> को जन्मदिन चाँडै आउँदै छ"</string>
<string name="anniversary_status" msgid="1790034157507590838">"वार्षिकोत्सव"</string>
<string name="anniversary_status_content_description" msgid="8212171790843327442">"आज <xliff:g id="NAME">%1$s</xliff:g> को वार्षिकोत्सव हो"</string>
- <string name="location_status" msgid="1294990572202541812">"स्थानसम्बन्धी जानकारी सेयर गरिँदै छ"</string>
+ <string name="location_status" msgid="1294990572202541812">"लोकेसन सेयर गरिँदै छ"</string>
<string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> आफ्नो स्थानसम्बन्धी जानकारी सेयर गर्दै हुनुहुन्छ"</string>
<string name="new_story_status" msgid="9012195158584846525">"नयाँ स्टोरी"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> ले एउटा नयाँ स्टोरी सेयर गर्नुभयो"</string>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index c473229..8e6293a 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -97,4 +97,6 @@
<!-- Accessibility floating menu -->
<color name="accessibility_floating_menu_background">#B3000000</color> <!-- 70% -->
+
+ <color name="people_tile_background">@android:color/system_accent2_800</color>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 37c3657..e91f0a0 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Wekker"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Zorg dat je sneller en beter beveiligd aankopen kunt doen met je telefoon"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Alles tonen"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Ontgrendelen om te betalen"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Niet ingesteld"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Sluiten"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Hervatten"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Instellingen"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> van <xliff:g id="ARTIST_NAME">%2$s</xliff:g> wordt afgespeeld via <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Afspelen"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> openen"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> van <xliff:g id="ARTIST_NAME">%2$s</xliff:g> afspelen via <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> afspelen via <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactief, check de app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fout. Opnieuw proberen…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Niet gevonden"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 722cdc9..739885d 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -211,7 +211,7 @@
<string name="accessibility_two_bars" msgid="1335676987274417121">"ଦୁଇଟି ବାର୍ ଅଛି।"</string>
<string name="accessibility_three_bars" msgid="819417766606501295">"ତିନୋଟି ବାର୍ ଅଛି।"</string>
<string name="accessibility_signal_full" msgid="5920148525598637311">"ସିଗ୍ନାଲ୍ ଫୁଲ୍ ଅଛି।"</string>
- <string name="accessibility_desc_on" msgid="2899626845061427845">"ଚାଲୁ।"</string>
+ <string name="accessibility_desc_on" msgid="2899626845061427845">"ଚାଲୁ ଅଛି।"</string>
<string name="accessibility_desc_off" msgid="8055389500285421408">"ବନ୍ଦ।"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"ସଂଯୁକ୍ତ।"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"ସଂଯୋଗ କରୁଛି।"</string>
@@ -220,7 +220,7 @@
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ୱାଇ-ଫାଇ"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"କୌଣସି SIM ନାହିଁ।"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"ମୋବାଇଲ୍ ଡାଟା"</string>
- <string name="accessibility_cell_data_on" msgid="691666434519443162">"ମୋବାଇଲ୍ ଡାଟା ଅନ୍"</string>
+ <string name="accessibility_cell_data_on" msgid="691666434519443162">"ମୋବାଇଲ୍ ଡାଟା ଚାଲୁ ଅଛି"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ବନ୍ଦ"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ବ୍ଲୁଟୁଥ ଟିଥରିଂ।"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍।"</string>
@@ -253,11 +253,11 @@
<string name="accessibility_desc_close" msgid="8293708213442107755">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="accessibility_quick_settings_wifi" msgid="167707325133803052">"<xliff:g id="SIGNAL">%1$s</xliff:g>।"</string>
<string name="accessibility_quick_settings_wifi_changed_off" msgid="2230487165558877262">"ୱାଇ-ଫାଇ ବନ୍ଦ ଅଛି।"</string>
- <string name="accessibility_quick_settings_wifi_changed_on" msgid="1490362586009027611">"ୱାଇ-ଫାଇ ଅନ୍ ଅଛି।"</string>
+ <string name="accessibility_quick_settings_wifi_changed_on" msgid="1490362586009027611">"ୱାଇ-ଫାଇ ଚାଲୁ ଅଛି।"</string>
<string name="accessibility_quick_settings_mobile" msgid="1817825313718492906">"ମୋବାଇଲ୍ <xliff:g id="SIGNAL">%1$s</xliff:g>। <xliff:g id="TYPE">%2$s</xliff:g>। <xliff:g id="NETWORK">%3$s</xliff:g>।"</string>
<string name="accessibility_quick_settings_battery" msgid="533594896310663853">"<xliff:g id="STATE">%s</xliff:g> ବ୍ୟାଟେରୀ ଅଛି।"</string>
<string name="accessibility_quick_settings_airplane_off" msgid="1275658769368793228">"ଏୟାର୍ପ୍ଲେନ୍ ମୋଡ୍ ଅଫ୍ ଅଛି।"</string>
- <string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"ଏୟାର୍ପ୍ଲେନ୍ ମୋଡ୍ ଅନ୍ ଅଛି।"</string>
+ <string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"ଏୟାର୍ପ୍ଲେନ୍ ମୋଡ୍ ଚାଲୁ ଅଛି।"</string>
<string name="accessibility_quick_settings_airplane_changed_off" msgid="8880183481476943754">"ଏୟାର୍ପ୍ଲେନ୍ ମୋଡ୍କୁ ବନ୍ଦ କରାଯାଇଛି।"</string>
<string name="accessibility_quick_settings_airplane_changed_on" msgid="6327378061894076288">"ଏୟାର୍ପ୍ଲେନ୍ ମୋଡ୍କୁ ଚାଲୁ କରାଯାଇଛି।"</string>
<string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ସମ୍ପୂର୍ଣ୍ଣ ନୀରବତା"</string>
@@ -267,13 +267,13 @@
<string name="accessibility_quick_settings_dnd_changed_on" msgid="186315911607486129">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ଚାଲୁ ଅଛି।"</string>
<string name="accessibility_quick_settings_bluetooth" msgid="8250942386687551283">"ବ୍ଲୁଟୁଥ।"</string>
<string name="accessibility_quick_settings_bluetooth_off" msgid="3795983516942423240">"ବ୍ଲୁଟୂଥ୍ ଅଫ୍ ଅଛି।"</string>
- <string name="accessibility_quick_settings_bluetooth_on" msgid="3819082137684078013">"ବ୍ଲୁଟୂଥ୍ ଅନ୍ ଅଛି।"</string>
+ <string name="accessibility_quick_settings_bluetooth_on" msgid="3819082137684078013">"ବ୍ଲୁଟୂଥ୍ ଚାଲୁ ଅଛି।"</string>
<string name="accessibility_quick_settings_bluetooth_connecting" msgid="7362294657419149294">"ବ୍ଲୁଟୂଥ୍ ସଂଯୋଗ ହେଉଛି।"</string>
<string name="accessibility_quick_settings_bluetooth_connected" msgid="5237625393869747261">"ବ୍ଲୁ-ଟୁଥ୍କୁ ସଂଯୋଗ କରାଯାଇଛି।"</string>
<string name="accessibility_quick_settings_bluetooth_changed_off" msgid="3344226652293797283">"ବ୍ଲୁ-ଟୁଥ୍କୁ ବନ୍ଦ କରିଦିଆଯାଇଛି।"</string>
<string name="accessibility_quick_settings_bluetooth_changed_on" msgid="1263282011749437549">"ବ୍ଲୁ-ଟୁଥ୍କୁ ଚାଲୁ କରାଯାଇଛି।"</string>
<string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"ଲୋକେଶନ୍ର ତଥ୍ୟ ବନ୍ଦ ଅଛି।"</string>
- <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"ଲୋକେଶନ୍ର ତଥ୍ୟ ଅନ୍ ଅଛି।"</string>
+ <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"ଲୋକେସନର ରିପୋର୍ଟିଂ ଚାଲୁ ଅଛି।"</string>
<string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"ଲୋକେଶନ୍ର ରିପୋର୍ଟ ବନ୍ଦ କରାଗଲା।"</string>
<string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"ଲୋକେଶନ୍ର ରିପୋର୍ଟ ଅନ୍ କରାଗଲା।"</string>
<string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"<xliff:g id="TIME">%s</xliff:g>ରେ ଆଲାର୍ମ ସେଟ୍ କରାଯାଇଛି।"</string>
@@ -284,11 +284,11 @@
<string name="accessibility_quick_settings_flashlight_unavailable" msgid="7458591827288347635">"ଟର୍ଚ୍ଚ ଲାଇଟ୍ ଅନୁପଲବ୍ଧ।"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="3785616827729850766">"ଫ୍ଲାସ୍ଲାଇଟ୍ ଚାଲୁଅଛି।"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3782375441381402599">"ଟର୍ଚ୍ଚ ଲାଇଟ୍ ବନ୍ଦ ଅଛି।"</string>
- <string name="accessibility_quick_settings_flashlight_changed_on" msgid="4747870681508334200">"ଟର୍ଚ୍ଚ ଲାଇଟ୍ ଅନ୍ ଅଛି।"</string>
+ <string name="accessibility_quick_settings_flashlight_changed_on" msgid="4747870681508334200">"ଟର୍ଚ୍ଚ ଲାଇଟ୍ ଚାଲୁ ଅଛି।"</string>
<string name="accessibility_quick_settings_color_inversion_changed_off" msgid="7548045840282925393">"ରଙ୍ଗ ବିପରୀତିକରଣକୁ ବନ୍ଦ କରିଦିଆଗଲା।"</string>
<string name="accessibility_quick_settings_color_inversion_changed_on" msgid="4711141858364404084">"ରଙ୍ଗ ବିପରୀତିକରଣକୁ ଚାଲୁ କରିଦିଆଗଲା।"</string>
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"ମୋବାଇଲ୍ ହଟସ୍ପଟ୍ ବନ୍ଦ ଅଛି।"</string>
- <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"ମୋବାଇଲ୍ ହଟସ୍ପଟ୍ ଅନ୍ ଅଛି।"</string>
+ <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"ମୋବାଇଲ୍ ହଟସ୍ପଟ୍ ଚାଲୁ ଅଛି।"</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"ସ୍କ୍ରୀନ୍ କାଷ୍ଟ କରିବା ରହିଯାଇଛି।"</string>
<string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"ୱାର୍କ ମୋଡକୁ ବିରତ କରାଯାଇଛି।"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"ୱର୍କ ମୋଡ୍କୁ ଅନ୍ କରାଯାଇଛି।"</string>
@@ -392,7 +392,7 @@
<string name="quick_settings_connecting" msgid="2381969772953268809">"ସଂଯୋଗ କରୁଛି..."</string>
<string name="quick_settings_tethering_label" msgid="5257299852322475780">"ଟିଥରିଂ"</string>
<string name="quick_settings_hotspot_label" msgid="1199196300038363424">"ହଟସ୍ପଟ୍"</string>
- <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"ଅନ୍ ହେଉଛି…"</string>
+ <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"ଚାଲୁ ହେଉଛି…"</string>
<string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"ଡାଟା ସେଭର୍ ଅନ୍ ଅଛି"</string>
<plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
<item quantity="other">%d ଡିଭାଇସ୍ଗୁଡ଼ିକ</item>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ଇଥରନେଟ୍"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"ଆଲାର୍ମ"</string>
<string name="wallet_title" msgid="5369767670735827105">"ୱାଲେଟ୍"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"ଆପଣଙ୍କ ଫୋନ୍ ମାଧ୍ୟମରେ ଆହୁରି ଶୀଘ୍ର, ଅଧିକ ସୁରକ୍ଷିତ କ୍ରୟ କରିବା ପାଇଁ ସେଟ୍ ଅପ୍ କରନ୍ତୁ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ସବୁ ଦେଖାନ୍ତୁ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ପେମେଣ୍ଟ କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ସେଟ୍ ଅପ୍ କରାଯାଇନାହିଁ"</string>
@@ -696,7 +697,7 @@
<string name="qs_rearrange" msgid="484816665478662911">"ଦ୍ରୁତ ସେଟିଙ୍ଗକୁ ପୁଣି ସଜାନ୍ତୁ"</string>
<string name="show_brightness" msgid="6700267491672470007">"ଦ୍ରୁତ ସେଟିଙ୍ଗରେ ବ୍ରାଇଟନେସ୍ ଦେଖାନ୍ତୁ"</string>
<string name="experimental" msgid="3549865454812314826">"ପରୀକ୍ଷାମୂଳକ"</string>
- <string name="enable_bluetooth_title" msgid="866883307336662596">"ବ୍ଲୁଟୂଥ୍ ଅନ୍ କରିବେ?"</string>
+ <string name="enable_bluetooth_title" msgid="866883307336662596">"ବ୍ଲୁଟୂଥ୍ ଚାଲୁ କରିବେ?"</string>
<string name="enable_bluetooth_message" msgid="6740938333772779717">"ଆପଣଙ୍କ ଟାବଲେଟ୍ରେ କୀ’ବୋର୍ଡ ସଂଯୋଗ କରିବା ପାଇଁ ଆପଣଙ୍କୁ ପ୍ରଥମେ ବ୍ଲୁଟୂଥ୍ ଅନ୍ କରିବାକୁ ହେବ।"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ଚାଲୁ କରନ୍ତୁ"</string>
<string name="show_silently" msgid="5629369640872236299">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ନିରବରେ ଦେଖାନ୍ତୁ"</string>
@@ -704,7 +705,7 @@
<string name="do_not_silence" msgid="4982217934250511227">"ନିରବ କରନ୍ତୁ ନାହିଁ"</string>
<string name="do_not_silence_block" msgid="4361847809775811849">"ନିରବ କିମ୍ବା ବ୍ଲକ୍ କରନ୍ତୁ ନାହିଁ"</string>
<string name="tuner_full_importance_settings" msgid="1388025816553459059">"ପାୱାର୍ ବିଜ୍ଞପ୍ତି କଣ୍ଟ୍ରୋଲ୍"</string>
- <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ଚାଲୁ"</string>
+ <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ଚାଲୁ ଅଛି"</string>
<string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ବନ୍ଦ"</string>
<string name="power_notification_controls_description" msgid="1334963837572708952">"ପାୱାର୍ ବିଜ୍ଞପ୍ତି କଣ୍ଟ୍ରୋଲ୍ରେ, ଆପଣ ଏକ ଆପ୍ ବିଜ୍ଞପ୍ତି ପାଇଁ 0 ରୁ 5 ଗୁରୁତ୍ୱ ସ୍ତର ସେଟ୍ କରିହେବେ। \n\n"<b>"ସ୍ତର 5"</b>" \n- ବିଜ୍ଞପ୍ତି ତାଲିକାର ଶୀର୍ଷରେ ଦେଖାନ୍ତୁ \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ \n- ସର୍ବଦା ପିକ୍ କରନ୍ତୁ \n\n"<b>"ସ୍ତର 4"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- ସର୍ବଦା ପିକ୍ କରନ୍ତୁ \n\n"<b>"ସ୍ତର 3"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- କଦାପି ପିକ୍ କରନ୍ତୁ ନାହିଁ \n\n"<b>"ସ୍ତର 2"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- କଦାପି ପିକ୍ କରନ୍ତୁ ନାହିଁ \n- କଦାପି ସାଉଣ୍ଡ ଓ ଭାଇବ୍ରେଟ୍ କରନ୍ତୁ ନାହିଁ \n\n"<b>"ସ୍ତର 1"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- କଦାପି ପିକ୍ କରନ୍ତୁ ନାହିଁ \n- କଦାପି ସାଉଣ୍ଡ ଓ ଭାଇବ୍ରେଟ୍ କରନ୍ତୁ ନାହିଁ \n- ଲକ୍ ସ୍କ୍ରୀନ୍ ଓ ଷ୍ଟାଟସ୍ ବାର୍ରୁ ଲୁଚାନ୍ତୁ \n- ବିଜ୍ଞପ୍ତି ତାଲିକାର ନିମ୍ନରେ ଦେଖାନ୍ତୁ \n\n"<b>"ସ୍ତର 0"</b>" \n- ଆପରୁ ସମସ୍ତ ବିଜ୍ଞପ୍ତି ବ୍ଲକ୍ କରନ୍ତୁ"</string>
<string name="notification_header_default_channel" msgid="225454696914642444">"ବିଜ୍ଞପ୍ତି"</string>
@@ -822,7 +823,7 @@
<string name="keyboard_key_media_fast_forward" msgid="3572444327046911822">"ଫାଷ୍ଟ ଫର୍ୱାର୍ଡ"</string>
<string name="keyboard_key_page_up" msgid="173914303254199845">"ଉପର ପୃଷ୍ଠା"</string>
<string name="keyboard_key_page_down" msgid="9035902490071829731">"ତଳ ପୃଷ୍ଠା"</string>
- <string name="keyboard_key_forward_del" msgid="5325501825762733459">"ଡିଲିଟ୍"</string>
+ <string name="keyboard_key_forward_del" msgid="5325501825762733459">"ଡିଲିଟ୍ କରନ୍ତୁ"</string>
<string name="keyboard_key_move_home" msgid="3496502501803911971">"ହୋମ୍"</string>
<string name="keyboard_key_move_end" msgid="99190401463834854">"ସମାପ୍ତ"</string>
<string name="keyboard_key_insert" msgid="4621692715704410493">"ଇନ୍ସର୍ଟ"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ଖାରଜ କରନ୍ତୁ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ପୁଣି ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ସେଟିଂସ୍"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ରୁ <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ଙ୍କ <xliff:g id="SONG_NAME">%1$s</xliff:g> ଚାଲୁଛି"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ଚଲାନ୍ତୁ"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ଖୋଲନ୍ତୁ"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ରୁ <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ଙ୍କ <xliff:g id="SONG_NAME">%1$s</xliff:g> ଚଲାନ୍ତୁ"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g>ରୁ <xliff:g id="SONG_NAME">%1$s</xliff:g> ଚଲାନ୍ତୁ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ନିଷ୍କ୍ରିୟ ଅଛି, ଆପ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ତ୍ରୁଟି, ପୁଣି ଚେଷ୍ଟା କରୁଛି…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ମିଳିଲା ନାହିଁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 456cb8f..deca3ff 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -110,7 +110,7 @@
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"ਸਕ੍ਰੀਨ ਅਤੇ ਆਡੀਓ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"ਸਕ੍ਰੀਨ \'ਤੇ ਸਪਰਸ਼ਾਂ ਨੂੰ ਦਿਖਾਓ"</string>
- <string name="screenrecord_stop_text" msgid="6549288689506057686">"ਰੋਕਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <string name="screenrecord_stop_text" msgid="6549288689506057686">"ਬੰਦ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"ਬੰਦ ਕਰੋ"</string>
<string name="screenrecord_pause_label" msgid="6004054907104549857">"ਰੋਕੋ"</string>
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ਈਥਰਨੈਟ"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"ਅਲਾਰਮ"</string>
<string name="wallet_title" msgid="5369767670735827105">"ਵਾਲੇਟ"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"ਆਪਣੇ ਫ਼ੋਨ ਨਾਲ ਜ਼ਿਆਦਾ ਤੇਜ਼ ਅਤੇ ਜ਼ਿਆਦਾ ਸੁਰੱਖਿਅਤ ਖਰੀਦਾਂ ਕਰਨ ਲਈ ਸੈੱਟਅੱਪ ਕਰੋ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ਸਭ ਦਿਖਾਓ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ਭੁਗਤਾਨ ਕਰਨ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ਸੈੱਟਅੱਪ ਨਹੀਂ ਕੀਤਾ ਗਿਆ"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ਖਾਰਜ ਕਰੋ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ਸੈਟਿੰਗਾਂ"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> ਤੋਂ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ਦਾ <xliff:g id="SONG_NAME">%1$s</xliff:g> ਚੱਲ ਰਿਹਾ ਹੈ"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ਚਲਾਓ"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ਖੋਲ੍ਹੋ"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> ਤੋਂ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ਦਾ <xliff:g id="SONG_NAME">%1$s</xliff:g> ਚਲਾਓ"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> ਤੋਂ <xliff:g id="SONG_NAME">%1$s</xliff:g> ਚਲਾਓ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ਅਕਿਰਿਆਸ਼ੀਲ, ਐਪ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ਗੜਬੜ, ਮੁੜ ਕੋਸ਼ਿਸ਼ ਹੋ ਰਹੀ ਹੈ…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ਨਹੀਂ ਮਿਲਿਆ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 8217c84..217b2f2 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -102,7 +102,7 @@
<string name="screenrecord_start_label" msgid="1750350278888217473">"Rozpocząć nagrywanie?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Podczas nagrywania system Android może rejestrować wszelkie informacje poufne wyświetlane na ekranie lub odtwarzane na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Nagraj dźwięk"</string>
- <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Dźwięki odtwarzane na urządzeniu"</string>
+ <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Dźwięki z urządzenia"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Dźwięki odtwarzane na urządzeniu, na przykład muzyka, połączenia i dzwonki"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Mikrofon"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Mikrofon i dźwięki odtwarzane na urządzeniu"</string>
@@ -615,7 +615,7 @@
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Ekran będzie widoczny, dopóki go nie odepniesz. Przesuń palcem w górę i przytrzymaj, by odpiąć."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, kliknij i przytrzymaj Przegląd."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, naciśnij i przytrzymaj Ekran główny."</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Dane osobowe (np. kontakty czy treść e-maili) mogą być dostępne."</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Dostępne mogą być dane osobiste (np. kontakty czy treść e-maili)."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Przypięta aplikacja może otwierać inne aplikacje."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"Aby odpiąć tę aplikację, naciśnij i przytrzymaj przyciski Wstecz oraz Przegląd"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Aby odpiąć tę aplikację, naciśnij i przytrzymaj przyciski Wstecz oraz Ekran główny"</string>
@@ -672,6 +672,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Portfel"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Skonfiguruj formę płatności, aby szybciej i bezpieczniej płacić telefonem za zakupy"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Pokaż wszystko"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Odblokuj, aby zapłacić"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nie skonfigurowano"</string>
@@ -727,13 +728,13 @@
<string name="inline_block_button" msgid="479892866568378793">"Zablokuj"</string>
<string name="inline_keep_button" msgid="299631874103662170">"Pokazuj nadal"</string>
<string name="inline_minimize_button" msgid="1474436209299333445">"Minimalizuj"</string>
- <string name="inline_silent_button_silent" msgid="525243786649275816">"Bez dźwięku"</string>
+ <string name="inline_silent_button_silent" msgid="525243786649275816">"Ciche"</string>
<string name="inline_silent_button_stay_silent" msgid="2129254868305468743">"Zachowaj wyciszenie"</string>
<string name="inline_silent_button_alert" msgid="5705343216858250354">"Alerty"</string>
<string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Powiadamiaj dalej"</string>
<string name="inline_turn_off_notifications" msgid="8543989584403106071">"Wyłącz powiadomienia"</string>
<string name="inline_keep_showing_app" msgid="4393429060390649757">"Nadal pokazywać powiadomienia z tej aplikacji?"</string>
- <string name="notification_silence_title" msgid="8608090968400832335">"Bez dźwięku"</string>
+ <string name="notification_silence_title" msgid="8608090968400832335">"Ciche"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"Domyślne"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Automatycznie"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Brak dźwięku i wibracji"</string>
@@ -751,7 +752,7 @@
<string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekran blokady, przerywa działanie trybu Nie przeszkadzać"</string>
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekran blokady, jako dymek, przerywa działanie trybu Nie przeszkadzać"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ustawienia"</string>
- <string name="notification_priority_title" msgid="2079708866333537093">"Priorytet"</string>
+ <string name="notification_priority_title" msgid="2079708866333537093">"Priorytetowe"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje funkcji rozmów"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Tych powiadomień nie można zmodyfikować."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Tej grupy powiadomień nie można tu skonfigurować"</string>
@@ -1096,7 +1097,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odrzuć"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Wznów"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ustawienia"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Aplikacja <xliff:g id="APP_LABEL">%3$s</xliff:g> odtwarza utwór <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>)"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Odtwórz"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otwórz aplikację <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Odtwórz utwór <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) w aplikacji <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Odtwórz utwór <xliff:g id="SONG_NAME">%1$s</xliff:g> w aplikacji <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nieaktywny, sprawdź aplikację"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Błąd, próbuję jeszcze raz…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nie znaleziono"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 1945c5d..6077c54 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4811759950673118541">"Interf sist"</string>
+ <string name="app_label" msgid="4811759950673118541">"Interface do sistema"</string>
<string name="status_bar_clear_all_button" msgid="2491321682873657397">"Limpar"</string>
<string name="status_bar_no_notifications_title" msgid="7812479124981107507">"Sem notificações"</string>
<string name="status_bar_ongoing_events_title" msgid="3986169317496615446">"Em andamento"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string>
<string name="wallet_title" msgid="5369767670735827105">"Carteira"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Prepare tudo para fazer compras mais rápidas e seguras com seu smartphone"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar tudo"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Desbloqueie para pagar"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Dispositivos não configurados"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Tocando <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> no app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Iniciar"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abrir <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Tocar <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> no app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Tocar <xliff:g id="SONG_NAME">%1$s</xliff:g> no app <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando novamente…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b75085f..2e7c629 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -342,7 +342,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Aparelhos auditivos"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"A ativar..."</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"Brilho"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotação automática"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotação auto."</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rodar o ecrã automaticamente"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"Modo <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"Rotação bloqueada"</string>
@@ -352,7 +352,7 @@
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localização"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Localização Desativada"</string>
<string name="quick_settings_camera_label" msgid="5612076679385269339">"Acesso câmara"</string>
- <string name="quick_settings_mic_label" msgid="8392773746295266375">"Acesso microfone"</string>
+ <string name="quick_settings_mic_label" msgid="8392773746295266375">"Ac. microfone"</string>
<string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Disponível"</string>
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Bloqueado"</string>
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositivo multimédia"</string>
@@ -373,7 +373,7 @@
<string name="quick_settings_wifi_on_label" msgid="2489928193654318511">"Wi-Fi ligado"</string>
<string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"Não estão disponíveis redes Wi-Fi"</string>
<string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"A ativar..."</string>
- <string name="quick_settings_cast_title" msgid="2279220930629235211">"Transm. do ecrã"</string>
+ <string name="quick_settings_cast_title" msgid="2279220930629235211">"Transm. ecrã"</string>
<string name="quick_settings_casting" msgid="1435880708719268055">"Transmissão"</string>
<string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispositivo sem nome"</string>
<string name="quick_settings_cast_device_default_description" msgid="2580520859212250265">"Pronto para transmitir"</string>
@@ -408,14 +408,14 @@
<string name="quick_settings_cellular_detail_data_used" msgid="6798849610647988987">"<xliff:g id="DATA_USED">%s</xliff:g> MB utiliz."</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Limite de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Apps de trabalho"</string>
+ <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Apps trabalho"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Luz noturna"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Ativ. ao pôr-do-sol"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Até ao amanhecer"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Ativada à(s) <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Até à(s) <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema escuro"</string>
- <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Poupança de bateria"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Poup. bateria"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ativ. ao pôr do sol"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até ao amanhecer"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativado à(s) <xliff:g id="TIME">%s</xliff:g>."</string>
@@ -423,7 +423,7 @@
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"O NFC está desativado"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"O NFC está ativado"</string>
- <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Gravação do ecrã"</string>
+ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Gravação ecrã"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Parar"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Pretende desbloquear o microfone do dispositivo?"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string>
<string name="wallet_title" msgid="5369767670735827105">"Carteira"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configure para efetuar pagamentos mais rápidos e seguros com o seu telemóvel"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar tudo"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Desbloquear para pagar"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Não configurado"</string>
@@ -855,7 +856,7 @@
<string name="accessibility_long_click_tile" msgid="210472753156768705">"Abrir as definições"</string>
<string name="accessibility_status_bar_headphones" msgid="1304082414912647414">"Auscultadores ligados"</string>
<string name="accessibility_status_bar_headset" msgid="2699275863720926104">"Auscultadores com microfone integrado ligados"</string>
- <string name="data_saver" msgid="3484013368530820763">"Poupança de dados"</string>
+ <string name="data_saver" msgid="3484013368530820763">"Poup. dados"</string>
<string name="accessibility_data_saver_on" msgid="5394743820189757731">"Poupança de dados ativada"</string>
<string name="accessibility_data_saver_off" msgid="58339669022107171">"Poupança de dados desativada"</string>
<string name="switch_bar_on" msgid="1770868129120096114">"Ativado"</string>
@@ -1041,7 +1042,7 @@
<string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover p/ extremidade e ocultar"</string>
<string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Retirar extremidade e mostrar"</string>
<string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"ativar/desativar"</string>
- <string name="quick_controls_title" msgid="7095074621086860062">"Controlos domésticos"</string>
+ <string name="quick_controls_title" msgid="7095074621086860062">"Controlo casa"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Escolha uma app para adicionar controlos"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
<item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlos adicionados.</item>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignorar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Definições"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> em reprodução a partir da app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reproduzir"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abrir <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reproduzir <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> a partir da app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproduzir <xliff:g id="SONG_NAME">%1$s</xliff:g> a partir da app <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativa. Consulte a app."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. A tentar novamente…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 1945c5d..6077c54 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4811759950673118541">"Interf sist"</string>
+ <string name="app_label" msgid="4811759950673118541">"Interface do sistema"</string>
<string name="status_bar_clear_all_button" msgid="2491321682873657397">"Limpar"</string>
<string name="status_bar_no_notifications_title" msgid="7812479124981107507">"Sem notificações"</string>
<string name="status_bar_ongoing_events_title" msgid="3986169317496615446">"Em andamento"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string>
<string name="wallet_title" msgid="5369767670735827105">"Carteira"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Prepare tudo para fazer compras mais rápidas e seguras com seu smartphone"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar tudo"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Desbloqueie para pagar"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Dispositivos não configurados"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Tocando <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> no app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Iniciar"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abrir <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Tocar <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> no app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Tocar <xliff:g id="SONG_NAME">%1$s</xliff:g> no app <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando novamente…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 267c308..d6c3756 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -669,6 +669,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarmă"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configurați pentru a face achiziții mai rapide și mai sigure cu telefonul dvs."</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Afișați-le pe toate"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Deblocați pentru a plăti"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Neconfigurat"</string>
@@ -1090,7 +1091,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Închideți"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reia"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Setări"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> de la <xliff:g id="ARTIST_NAME">%2$s</xliff:g> se redă în <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Redați"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Deschideți <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Redați <xliff:g id="SONG_NAME">%1$s</xliff:g> de la <xliff:g id="ARTIST_NAME">%2$s</xliff:g> în <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Redați <xliff:g id="SONG_NAME">%1$s</xliff:g> în <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiv, verificați aplicația"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Eroare, se încearcă din nou…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nu s-a găsit"</string>
@@ -1135,8 +1140,8 @@
<string name="new_story_status" msgid="9012195158584846525">"Subiect nou"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> a trimis o poveste nouă"</string>
<string name="video_status" msgid="4548544654316843225">"Urmăresc"</string>
- <string name="audio_status" msgid="4237055636967709208">"Se ascultă"</string>
- <string name="game_status" msgid="1340694320630973259">"Se redă"</string>
+ <string name="audio_status" msgid="4237055636967709208">"Ascult"</string>
+ <string name="game_status" msgid="1340694320630973259">"Mă joc"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Prieteni"</string>
<string name="empty_status" msgid="5938893404951307749">"Conversăm prin chat diseară?"</string>
<string name="status_before_loading" msgid="1500477307859631381">"Conținutul va apărea în curând"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 6d41d9e..33f47de 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -100,14 +100,14 @@
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обработка записи с экрана…"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущее уведомление для записи видео с экрана"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Начать запись?"</string>
- <string name="screenrecord_description" msgid="1123231719680353736">"Во время записи система Android может получить доступ к конфиденциальной информации, которая видна на экране или воспроизводится на устройстве, в том числе к паролям, сведениям о платежах, фотографиям, сообщениям и аудиозаписям."</string>
+ <string name="screenrecord_description" msgid="1123231719680353736">"В записи может появиться конфиденциальная информация, которая видна на экране или воспроизводится на устройстве, например пароли, сведения о платежах, фотографии, сообщения и аудиозаписи."</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Записывать аудио"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Звук с устройства"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Звук с вашего устройства, например музыка, звонки и рингтоны"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Микрофон"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Звук с устройства и микрофон"</string>
<string name="screenrecord_start" msgid="330991441575775004">"Начать"</string>
- <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Идет запись видео с экрана."</string>
+ <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Идет запись видео с экрана"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Идет запись видео с экрана и звука"</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Показывать прикосновения к экрану"</string>
<string name="screenrecord_stop_text" msgid="6549288689506057686">"Нажмите, чтобы остановить"</string>
@@ -672,6 +672,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Будильник"</string>
<string name="wallet_title" msgid="5369767670735827105">"Кошелек"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Расплачивайтесь через телефон быстро и безопасно."</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Показать все"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Разблокировать для оплаты"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Не настроено"</string>
@@ -736,10 +737,10 @@
<string name="notification_silence_title" msgid="8608090968400832335">"Без звука"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"По умолчанию"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Автоматически"</string>
- <string name="notification_channel_summary_low" msgid="4860617986908931158">"Без звука или вибрации"</string>
+ <string name="notification_channel_summary_low" msgid="4860617986908931158">"Без звука и вибрации"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"Без звука или вибрации, появляется в нижней части списка разговоров"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Звонок или вибрация в зависимости от настроек телефона"</string>
- <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Звонок или вибрация в зависимости от настроек телефона. Разговоры из приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" по умолчанию появляются в виде всплывающего чата."</string>
+ <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Звонок или вибрация в зависимости от настроек телефона. Разговоры из приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" по умолчанию появляются в виде всплывающего чата"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привлекает ваше внимание к контенту с помощью плавающего ярлыка"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Система будет сама определять, включать ли звуковой сигнал или вибрацию для уведомления"</string>
<string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"<b>Статус:</b> повышено до уровня \"По умолчанию\""</string>
@@ -899,8 +900,8 @@
<string name="right_keycode" msgid="2480715509844798438">"Код клавиши \"Вправо\""</string>
<string name="left_icon" msgid="5036278531966897006">"Значок \"Влево\""</string>
<string name="right_icon" msgid="1103955040645237425">"Значок \"Вправо\""</string>
- <string name="drag_to_add_tiles" msgid="8933270127508303672">"Перетащите нужные элементы"</string>
- <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Чтобы изменить порядок элементов, перетащите их"</string>
+ <string name="drag_to_add_tiles" msgid="8933270127508303672">"Чтобы добавить элементы, перетащите их."</string>
+ <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Чтобы изменить порядок элементов, перетащите их."</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"Чтобы удалить, перетащите сюда"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"Должно остаться не менее <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> элементов"</string>
<string name="qs_edit" msgid="5583565172803472437">"Изменить"</string>
@@ -1015,8 +1016,8 @@
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"В приложениях используется <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
- <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Используется в приложении \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\""</string>
- <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Недавно использовалось в приложении \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\""</string>
+ <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Используется приложением \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\""</string>
+ <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Недавно использовалось приложением \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\""</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(работа)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефонный звонок"</string>
<string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(через приложение \"<xliff:g id="APPLICATION_NAME_S_">%s</xliff:g>\")"</string>
@@ -1067,7 +1068,7 @@
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"удалить из избранного"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"Переместить на позицию <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"Элементы управления"</string>
- <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Выберите элементы управления, которые будут доступны в меню \"Быстрые настройки\""</string>
+ <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Выберите виджеты управления, которые будут доступны в меню \"Быстрые настройки\"."</string>
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Чтобы изменить порядок виджетов, перетащите их."</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Все виджеты управления удалены."</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Изменения не сохранены."</string>
@@ -1096,7 +1097,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Скрыть"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Возобновить"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Воспроизводится медиафайл \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" (исполнитель: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) из приложения \"<xliff:g id="APP_LABEL">%3$s</xliff:g>\"."</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Воспроизведение"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Открыть приложение \"<xliff:g id="APP_LABEL">%1$s</xliff:g>\""</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Воспроизвести медиафайл \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" (исполнитель: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) из приложения \"<xliff:g id="APP_LABEL">%3$s</xliff:g>\""</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Воспроизвести медиафайл \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" из приложения \"<xliff:g id="APP_LABEL">%2$s</xliff:g>\""</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Нет ответа. Проверьте приложение."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Ошибка. Повторная попытка…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не найдено."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index a719c92..cc27dfb 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"එලාමය"</string>
<string name="wallet_title" msgid="5369767670735827105">"පසුම්බිය"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"ඔබගේ දුරකථනය සමඟ වඩා වේගවත්, වඩා සුරක්ෂිත මිලදී ගැනීම් සිදු කිරීමට සූදානම් වන්න"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"සියල්ල පෙන්වන්න"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ගෙවීමට අගුලු හරින්න"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"පිහිටුවා නැත"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ඉවත ලන්න"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"නැවත පටන් ගන්න"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"සැකසීම්"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>ගේ <xliff:g id="SONG_NAME">%1$s</xliff:g> ගීතය <xliff:g id="APP_LABEL">%3$s</xliff:g> වෙතින් ධාවනය වෙමින් පවතී"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"වාදනය කරන්න"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> විවෘත කරන්න"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>ගේ <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%3$s</xliff:g> වෙතින් වාදනය කරන්න"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%2$s</xliff:g> වෙතින් වාදනය කරන්න"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"අක්රියයි, යෙදුම පරීක්ෂා කරන්න"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"දෝෂයකි, නැවත උත්සාහ කරමින්…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"හමු නොවිණි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f006722..0b74313 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -117,7 +117,7 @@
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Zrušiť"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Zdieľať"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Záznam obrazovky bol zrušený"</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"Nahrávka obrazovky bola uložená"</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"Nahrávka bola uložená"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"Zobrazte klepnutím"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Pri odstraňovaní záznamu obrazovky sa vyskytla chyba"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Nepodarilo sa získať povolenia"</string>
@@ -672,6 +672,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Budík"</string>
<string name="wallet_title" msgid="5369767670735827105">"Peňaženka"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Nastavte si všetko potrebné na rýchlejšie a bezpečnejšie nákupy telefónom"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Zobraziť všetko"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Odomknúť a zaplatiť"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nenastavené"</string>
@@ -1010,7 +1011,7 @@
<string name="auto_saver_enabled_text" msgid="7889491183116752719">"Keď batéria klesne pod <xliff:g id="PERCENTAGE">%d</xliff:g> %%, automaticky sa aktivujte Šetrič batérie."</string>
<string name="open_saver_setting_action" msgid="2111461909782935190">"Nastavenia"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Dobre"</string>
- <string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="heap_dump_tile_name" msgid="2464189856478823046">"V7pis haldy SysUI"</string>
<string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> používa zoznam <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikácie používajú zoznam <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
@@ -1096,7 +1097,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Zavrieť"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Pokračovať"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavenia"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> od interpreta <xliff:g id="ARTIST_NAME">%2$s</xliff:g> sa prehráva z aplikácie <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Prehrať"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvoriť <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Prehrať skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> od interpreta <xliff:g id="ARTIST_NAME">%2$s</xliff:g> z aplikácie <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Prehrať skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> z aplikácie <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktívne, preverte aplikáciu"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Chyba, skúša sa znova…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nenájdené"</string>
@@ -1136,13 +1141,13 @@
<string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"<xliff:g id="NAME">%1$s</xliff:g> má čoskoro narodeniny"</string>
<string name="anniversary_status" msgid="1790034157507590838">"Výročie"</string>
<string name="anniversary_status_content_description" msgid="8212171790843327442">"<xliff:g id="NAME">%1$s</xliff:g> má výročie"</string>
- <string name="location_status" msgid="1294990572202541812">"Zdieľa sa poloha"</string>
+ <string name="location_status" msgid="1294990572202541812">"Zdieľam polohu"</string>
<string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> zdieľa polohu"</string>
<string name="new_story_status" msgid="9012195158584846525">"Nová správa"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> zdieľal(a) nový príbeh"</string>
- <string name="video_status" msgid="4548544654316843225">"Pozerá sa video"</string>
+ <string name="video_status" msgid="4548544654316843225">"Pozerám video"</string>
<string name="audio_status" msgid="4237055636967709208">"Počúvam"</string>
- <string name="game_status" msgid="1340694320630973259">"Hrá sa hra"</string>
+ <string name="game_status" msgid="1340694320630973259">"Hrám hru"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Priatelia"</string>
<string name="empty_status" msgid="5938893404951307749">"Poďme sa rozprávať."</string>
<string name="status_before_loading" msgid="1500477307859631381">"Obsah sa čoskoro zobrazí"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 4aea246..b4729f4 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -622,8 +622,8 @@
<string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Če želite odpeti to aplikacijo, povlecite navzgor in pridržite."</string>
<string name="screen_pinning_positive" msgid="3285785989665266984">"Razumem"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"Ne, hvala"</string>
- <string name="screen_pinning_start" msgid="7483998671383371313">"Aplikacija je pripeta"</string>
- <string name="screen_pinning_exit" msgid="4553787518387346893">"Aplikacija je odpeta"</string>
+ <string name="screen_pinning_start" msgid="7483998671383371313">"Aplikacija je pripeta."</string>
+ <string name="screen_pinning_exit" msgid="4553787518387346893">"Aplikacija je odpeta."</string>
<string name="quick_settings_reset_confirmation_title" msgid="463533331480997595">"Želite skriti <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"Znova se bo pojavila, ko jo naslednjič vklopite v nastavitvah."</string>
<string name="quick_settings_reset_confirmation_button" msgid="3341477479055016776">"Skrij"</string>
@@ -672,6 +672,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Opozorilo"</string>
<string name="wallet_title" msgid="5369767670735827105">"Denarnica"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Nastavite možnost hitrejšega in varnejšega plačevanja s telefonom."</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Prikaži vse"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Odklenite za plačevanje"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ni nastavljeno"</string>
@@ -736,7 +737,7 @@
<string name="notification_silence_title" msgid="8608090968400832335">"Tiho"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"Privzeto"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Samodejno"</string>
- <string name="notification_channel_summary_low" msgid="4860617986908931158">"Brez zvočnega opozarjanja ali vibriranja"</string>
+ <string name="notification_channel_summary_low" msgid="4860617986908931158">"Brez zvočnega opozarjanja ali vibriranja."</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"Brez zvočnega opozarjanja ali vibriranja, prikaz nižje v razdelku Pogovor."</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Zvonjenje ali vibriranje je omogočeno na podlagi nastavitev telefona."</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Zvonjenje ali vibriranje je omogočeno na podlagi nastavitev telefona. Pogovori v aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> so privzeto prikazani v oblačkih."</string>
@@ -747,7 +748,7 @@
<string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"<b>Stanje:</b> Uvrščeno višje"</string>
<string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>Stanje:</b> Uvrščeno nižje"</string>
<string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Prikaz na vrhu razdelka z obvestili za pogovor in kot profilna slika na zaklenjenem zaslonu"</string>
- <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Prikaz v obliki oblačka na vrhu razdelka z obvestili za pogovor in kot profilna slika na zaklenjenem zaslonu"</string>
+ <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Prikaz v obliki oblačka na vrhu razdelka z obvestili za pogovor in kot profilna slika na zaklenjenem zaslonu."</string>
<string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Prikaz na vrhu razdelka z obvestili za pogovor in kot profilna slika na zaklenjenem zaslonu, preglasitev načina Ne moti"</string>
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Prikaz v obliki oblačka na vrhu razdelka z obvestili za pogovor in kot profilna slika na zaklenjenem zaslonu, preglasitev načina Ne moti"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavitve"</string>
@@ -899,8 +900,8 @@
<string name="right_keycode" msgid="2480715509844798438">"Desna koda tipke"</string>
<string name="left_icon" msgid="5036278531966897006">"Leva ikona"</string>
<string name="right_icon" msgid="1103955040645237425">"Desna ikona"</string>
- <string name="drag_to_add_tiles" msgid="8933270127508303672">"Držite in povlecite, da dodate ploščice"</string>
- <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Držite in povlecite, da prerazporedite ploščice"</string>
+ <string name="drag_to_add_tiles" msgid="8933270127508303672">"Držite in povlecite, da dodate ploščice."</string>
+ <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Držite in povlecite, da prerazporedite ploščice."</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"Če želite odstraniti, povlecite sem"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"Imeti morate vsaj toliko ploščic: <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g>"</string>
<string name="qs_edit" msgid="5583565172803472437">"Uredi"</string>
@@ -1067,7 +1068,7 @@
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"odstranitev iz priljubljenih"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"Premakni na položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrolniki"</string>
- <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Izbira kontrolnikov, dostopnih v hitrih nastavitvah"</string>
+ <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Izberite kontrolnike, do katerih želite imeti dostop v hitrih nastavitvah."</string>
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Držite in povlecite, da prerazporedite kontrolnike."</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Vsi kontrolniki so bili odstranjeni."</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Spremembe niso shranjene"</string>
@@ -1096,7 +1097,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Opusti"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nadaljuj"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavitve"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Skladba <xliff:g id="SONG_NAME">%1$s</xliff:g> izvajalca <xliff:g id="ARTIST_NAME">%2$s</xliff:g> se predvaja iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Predvajaj"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Odpri aplikacijo <xliff:g id="APP_LABEL">%1$s</xliff:g>."</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Predvajaj skladbo <xliff:g id="SONG_NAME">%1$s</xliff:g> izvajalca <xliff:g id="ARTIST_NAME">%2$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Predvajaj skladbo <xliff:g id="SONG_NAME">%1$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>."</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, poglejte aplikacijo"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Napaka, vnovični poskus …"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ni mogoče najti"</string>
@@ -1107,8 +1112,8 @@
<string name="controls_error_failed" msgid="960228639198558525">"Napaka, poskusite znova"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"V teku"</string>
<string name="controls_added_tooltip" msgid="5866098408470111984">"Za ogled novih kontrolnikov odprite hitre nastavitve."</string>
- <string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrolnike"</string>
- <string name="controls_menu_edit" msgid="890623986951347062">"Uredi kontrolnike"</string>
+ <string name="controls_menu_add" msgid="4447246119229920050">"Dodajte kontrolnike"</string>
+ <string name="controls_menu_edit" msgid="890623986951347062">"Uredite kontrolnike"</string>
<string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajanje izhodov"</string>
<string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
<string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izbrana je ena naprava"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 94a16ad..3ec14ea 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -617,7 +617,7 @@
<string name="screen_pinning_positive" msgid="3285785989665266984">"E kuptova"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"Jo, faleminderit!"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"Aplikacioni u gozhdua"</string>
- <string name="screen_pinning_exit" msgid="4553787518387346893">"Aplikacioni i zhgozhduar"</string>
+ <string name="screen_pinning_exit" msgid="4553787518387346893">"Aplikacioni u zhgozhdua"</string>
<string name="quick_settings_reset_confirmation_title" msgid="463533331480997595">"Të fshihet <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"Do të rishfaqet herën tjetër kur ta aktivizoni te cilësimet."</string>
<string name="quick_settings_reset_confirmation_button" msgid="3341477479055016776">"Fshih"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Eternet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarmi"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Konfiguro për të kryer pagesa më të shpejta dhe më të sigurta përmes telefonit"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Shfaqi të gjitha"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Shkyçe për të paguar"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nuk është konfiguruar"</string>
@@ -745,7 +746,7 @@
<string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Shfaqet në krye të njoftimeve të bisedës, shfaqet si fotografia e profilit në ekranin e kyçjes dhe ndërpret modalitetin \"Mos shqetëso\""</string>
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shfaqet në krye të njoftimeve të bisedës dhe si fotografia e profilit në ekranin e kyçjes, shfaqet si flluskë dhe ndërpret modalitetin \"Mos shqetëso\""</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Cilësimet"</string>
- <string name="notification_priority_title" msgid="2079708866333537093">"Përparësia"</string>
+ <string name="notification_priority_title" msgid="2079708866333537093">"Me përparësi"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mbështet veçoritë e bisedës"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Këto njoftime nuk mund të modifikohen."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ky grup njoftimesh nuk mund të konfigurohet këtu"</string>
@@ -777,7 +778,7 @@
<string name="inline_undo" msgid="9026953267645116526">"Zhbëj"</string>
<string name="demote" msgid="6225813324237153980">"Shëno se ky njoftim nuk është një bisedë"</string>
<string name="notification_conversation_favorite" msgid="1905240206975921907">"Bashkëbisedim i rëndësishëm"</string>
- <string name="notification_conversation_unfavorite" msgid="181383708304763807">"Nuk është bashkëbisedim i rëndësishëm"</string>
+ <string name="notification_conversation_unfavorite" msgid="181383708304763807">"Nuk është bisedë e rëndësishme"</string>
<string name="notification_conversation_mute" msgid="268951550222925548">"Në heshtje"</string>
<string name="notification_conversation_unmute" msgid="2692255619510896710">"Po sinjalizon"</string>
<string name="notification_conversation_bubble" msgid="2242180995373949022">"Shfaq flluskën"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Hiq"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Vazhdo"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Cilësimet"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> nga <xliff:g id="ARTIST_NAME">%2$s</xliff:g> po luhet nga <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Luaj"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Hap <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Luaj <xliff:g id="SONG_NAME">%1$s</xliff:g> nga <xliff:g id="ARTIST_NAME">%2$s</xliff:g> nga <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Luaj <xliff:g id="SONG_NAME">%1$s</xliff:g> nga <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Joaktive, kontrollo aplikacionin"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Gabim, po provohet përsëri"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nuk u gjet"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 9409e70..70fcb26 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -669,6 +669,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Етернет"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Аларм"</string>
<string name="wallet_title" msgid="5369767670735827105">"Новчаник"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Обавите конфигурисање да бисте могли брже и сигурније да купујете помоћу телефона"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Прикажи све"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Откључај ради плаћања"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Није подешено"</string>
@@ -1011,7 +1012,7 @@
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
<string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Користи <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
- <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Недавно користио <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Недавно користио/ла <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(посао)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефонски позив"</string>
<string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(преко: <xliff:g id="APPLICATION_NAME_S_">%s</xliff:g>)"</string>
@@ -1090,7 +1091,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Одбаци"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Настави"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Подешавања"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> извођача <xliff:g id="ARTIST_NAME">%2$s</xliff:g> се пушта из апликације <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Пусти"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Отворите <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Пустите <xliff:g id="SONG_NAME">%1$s</xliff:g> извођача <xliff:g id="ARTIST_NAME">%2$s</xliff:g> из апликације <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Пустите <xliff:g id="SONG_NAME">%1$s</xliff:g> из апликације <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно. Видите апликацију"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Грешка, покушава се поново…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Није пронађено"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 598dccb..6233370 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -117,7 +117,7 @@
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Avbryt"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Dela"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Skärminspelningen har avbrutits"</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"Skärminspelningen har sparats"</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"Skärminspelning sparad"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"Tryck för att visa"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Det gick inte att radera skärminspelningen"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Behörighet saknas"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Lägg till en betalningsmetod för att betala snabbare och säkrare med telefonen"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Visa alla"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Lås upp för att betala"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Har inte konfigurerats"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Stäng"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Återuppta"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Inställningar"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> med <xliff:g id="ARTIST_NAME">%2$s</xliff:g> spelas upp från <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Spela upp"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Öppna <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Spela upp <xliff:g id="SONG_NAME">%1$s</xliff:g> med <xliff:g id="ARTIST_NAME">%2$s</xliff:g> från <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Spela upp <xliff:g id="SONG_NAME">%1$s</xliff:g> från <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv, kolla appen"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fel, försöker igen …"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hittades inte"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index fa6952c..f7e50ef 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethaneti"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Kengele"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Weka njia ya kulipa ili uweze kununua kwa njia salama na haraka zaidi ukitumia simu yako"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Onyesha zote"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Fungua ili ulipe"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Haijawekwa"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ondoa"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Endelea"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Mipangilio"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ulioimbwa na <xliff:g id="ARTIST_NAME">%2$s</xliff:g> unacheza katika <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Cheza"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Fungua <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Cheza <xliff:g id="SONG_NAME">%1$s</xliff:g> ulioimbwa na <xliff:g id="ARTIST_NAME">%2$s</xliff:g> katika <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Cheza <xliff:g id="SONG_NAME">%1$s</xliff:g> katika <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Haitumiki, angalia programu"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hitilafu, inajaribu tena…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hakipatikani"</string>
@@ -1124,13 +1129,13 @@
<string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"Siku ya kuzaliwa ya <xliff:g id="NAME">%1$s</xliff:g> inakaribia"</string>
<string name="anniversary_status" msgid="1790034157507590838">"Maadhimisho"</string>
<string name="anniversary_status_content_description" msgid="8212171790843327442">"Ni maadhimisho ya <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="location_status" msgid="1294990572202541812">"Inashiriki mahali"</string>
+ <string name="location_status" msgid="1294990572202541812">"Unashiriki mahali"</string>
<string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> anashiriki maelezo ya mahali"</string>
<string name="new_story_status" msgid="9012195158584846525">"Habari mpya"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> ameshiriki hadithi mpya"</string>
<string name="video_status" msgid="4548544654316843225">"Unatazama"</string>
- <string name="audio_status" msgid="4237055636967709208">"Inasikiliza"</string>
- <string name="game_status" msgid="1340694320630973259">"Inacheza"</string>
+ <string name="audio_status" msgid="4237055636967709208">"Unasikiliza"</string>
+ <string name="game_status" msgid="1340694320630973259">"Unacheza"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Marafiki"</string>
<string name="empty_status" msgid="5938893404951307749">"Tupige gumzo usiku!"</string>
<string name="status_before_loading" msgid="1500477307859631381">"Maudhui yataonekana hivi karibuni"</string>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 3be73ba..9f8e636 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -68,8 +68,6 @@
phone hints. -->
<dimen name="edge_tap_area_width">80dp</dimen>
- <dimen name="keyguard_indication_margin_bottom">90dp</dimen>
-
<!-- Margin on the right side of the system icon group on Keyguard. -->
<dimen name="system_icons_keyguard_padding_end">2dp</dimen>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index c93bdd6..df52b0e 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ஈதர்நெட்"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"அலாரம்"</string>
<string name="wallet_title" msgid="5369767670735827105">"வாலட்"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"மொபைல் மூலம் விரைவாகவும் பாதுகாப்பாகவும் பர்ச்சேஸ்கள் செய்ய பேமெண்ட் முறையை அமைக்கவும்"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"அனைத்தையும் காட்டு"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"பணம் செலுத்த அன்லாக் செய்க"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"அமைக்கப்படவில்லை"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"மூடுக"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"தொடர்க"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"அமைப்புகள்"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> இன் <xliff:g id="SONG_NAME">%1$s</xliff:g> பாடல் <xliff:g id="APP_LABEL">%3$s</xliff:g> ஆப்ஸில் பிளேயாகிறது"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"இயக்குதல்"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ஆப்ஸைத் திறங்கள்"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> இன் <xliff:g id="SONG_NAME">%1$s</xliff:g> பாடலை <xliff:g id="APP_LABEL">%3$s</xliff:g> ஆப்ஸில் பிளேசெய்"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> பாடலை <xliff:g id="APP_LABEL">%2$s</xliff:g> ஆப்ஸில் பிளேசெய்"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"செயலில் இல்லை , சரிபார்க்கவும்"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"பிழை, மீண்டும் முயல்கிறது…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"இல்லை"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 900277a..84b33a9 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ఈథర్నెట్"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"అలారం"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"మీ ఫోన్తో మరింత వేగంగా, సురక్షితంగా కొనుగోళ్లు చేయడానికి సెటప్ చేయండి"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"అన్నింటినీ చూపు"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"పే చేయడానికి అన్లాక్ చేయండి"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"సెటప్ చేయలేదు"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"విస్మరించు"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"కొనసాగించండి"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"సెట్టింగ్లు"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> పాడిన <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%3$s</xliff:g> నుండి ప్లే అవుతోంది"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ప్లే చేయండి"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g>ను తెరవండి"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> నుండి <xliff:g id="ARTIST_NAME">%2$s</xliff:g> పాడిన <xliff:g id="SONG_NAME">%1$s</xliff:g>ను ప్లే చేయండి"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> నుండి <xliff:g id="SONG_NAME">%1$s</xliff:g>ను ప్లే చేయండి"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ఇన్యాక్టివ్, యాప్ చెక్ చేయండి"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"లోపం, మళ్లీ ప్రయత్నిస్తోంది..."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"కనుగొనబడలేదు"</string>
@@ -1124,12 +1129,12 @@
<string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"<xliff:g id="NAME">%1$s</xliff:g> పుట్టినరోజు త్వరలో రాబోతోంది"</string>
<string name="anniversary_status" msgid="1790034157507590838">"వార్షికోత్సవం"</string>
<string name="anniversary_status_content_description" msgid="8212171790843327442">"ఇది <xliff:g id="NAME">%1$s</xliff:g> వార్షికోత్సవం"</string>
- <string name="location_status" msgid="1294990572202541812">"లొకేషన్ షేరింగ్"</string>
+ <string name="location_status" msgid="1294990572202541812">"లొకేషన్ షేర్ ఔతోంది"</string>
<string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> లొకేషన్ను షేర్ చేస్తోంది"</string>
<string name="new_story_status" msgid="9012195158584846525">"కొత్త కథనం"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> కొత్త కథనాన్ని షేర్ చేసింది"</string>
<string name="video_status" msgid="4548544654316843225">"చూస్తున్నారు"</string>
- <string name="audio_status" msgid="4237055636967709208">"వినడం"</string>
+ <string name="audio_status" msgid="4237055636967709208">"వింటున్నారు"</string>
<string name="game_status" msgid="1340694320630973259">"ఆడుతున్నారు"</string>
<string name="empty_user_name" msgid="3389155775773578300">"ఫ్రెండ్స్"</string>
<string name="empty_status" msgid="5938893404951307749">"రాత్రి చాట్ చేద్దాం!"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index b7a0cc9..2b7bc58 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4811759950673118541">"ส่วนติดต่อผู้ใช้ของระบบ"</string>
+ <string name="app_label" msgid="4811759950673118541">"อินเทอร์เฟซผู้ใช้ของระบบ"</string>
<string name="status_bar_clear_all_button" msgid="2491321682873657397">"ล้างข้อมูล"</string>
<string name="status_bar_no_notifications_title" msgid="7812479124981107507">"ไม่มีการแจ้งเตือน"</string>
<string name="status_bar_ongoing_events_title" msgid="3986169317496615446">"ดำเนินอยู่"</string>
@@ -606,14 +606,14 @@
<string name="screen_pinning_title" msgid="9058007390337841305">"ปักหมุดแอปอยู่"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"กลับ\" และ \"ภาพรวม\" ค้างไว้เพื่อเลิกตรึง"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"กลับ\" และ \"หน้าแรก\" ค้างไว้เพื่อเลิกตรึง"</string>
- <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"วิธีนี้ช่วยให้เห็นแอปบนหน้าจอตลอดจนกว่าจะเลิกปักหมุด เลื่อนขึ้นค้างไว้เพื่อเลิกปักหมุด"</string>
+ <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"วิธีนี้ช่วยให้เห็นแอปบนหน้าจอตลอดจนกว่าจะเลิกปักหมุด ปัดขึ้นค้างไว้เพื่อเลิกปักหมุด"</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"ภาพรวม\" ค้างไว้เพื่อเลิกตรึง"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"หน้าแรก\" ค้างไว้เพื่อเลิกตรึง"</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"อาจมีการเข้าถึงข้อมูลส่วนตัว (เช่น รายชื่อติดต่อและเนื้อหาในอีเมล)"</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"แอปที่ปักหมุดไว้อาจเปิดแอปอื่นๆ"</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"หากต้องการเลิกปักหมุดแอปนี้ ให้แตะปุ่ม \"กลับ\" และ \"ภาพรวม\" ค้างไว้"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"หากต้องการเลิกปักหมุดแอปนี้ ให้แตะปุ่ม \"กลับ\" และ \"หน้าแรก\" ค้างไว้"</string>
- <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"หากต้องการเลิกปักหมุดแอปนี้ ให้เลื่อนขึ้นค้างไว้"</string>
+ <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"หากต้องการเลิกปักหมุดแอปนี้ ให้ปัดขึ้นค้างไว้"</string>
<string name="screen_pinning_positive" msgid="3285785989665266984">"รับทราบ"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"ไม่เป็นไร ขอบคุณ"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"ปักหมุดแอปแล้ว"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"อีเทอร์เน็ต"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"การปลุก"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"ตั้งค่าเพื่อซื้อสินค้าและบริการด้วยโทรศัพท์ได้อย่างรวดเร็วและปลอดภัยยิ่งขึ้น"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"แสดงทั้งหมด"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ปลดล็อกเพื่อชำระเงิน"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ไม่ได้ตั้งค่า"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ปิด"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"เล่นต่อ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"การตั้งค่า"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"กำลังเปิดเพลง <xliff:g id="SONG_NAME">%1$s</xliff:g> ของ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> จาก <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"เล่น"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"เปิด <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"เปิดเพลง <xliff:g id="SONG_NAME">%1$s</xliff:g> ของ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> จาก <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"เปิดเพลง <xliff:g id="SONG_NAME">%1$s</xliff:g> จาก <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ไม่มีการใช้งาน โปรดตรวจสอบแอป"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"มีข้อผิดพลาด กำลังลองอีกครั้ง…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ไม่พบ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index f15e377..8db4e9e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"I-set up para makapagsagawa ng mas mabibilis, mas secure na pagbili gamit ang telepono mo"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Ipakita lahat"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"I-unlock para magbayad"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Hindi naka-set up"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"I-dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Ituloy"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Mga Setting"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Nagpe-play ang <xliff:g id="SONG_NAME">%1$s</xliff:g> ni/ng <xliff:g id="ARTIST_NAME">%2$s</xliff:g> mula sa <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"I-play"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Buksan ang <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"I-play ang <xliff:g id="SONG_NAME">%1$s</xliff:g> ni/ng <xliff:g id="ARTIST_NAME">%2$s</xliff:g> mula sa <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"I-play ang <xliff:g id="SONG_NAME">%1$s</xliff:g> mula sa <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Hindi aktibo, tingnan ang app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Nagka-error, sinusubukan ulit…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hindi nahanap"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 4fd84a1..568be8a 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -117,7 +117,7 @@
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"İptal"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Paylaş"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Ekran kaydı iptal edildi"</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"Ekran kaydı saklandı"</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"Ekran kaydı kaydedildi"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"Görüntülemek için dokunun"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Ekran kaydı silinirken hata oluştu"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"İzinler alınamadı"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
<string name="wallet_title" msgid="5369767670735827105">"Cüzdan"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Telefonunuzla daha hızlı ve güvenli satın alma işlemleri gerçekleştirmek için gerekli ayarları yapın"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Tümünü göster"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Ödeme için kilidi aç"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ayarlanmadı"</string>
@@ -674,8 +675,8 @@
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Kilit ekranı ayarları"</string>
<string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Uçak modu"</string>
- <string name="add_tile" msgid="6239678623873086686">"Blok ekle"</string>
- <string name="broadcast_tile" msgid="5224010633596487481">"Yayın Bloku"</string>
+ <string name="add_tile" msgid="6239678623873086686">"Kutu ekle"</string>
+ <string name="broadcast_tile" msgid="5224010633596487481">"Yayın Kutusu"</string>
<string name="zen_alarm_warning_indef" msgid="5252866591716504287">"<xliff:g id="WHEN">%1$s</xliff:g> olarak ayarlanmış bir sonraki alarmınızdan önce bu işlevi kapatmazsanız alarmı duymayacaksınız"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> olarak ayarlanmış bir sonraki alarmınızı duymayacaksınız"</string>
<string name="alarm_template" msgid="2234991538018805736">"saat: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -745,7 +746,7 @@
<string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Görüşme bildirimlerinin üstünde ve kilit ekranında profil resmi olarak gösterilir, Rahatsız Etmeyin\'i kesintiye uğratır"</string>
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Görüşme bildirimlerinin üstünde ve kilit ekranında profil resmi olarak gösterilir, baloncuk olarak görünür, Rahatsız Etmeyin\'i kesintiye uğratır"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ayarlar"</string>
- <string name="notification_priority_title" msgid="2079708866333537093">"Öncelik"</string>
+ <string name="notification_priority_title" msgid="2079708866333537093">"Öncelikli"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>, sohbet özelliklerini desteklemiyor"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirimler değiştirilemez."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Bu bildirim grubu burada yapılandırılamaz"</string>
@@ -889,10 +890,10 @@
<string name="right_keycode" msgid="2480715509844798438">"Sağ tuş kodu"</string>
<string name="left_icon" msgid="5036278531966897006">"Sol simge"</string>
<string name="right_icon" msgid="1103955040645237425">"Sağ simge"</string>
- <string name="drag_to_add_tiles" msgid="8933270127508303672">"Blok eklemek için basılı tutup sürükleyin"</string>
- <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Blokları yeniden düzenlemek için basılı tutun ve sürükleyin"</string>
+ <string name="drag_to_add_tiles" msgid="8933270127508303672">"Kutu eklemek için basılı tutup sürükleyin"</string>
+ <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Kutuları yeniden düzenlemek için basılı tutun ve sürükleyin"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"Kaldırmak için buraya sürükleyin"</string>
- <string name="drag_to_remove_disabled" msgid="933046987838658850">"En az <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> blok gerekiyor"</string>
+ <string name="drag_to_remove_disabled" msgid="933046987838658850">"En az <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> kutu gerekiyor"</string>
<string name="qs_edit" msgid="5583565172803472437">"Düzenle"</string>
<string name="tuner_time" msgid="2450785840990529997">"Saat"</string>
<string-array name="clock_options">
@@ -907,15 +908,15 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Düşük öncelikli bildirim simgelerini göster"</string>
<string name="other" msgid="429768510980739978">"Diğer"</string>
- <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"Karoyu kaldırmak için"</string>
- <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"Sona karo eklemek için"</string>
- <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Karoyu taşı"</string>
- <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Karo ekle"</string>
+ <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"Kutuyu kaldırmak için"</string>
+ <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"Sona kutu eklemek için"</string>
+ <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Kutuyu taşı"</string>
+ <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Kutu ekle"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> konumuna taşı"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> konumuna ekle"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Konum: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kart eklendi"</string>
- <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Parça kaldırıldı"</string>
+ <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kutu eklendi"</string>
+ <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kutu kaldırıldı"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Hızlı ayar düzenleyicisi."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> bildirimi: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ayarları aç."</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Kapat"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Devam ettir"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> uygulamasından <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, <xliff:g id="SONG_NAME">%1$s</xliff:g> şarkısı çalıyor"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Oynat"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> uygulamasını aç"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> uygulamasından <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, <xliff:g id="SONG_NAME">%1$s</xliff:g> şarkısını çal"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> uygulamasından <xliff:g id="SONG_NAME">%1$s</xliff:g> şarkısını çal"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Devre dışı, uygulamaya bakın"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hata, yeniden deneniyor…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Bulunamadı"</string>
@@ -1137,7 +1142,7 @@
<string name="missed_call" msgid="4228016077700161689">"Cevapsız arama"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
<string name="people_tile_description" msgid="8154966188085545556">"Yeni mesajları, cevapsız aramaları ve durum güncellemelerini görün"</string>
- <string name="people_tile_title" msgid="6589377493334871272">"Konuşma"</string>
+ <string name="people_tile_title" msgid="6589377493334871272">"Görüşme"</string>
<string name="new_notification_text_content_description" msgid="5574393603145263727">"<xliff:g id="NAME">%1$s</xliff:g> bir mesaj gönderdi"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> bir resim gönderdi"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Pil ölçeriniz okunurken sorun oluştu"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index f1bd9b4..7aef252 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -96,7 +96,7 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Знизу на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Зліва на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Справа на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
- <string name="screenrecord_name" msgid="2596401223859996572">"Відеозапис екрана"</string>
+ <string name="screenrecord_name" msgid="2596401223859996572">"Запис відео з екрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обробка записування екрана"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Почати запис?"</string>
@@ -117,7 +117,7 @@
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Скасувати"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Поділитися"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Запис екрана скасовано"</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"Запис відео з екрана збережено"</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"Запис екрана збережено"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"Натисніть, щоб переглянути"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Не вдалося видалити запис екрана"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Не вдалось отримати дозволи"</string>
@@ -427,7 +427,7 @@
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC вимкнено"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ввімкнено"</string>
- <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Запис відео з екрана"</string>
+ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Запис екрана"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Почати"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зупинити"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Надати доступ до мікрофона?"</string>
@@ -672,6 +672,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Сигнал"</string>
<string name="wallet_title" msgid="5369767670735827105">"Гаманець"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Швидше й безпечніше сплачуйте за покупки за допомогою телефона"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Показати все"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Розблокувати, щоб сплатити"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Не налаштовано"</string>
@@ -747,7 +748,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>
@@ -1096,7 +1097,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Закрити"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Відновити"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Налаштування"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Пісня \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\", яку виконує <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, грає в додатку <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Відтворення"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Відкрити додаток <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Увімкнути пісню \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\", яку виконує <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, у додатку <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Увімкнути пісню \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" у додатку <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, перейдіть у додаток"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Помилка. Повторна спроба…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не знайдено"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 4ca003d8..b8911fd 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"ایتھرنیٹ"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"الارم"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"اپنے فون سے تیز تر مزید محفوظ خریداریاں کرنے کے لیے، سیٹ اپ مکمل کریں"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"سبھی دکھائیں"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ادائیگی کرنے کے لیے غیر مقفل کریں"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"سیٹ اپ نہیں کیا گیا"</string>
@@ -746,7 +747,7 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"یہ گفتگو کی اطلاعات کے اوپری حصّے پر اور مقفل اسکرین پر پروفائل کی تصویر کے بطور دکھائی دیتا ہے، بلبلے کے بطور ظاہر ہوتا ہے، \'ڈسٹرب نہ کریں\' میں مداخلت کرتا ہے"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ترتیبات"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ترجیح"</string>
- <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> گفتگو کی خصوصیات کو سپورٹ نہیں کرتا ہے"</string>
+ <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ گفتگو کی خصوصیات کو سپورٹ نہیں کرتی ہے"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ان اطلاعات کی ترمیم نہیں کی جا سکتی۔"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"اطلاعات کے اس گروپ کو یہاں کنفیگر نہیں کیا جا سکتا"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"پراکسی اطلاع"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"برخاست کریں"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"دوبارہ شروع کریں"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ترتیبات"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> سے <xliff:g id="ARTIST_NAME">%2$s</xliff:g> کا <xliff:g id="SONG_NAME">%1$s</xliff:g> چل رہا ہے"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"چلائیں"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> کھولیں"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> سے <xliff:g id="ARTIST_NAME">%2$s</xliff:g> کا <xliff:g id="SONG_NAME">%1$s</xliff:g> چلائیں"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> سے <xliff:g id="SONG_NAME">%1$s</xliff:g> چلائیں"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غیر فعال، ایپ چیک کریں"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"خرابی، دوبارہ کوشش کی جا رہی ہے…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"نہیں ملا"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 7b4c5d9..f411938 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -342,7 +342,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Eshitish apparatlari"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Yoqilmoqda…"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"Yorqinlik"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Avtomatik burilish"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Avto-burilish"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Ekranning avtomatik burilishi"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"<xliff:g id="ID_1">%s</xliff:g> rejimi"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"Aylanmaydigan qilingan"</string>
@@ -408,7 +408,7 @@
<string name="quick_settings_cellular_detail_data_used" msgid="6798849610647988987">"<xliff:g id="DATA_USED">%s</xliff:g> sarflandi"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Cheklov: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Ogohlantirish: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Ishga oid ilovalar"</string>
+ <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Ish ilovalari"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Tungi rejim"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Kunbotarda yoqish"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Quyosh chiqqunicha"</string>
@@ -423,7 +423,7 @@
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC o‘chiq"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC yoniq"</string>
- <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Ekranni yozib olish"</string>
+ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Ekran yozuvi"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Boshlash"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Toʻxtatish"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Qurilma mikrofoni blokdan chiqarilsinmi?"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Signal"</string>
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Telefonda tezroq va xavfsizroq xarid qilish uchun sozlang"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Hammasi"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Toʻlov uchun qulfdan chiqarish"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Sozlanmagan"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Yopish"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Davom etish"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Sozlamalar"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> ilovasida ijro etilmoqda: <xliff:g id="SONG_NAME">%1$s</xliff:g> – <xliff:g id="ARTIST_NAME">%2$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Ijro"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ilovasini ochish"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> ilovasida ijro etish: <xliff:g id="SONG_NAME">%1$s</xliff:g> – <xliff:g id="ARTIST_NAME">%2$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> ilovasida ijro etilmoqda: <xliff:g id="SONG_NAME">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nofaol. Ilovani tekshiring"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Xato, qayta urinilmoqda…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Topilmadi"</string>
@@ -1128,9 +1133,9 @@
<string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> joylashuvni ulashmoqda"</string>
<string name="new_story_status" msgid="9012195158584846525">"Yangi hikoya"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> yangi hikoyani ulashdi"</string>
- <string name="video_status" msgid="4548544654316843225">"Tomosha"</string>
- <string name="audio_status" msgid="4237055636967709208">"Gapiring"</string>
- <string name="game_status" msgid="1340694320630973259">"Ijro etilmoqda"</string>
+ <string name="video_status" msgid="4548544654316843225">"Tomosha qilmoqda"</string>
+ <string name="audio_status" msgid="4237055636967709208">"Tinglamoqda"</string>
+ <string name="game_status" msgid="1340694320630973259">"Oʻynamoqda"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Doʻstlar"</string>
<string name="empty_status" msgid="5938893404951307749">"Bugun yozishaylik!"</string>
<string name="status_before_loading" msgid="1500477307859631381">"Kontent tezda chiqadi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 8d90382..1e10496 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -405,7 +405,7 @@
<string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"Sử dụng dữ liệu"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="1136599216568805644">"Dữ liệu còn lại"</string>
<string name="quick_settings_cellular_detail_over_limit" msgid="4561921367680636235">"Vượt quá giới hạn"</string>
- <string name="quick_settings_cellular_detail_data_used" msgid="6798849610647988987">"Đã sử dụng <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="6798849610647988987">"Đã dùng <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Giới hạn <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Cảnh báo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Ứng dụng công việc"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Báo thức"</string>
<string name="wallet_title" msgid="5369767670735827105">"Ví"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Thiết lập để mua hàng nhanh hơn và an toàn hơn bằng điện thoại"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Hiện tất cả"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Mở khóa để thanh toán"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Chưa thiết lập"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Đóng"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Tiếp tục"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Cài đặt"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Đang phát <xliff:g id="SONG_NAME">%1$s</xliff:g> của <xliff:g id="ARTIST_NAME">%2$s</xliff:g> trên <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Phát"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Mở <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Phát <xliff:g id="SONG_NAME">%1$s</xliff:g> của <xliff:g id="ARTIST_NAME">%2$s</xliff:g> trên <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Phát <xliff:g id="SONG_NAME">%1$s</xliff:g> trên <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Không hoạt động, hãy kiểm tra ứng dụng"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Lỗi, đang thử lại…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Không tìm thấy"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 681430b..9272b8a 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"以太网"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"闹钟"</string>
<string name="wallet_title" msgid="5369767670735827105">"电子钱包"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"开始设置,享受更加快捷安全的手机购物体验"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"全部显示"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"解锁设备才能付款"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"未设置"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"关闭"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"继续播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"设置"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"正在通过<xliff:g id="APP_LABEL">%3$s</xliff:g>播放<xliff:g id="ARTIST_NAME">%2$s</xliff:g>的《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"播放"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"打开<xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"通过<xliff:g id="APP_LABEL">%3$s</xliff:g>播放<xliff:g id="ARTIST_NAME">%2$s</xliff:g>的《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"通过<xliff:g id="APP_LABEL">%2$s</xliff:g>播放《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"无效,请检查应用"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"出现错误,正在重试…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"未找到"</string>
@@ -1129,7 +1134,7 @@
<string name="new_story_status" msgid="9012195158584846525">"新故事"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g>分享了一个新故事"</string>
<string name="video_status" msgid="4548544654316843225">"正在观看"</string>
- <string name="audio_status" msgid="4237055636967709208">"正在收听"</string>
+ <string name="audio_status" msgid="4237055636967709208">"正在听音频内容"</string>
<string name="game_status" msgid="1340694320630973259">"正在玩游戏"</string>
<string name="empty_user_name" msgid="3389155775773578300">"好友"</string>
<string name="empty_status" msgid="5938893404951307749">"今晚来聊聊吧!"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 47ffed0..fff99e4 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"以太網"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"鬧鐘"</string>
<string name="wallet_title" msgid="5369767670735827105">"電子錢包"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"完成設定後即可透過手機更快速安全地購物"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"顯示全部"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"解鎖裝置才能付款"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"未設定"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"關閉"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"正在透過 <xliff:g id="APP_LABEL">%3$s</xliff:g> 播放 <xliff:g id="ARTIST_NAME">%2$s</xliff:g> 的《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"播放"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"開啟 <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"在 <xliff:g id="APP_LABEL">%3$s</xliff:g> 播放 <xliff:g id="ARTIST_NAME">%2$s</xliff:g> 的《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"在 <xliff:g id="APP_LABEL">%2$s</xliff:g> 播放《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"已停用,請檢查應用程式"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"發生錯誤,正在重試…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"找不到"</string>
@@ -1124,12 +1129,12 @@
<string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"<xliff:g id="NAME">%1$s</xliff:g>的生日快到了"</string>
<string name="anniversary_status" msgid="1790034157507590838">"週年紀念"</string>
<string name="anniversary_status_content_description" msgid="8212171790843327442">"今天是<xliff:g id="NAME">%1$s</xliff:g>的週年紀念"</string>
- <string name="location_status" msgid="1294990572202541812">"分享位置資訊"</string>
+ <string name="location_status" msgid="1294990572202541812">"正在分享位置"</string>
<string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g>正在分享位置"</string>
- <string name="new_story_status" msgid="9012195158584846525">"最新報導"</string>
+ <string name="new_story_status" msgid="9012195158584846525">"新故事"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g>分享了新的動態消息"</string>
- <string name="video_status" msgid="4548544654316843225">"正在觀看"</string>
- <string name="audio_status" msgid="4237055636967709208">"正在聽取音訊"</string>
+ <string name="video_status" msgid="4548544654316843225">"正在觀看影片"</string>
+ <string name="audio_status" msgid="4237055636967709208">"正在收聽音訊"</string>
<string name="game_status" msgid="1340694320630973259">"正在玩遊戲"</string>
<string name="empty_user_name" msgid="3389155775773578300">"朋友"</string>
<string name="empty_status" msgid="5938893404951307749">"今晚傾下偈啦!"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 58d9231..9a278fd 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -76,7 +76,7 @@
<string name="learn_more" msgid="4690632085667273811">"瞭解詳情"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
- <string name="global_action_screenshot" msgid="2760267567509131654">"擷取螢幕畫面"</string>
+ <string name="global_action_screenshot" msgid="2760267567509131654">"螢幕截圖"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"傳送了一張圖片"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕截圖…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕截圖…"</string>
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"乙太網路"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"鬧鐘"</string>
<string name="wallet_title" msgid="5369767670735827105">"電子錢包"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"完成相關設定之後,就能以更快速安全的方式透過手機消費"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"顯示全部"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"解鎖裝置才能付款"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"未設定"</string>
@@ -731,7 +732,7 @@
<string name="notification_alert_title" msgid="3656229781017543655">"預設"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"自動"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"不震動或發出聲音"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"不震動或發出聲音,並調整排序到其他對話下方"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"不震動或發出聲音,並顯示在對話區的下方"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"根據手機的設定響鈴或震動"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能會根據手機的設定響鈴或震動。根據預設,來自「<xliff:g id="APP_NAME">%1$s</xliff:g>」的對話會以對話框形式顯示。"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"利用浮動式捷徑快速存取這項內容。"</string>
@@ -890,7 +891,7 @@
<string name="left_icon" msgid="5036278531966897006">"向左圖示"</string>
<string name="right_icon" msgid="1103955040645237425">"向右圖示"</string>
<string name="drag_to_add_tiles" msgid="8933270127508303672">"按住並拖曳即可新增設定方塊"</string>
- <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"按住並拖曳即可重新排列圖塊"</string>
+ <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"按住並拖曳即可重新排列設定方塊"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"拖曳到這裡即可移除"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"你至少必須要有 <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> 個設定方塊"</string>
<string name="qs_edit" msgid="5583565172803472437">"編輯"</string>
@@ -1055,7 +1056,7 @@
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"從收藏中移除"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"移到位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"控制項"</string>
- <string name="controls_favorite_subtitle" msgid="6481675111056961083">"選擇要透過快速設定存取的控制項"</string>
+ <string name="controls_favorite_subtitle" msgid="6481675111056961083">"選擇要顯示在「快速設定」選單中的控制項"</string>
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"按住並拖曳即可重新排列控制項"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"所有控制項都已移除"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"未儲存變更"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"關閉"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"系統正透過「<xliff:g id="APP_LABEL">%3$s</xliff:g>」播放<xliff:g id="ARTIST_NAME">%2$s</xliff:g>的〈<xliff:g id="SONG_NAME">%1$s</xliff:g>〉"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"播放"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"開啟「<xliff:g id="APP_LABEL">%1$s</xliff:g>」"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"透過「<xliff:g id="APP_LABEL">%3$s</xliff:g>」播放<xliff:g id="ARTIST_NAME">%2$s</xliff:g>的〈<xliff:g id="SONG_NAME">%1$s</xliff:g>〉"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"透過「<xliff:g id="APP_LABEL">%2$s</xliff:g>」播放〈<xliff:g id="SONG_NAME">%1$s</xliff:g>〉"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"無效,請查看應用程式"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"發生錯誤,正在重試…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"找不到控制項"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index e4ac66a..a11c5a8 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -666,6 +666,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"I-Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"I-alamu"</string>
<string name="wallet_title" msgid="5369767670735827105">"I-wallet"</string>
+ <string name="wallet_empty_state_label" msgid="7776761245237530394">"Lungela ukuthenga ngokushesha, ngokuphepha ngefoni yakho"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Bonisa konke"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Vula ukuze ukhokhele"</string>
<string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Akusethiwe"</string>
@@ -1084,7 +1085,11 @@
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Cashisa"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Qalisa kabusha"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Izilungiselelo"</string>
+ <string name="controls_media_playing_item_description" msgid="4531853311504359098">"I-<xliff:g id="SONG_NAME">%1$s</xliff:g> ka-<xliff:g id="ARTIST_NAME">%2$s</xliff:g> idlala kusuka ku-<xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Dlala"</string>
+ <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Vula i-<xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Dlala i-<xliff:g id="SONG_NAME">%1$s</xliff:g> ka-<xliff:g id="ARTIST_NAME">%2$s</xliff:g> kusuka ku-<xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
+ <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Dlala i-<xliff:g id="SONG_NAME">%1$s</xliff:g> kusuka ku-<xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Akusebenzi, hlola uhlelo lokusebenza"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Iphutha, iyazama futhi…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ayitholakali"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 1f6a94d..2cf3058 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -187,7 +187,6 @@
<!-- UDFPS colors -->
<color name="udfps_enroll_icon">#000000</color> <!-- 100% black -->
<color name="udfps_moving_target_fill">#cc4285f4</color> <!-- 80% blue -->
- <color name="udfps_moving_target_stroke">#ff669DF6</color> <!-- 100% blue -->
<color name="udfps_enroll_progress">#ff669DF6</color> <!-- 100% blue -->
<!-- Logout button -->
@@ -282,4 +281,6 @@
<!-- Wallet screen -->
<color name="wallet_card_border">#33FFFFFF</color>
+
+ <color name="people_tile_background">@android:color/system_accent2_50</color>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1a00503..b4deaa0 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -99,7 +99,7 @@
<!-- The default tiles to display in QuickSettings -->
<string name="quick_settings_tiles_default" translatable="false">
- internet,wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast,screenrecord
+ internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle
</string>
<!-- The minimum number of tiles to display in QuickSettings -->
@@ -107,7 +107,7 @@
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
- internet,wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness,cameratoggle,mictoggle,controls,alarm,wallet
+ internet,wifi,cell,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness
</string>
<!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 05f2f67..76a4c5f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -771,6 +771,9 @@
<!-- Move distance for the unlock hint animation on the lockscreen -->
<dimen name="hint_move_distance">75dp</dimen>
+ <!-- The overshoot amount when the panel flings open -->
+ <dimen name="panel_overshoot_amount">16dp</dimen>
+
<!-- The width of the region on the left/right edge of the screen for performing the camera/
phone hints. -->
<dimen name="edge_tap_area_width">48dp</dimen>
@@ -892,6 +895,10 @@
<!-- The width/height of the keyguard bottom area icon view on keyguard. -->
<dimen name="keyguard_affordance_height">48dp</dimen>
<dimen name="keyguard_affordance_width">48dp</dimen>
+
+ <dimen name="keyguard_affordance_wallet_height">48dp</dimen>
+ <dimen name="keyguard_affordance_wallet_width">48dp</dimen>
+
<dimen name="keyguard_affordance_horizontal_offset">32dp</dimen>
<dimen name="keyguard_affordance_vertical_offset">32dp</dimen>
<!-- Value should be at least sum of 'keyguard_affordance_width' +
@@ -903,7 +910,7 @@
<dimen name="keyguard_lock_width">42dp</dimen>
<dimen name="keyguard_lock_padding">20dp</dimen>
- <dimen name="keyguard_indication_margin_bottom">40dp</dimen>
+ <dimen name="keyguard_indication_margin_bottom">32dp</dimen>
<!-- The text size for battery level -->
<dimen name="battery_level_text_size">12sp</dimen>
@@ -1229,7 +1236,7 @@
<!-- Blur radius on status bar window and power menu -->
<dimen name="min_window_blur_radius">1px</dimen>
- <dimen name="max_window_blur_radius">150px</dimen>
+ <dimen name="max_window_blur_radius">72px</dimen>
<!-- How much into a DisplayCutout's bounds we can go, on each side -->
<dimen name="display_cutout_margin_consumption">0px</dimen>
@@ -1275,7 +1282,7 @@
<dimen name="qs_media_action_spacing">4dp</dimen>
<dimen name="qs_media_action_top">8dp</dimen>
<dimen name="qs_seamless_height">24dp</dimen>
- <dimen name="qs_seamless_icon_size">16dp</dimen>
+ <dimen name="qs_seamless_icon_size">12dp</dimen>
<dimen name="qs_seamless_fallback_icon_size">@dimen/qs_seamless_icon_size</dimen>
<dimen name="qs_seamless_fallback_margin">20dp</dimen>
<dimen name="qs_footer_horizontal_margin">22dp</dimen>
@@ -1285,7 +1292,7 @@
<dimen name="qs_media_disabled_seekbar_vertical_padding">36dp</dimen>
<!-- Size of Smartspace media recommendations cards in the QSPanel carousel -->
- <dimen name="qs_aa_media_rec_album_size_collapsed">66dp</dimen>
+ <dimen name="qs_aa_media_rec_album_size_collapsed">72dp</dimen>
<dimen name="qs_aa_media_rec_album_size_expanded">80dp</dimen>
<dimen name="qs_aa_media_rec_album_margin">8dp</dimen>
<dimen name="qq_aa_media_rec_header_text_size">16sp</dimen>
@@ -1324,15 +1331,15 @@
<dimen name="control_spinner_padding_horizontal">20dp</dimen>
<dimen name="control_text_size">14sp</dimen>
<dimen name="control_icon_size">24dp</dimen>
- <dimen name="control_spacing">4dp</dimen>
+ <dimen name="control_spacing">8dp</dimen>
<dimen name="control_list_divider">1dp</dimen>
- <dimen name="control_corner_radius">12dp</dimen>
- <dimen name="control_height">106dp</dimen>
+ <dimen name="control_corner_radius">14dp</dimen>
+ <dimen name="control_height">104dp</dimen>
<dimen name="control_padding">12dp</dimen>
<dimen name="control_padding_adjustment">4dp</dimen>
<dimen name="control_status_normal">14sp</dimen>
<dimen name="control_status_expanded">18sp</dimen>
- <dimen name="control_base_item_margin">2dp</dimen>
+ <dimen name="control_base_item_margin">4dp</dimen>
<dimen name="control_status_padding">3dp</dimen>
<fraction name="controls_toggle_bg_intensity">5%</fraction>
<fraction name="controls_dimmed_alpha">40%</fraction>
@@ -1449,7 +1456,8 @@
<dimen name="max_people_avatar_size_for_large_content">64dp</dimen>
<dimen name="max_people_avatar_size">108dp</dimen>
<dimen name="name_text_size_for_small">14sp</dimen>
- <dimen name="name_text_size_for_content">12sp</dimen>
+ <dimen name="name_text_size_for_medium_content">12sp</dimen>
+ <dimen name="name_text_size_for_large_content">14sp</dimen>
<dimen name="empty_name_text_size_for_medium">12sp</dimen>
<dimen name="max_name_text_size_for_medium">14sp</dimen>
<dimen name="medium_height_for_max_name_text_size">104dp</dimen>
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index c388b1e..027f162 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -33,15 +33,11 @@
<!-- People Tile flag -->
<bool name="flag_conversations">false</bool>
- <bool name="flag_wallet">false</bool>
-
<!-- The new animations to/from lockscreen and AOD! -->
<bool name="flag_lockscreen_animations">false</bool>
<bool name="flag_pm_lite">true</bool>
- <bool name="flag_alarm_tile">false</bool>
-
<bool name="flag_charging_ripple">false</bool>
<bool name="flag_ongoing_call_status_bar_chip">true</bool>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3fe6acd..7f4e475 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2821,9 +2821,17 @@
<string name="controls_media_resume">Resume</string>
<!-- Label for button to go to media control settings screen [CHAR_LIMIT=30] -->
<string name="controls_media_settings_button">Settings</string>
+ <!-- Description for media control's playing media item, including information for the media's title, the artist, and source app [CHAR LIMIT=NONE]-->
+ <string name="controls_media_playing_item_description"><xliff:g id="song_name" example="Daily mix">%1$s</xliff:g> by <xliff:g id="artist_name" example="Various artists">%2$s</xliff:g> is playing from <xliff:g id="app_label" example="Spotify">%3$s</xliff:g></string>
<!-- Title for Smartspace recommendation card within media controls. The "Play" means the action to play a media [CHAR_LIMIT=10] -->
<string name="controls_media_smartspace_rec_title">Play</string>
+ <!-- Description for Smartspace recommendation card within media controls [CHAR_LIMIT=NONE] -->
+ <string name="controls_media_smartspace_rec_description">Open <xliff:g id="app_label" example="Spotify">%1$s</xliff:g></string>
+ <!-- Description for Smartspace recommendation's media item, including information for the media's title, the artist, and source app [CHAR LIMIT=NONE]-->
+ <string name="controls_media_smartspace_rec_item_description">Play <xliff:g id="song_name" example="Daily mix">%1$s</xliff:g> by <xliff:g id="artist_name" example="Various artists">%2$s</xliff:g> from <xliff:g id="app_label" example="Spotify">%3$s</xliff:g></string>
+ <!-- Description for Smartspace recommendation's media item which doesn't have artist info, including information for the media's title and the source app [CHAR LIMIT=NONE]-->
+ <string name="controls_media_smartspace_rec_item_no_artist_description">Play <xliff:g id="song_name" example="Daily mix">%1$s</xliff:g> from <xliff:g id="app_label" example="Spotify">%2$s</xliff:g></string>
<!-- Error message indicating that a control timed out while waiting for an update [CHAR_LIMIT=30] -->
<string name="controls_error_timeout">Inactive, check app</string>
diff --git a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml
index 795c908..5c41ad8 100644
--- a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml
+++ b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml
@@ -38,7 +38,7 @@
app:layout_constraintHorizontal_bias="0" />
<Constraint
- android:id="@+id/media_cover1"
+ android:id="@+id/media_cover1_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_collapsed"
@@ -48,13 +48,13 @@
android:layout_marginBottom="@dimen/qs_media_padding"
android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
- app:layout_constraintEnd_toStartOf="@id/media_cover2"
+ app:layout_constraintEnd_toStartOf="@id/media_cover2_container"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
android:visibility="gone" />
<Constraint
- android:id="@+id/media_cover2"
+ android:id="@+id/media_cover2_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_collapsed"
@@ -63,14 +63,14 @@
android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover1"
- app:layout_constraintEnd_toStartOf="@id/media_cover3"
+ app:layout_constraintStart_toEndOf="@id/media_cover1_container"
+ app:layout_constraintEnd_toStartOf="@id/media_cover3_container"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
android:visibility="gone" />
<Constraint
- android:id="@+id/media_cover3"
+ android:id="@+id/media_cover3_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_collapsed"
@@ -78,45 +78,45 @@
android:layout_marginBottom="@dimen/qs_media_padding"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover2"
+ app:layout_constraintStart_toEndOf="@id/media_cover2_container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
android:visibility="gone" />
<Constraint
- android:id="@+id/media_cover4"
+ android:id="@+id/media_cover4_container"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
- app:layout_constraintTop_toBottomOf="@+id/media_cover1"
+ app:layout_constraintTop_toBottomOf="@+id/media_cover1_container"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
- app:layout_constraintEnd_toStartOf="@id/media_cover5"
+ app:layout_constraintEnd_toStartOf="@id/media_cover5_container"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
android:visibility="gone" />
<Constraint
- android:id="@+id/media_cover5"
+ android:id="@+id/media_cover5_container"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
- app:layout_constraintTop_toBottomOf="@+id/media_cover2"
+ app:layout_constraintTop_toBottomOf="@+id/media_cover2_container"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@+id/media_cover4"
- app:layout_constraintEnd_toStartOf="@+id/media_cover6"
+ app:layout_constraintStart_toEndOf="@+id/media_cover4_container"
+ app:layout_constraintEnd_toStartOf="@+id/media_cover6_container"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
android:visibility="gone" />
<Constraint
- android:id="@+id/media_cover6"
+ android:id="@+id/media_cover6_container"
android:layout_width="0dp"
android:layout_height="0dp"
- app:layout_constraintTop_toBottomOf="@id/media_cover3"
+ app:layout_constraintTop_toBottomOf="@id/media_cover3_container"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover5"
+ app:layout_constraintStart_toEndOf="@id/media_cover5_container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
diff --git a/packages/SystemUI/res/xml/media_recommendation_expanded.xml b/packages/SystemUI/res/xml/media_recommendation_expanded.xml
index 3d03a9a..d8e132c 100644
--- a/packages/SystemUI/res/xml/media_recommendation_expanded.xml
+++ b/packages/SystemUI/res/xml/media_recommendation_expanded.xml
@@ -38,7 +38,7 @@
app:layout_constraintHorizontal_bias="0" />
<Constraint
- android:id="@+id/media_cover1"
+ android:id="@+id/media_cover1_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
@@ -48,7 +48,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline"
app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
- app:layout_constraintEnd_toStartOf="@id/media_cover2"
+ app:layout_constraintEnd_toStartOf="@id/media_cover2_container"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintVertical_chainStyle="packed"
@@ -56,7 +56,7 @@
android:visibility="gone" />
<Constraint
- android:id="@+id/media_cover2"
+ android:id="@+id/media_cover2_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
@@ -65,8 +65,8 @@
android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline"
- app:layout_constraintStart_toEndOf="@id/media_cover1"
- app:layout_constraintEnd_toStartOf="@id/media_cover3"
+ app:layout_constraintStart_toEndOf="@id/media_cover1_container"
+ app:layout_constraintEnd_toStartOf="@id/media_cover3_container"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintVertical_chainStyle="packed"
@@ -74,7 +74,7 @@
android:visibility="gone" />
<Constraint
- android:id="@+id/media_cover3"
+ android:id="@+id/media_cover3_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
@@ -82,7 +82,7 @@
android:layout_marginBottom="@dimen/qs_aa_media_rec_album_margin"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline"
- app:layout_constraintStart_toEndOf="@id/media_cover2"
+ app:layout_constraintStart_toEndOf="@id/media_cover2_container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
@@ -91,7 +91,7 @@
android:visibility="gone" />
<Constraint
- android:id="@+id/media_cover4"
+ android:id="@+id/media_cover4_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
@@ -101,7 +101,7 @@
app:layout_constraintTop_toBottomOf="@+id/media_horizontal_center_guideline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
- app:layout_constraintEnd_toStartOf="@id/media_cover5"
+ app:layout_constraintEnd_toStartOf="@id/media_cover5_container"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintVertical_chainStyle="packed"
@@ -109,7 +109,7 @@
android:visibility="gone" />
<Constraint
- android:id="@+id/media_cover5"
+ android:id="@+id/media_cover5_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
@@ -118,8 +118,8 @@
android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
app:layout_constraintTop_toBottomOf="@+id/media_horizontal_center_guideline"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@+id/media_cover4"
- app:layout_constraintEnd_toStartOf="@+id/media_cover6"
+ app:layout_constraintStart_toEndOf="@+id/media_cover4_container"
+ app:layout_constraintEnd_toStartOf="@+id/media_cover6_container"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintVertical_chainStyle="packed"
@@ -127,7 +127,7 @@
android:visibility="gone" />
<Constraint
- android:id="@+id/media_cover6"
+ android:id="@+id/media_cover6_container"
android:layout_width="0dp"
android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
@@ -135,7 +135,7 @@
android:layout_marginBottom="@dimen/qs_media_padding"
app:layout_constraintTop_toBottomOf="@id/media_horizontal_center_guideline"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover5"
+ app:layout_constraintStart_toEndOf="@id/media_cover5_container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
index 74aa138..998b318 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
@@ -46,12 +46,13 @@
mTmpSourceRectF.set(sourceBounds);
mTmpDestinationRectF.set(destinationBounds);
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
+ final float cornerRadius = getScaledCornerRadius(sourceBounds, destinationBounds);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top)
- .setCornerRadius(leash, mCornerRadius);
+ .setCornerRadius(leash, cornerRadius);
return new PictureInPictureSurfaceTransaction(
mTmpDestinationRectF.left, mTmpDestinationRectF.top,
- mTmpFloat9, 0 /* rotation */, mCornerRadius, sourceBounds);
+ mTmpFloat9, 0 /* rotation */, cornerRadius, sourceBounds);
}
public PictureInPictureSurfaceTransaction scale(
@@ -62,11 +63,12 @@
mTmpDestinationRectF.set(destinationBounds);
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
mTmpTransform.postRotate(degree, 0, 0);
+ final float cornerRadius = getScaledCornerRadius(sourceBounds, destinationBounds);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setPosition(leash, positionX, positionY)
- .setCornerRadius(leash, mCornerRadius);
+ .setCornerRadius(leash, cornerRadius);
return new PictureInPictureSurfaceTransaction(
- positionX, positionY, mTmpFloat9, degree, mCornerRadius, sourceBounds);
+ positionX, positionY, mTmpFloat9, degree, cornerRadius, sourceBounds);
}
public PictureInPictureSurfaceTransaction scaleAndCrop(
@@ -83,12 +85,13 @@
final float left = destinationBounds.left - insets.left * scale;
final float top = destinationBounds.top - insets.top * scale;
mTmpTransform.setScale(scale, scale);
+ final float cornerRadius = getScaledCornerRadius(mTmpDestinationRect, destinationBounds);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
.setPosition(leash, left, top)
- .setCornerRadius(leash, mCornerRadius);
+ .setCornerRadius(leash, cornerRadius);
return new PictureInPictureSurfaceTransaction(
- left, top, mTmpFloat9, 0 /* rotation */, mCornerRadius, mTmpDestinationRect);
+ left, top, mTmpFloat9, 0 /* rotation */, cornerRadius, mTmpDestinationRect);
}
public PictureInPictureSurfaceTransaction scaleAndRotate(
@@ -105,12 +108,30 @@
: (float) destinationBounds.height() / sourceBounds.height();
mTmpTransform.setRotate(degree, 0, 0);
mTmpTransform.postScale(scale, scale);
+ final float cornerRadius = getScaledCornerRadius(mTmpDestinationRect, destinationBounds);
+ // adjust the positions, take account also the insets
+ final float adjustedPositionX, adjustedPositionY;
+ if (degree < 0) {
+ adjustedPositionX = positionX + insets.top * scale;
+ adjustedPositionY = positionY + insets.left * scale;
+ } else {
+ adjustedPositionX = positionX - insets.top * scale;
+ adjustedPositionY = positionY - insets.left * scale;
+ }
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
- .setPosition(leash, positionX, positionY)
- .setCornerRadius(leash, mCornerRadius);
+ .setPosition(leash, adjustedPositionX, adjustedPositionY)
+ .setCornerRadius(leash, cornerRadius);
return new PictureInPictureSurfaceTransaction(
- positionX, positionY, mTmpFloat9, degree, mCornerRadius, mTmpDestinationRect);
+ adjustedPositionX, adjustedPositionY,
+ mTmpFloat9, degree, cornerRadius, mTmpDestinationRect);
+ }
+
+ /** @return the round corner radius scaled by given from and to bounds */
+ private float getScaledCornerRadius(Rect fromBounds, Rect toBounds) {
+ final float scale = (float) (Math.hypot(fromBounds.width(), fromBounds.height())
+ / Math.hypot(toBounds.width(), toBounds.height()));
+ return mCornerRadius * scale;
}
/** @return {@link SurfaceControl.Transaction} instance with vsync-id */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 700ec49..8e65560 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -152,4 +152,15 @@
Log.e(TAG, "Failed to detach the navigation bar from app", e);
}
}
+
+ /**
+ * @see IRecentsAnimationController#animateNavigationBarToApp(long)
+ */
+ public void animateNavigationBarToApp(long duration) {
+ try {
+ mAnimationController.animateNavigationBarToApp(duration);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to animate the navigation bar to app", e);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index 92af58e..08076c1 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -127,8 +127,10 @@
@Override
public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
boolean isStrongBiometric) {
+ // Strong auth will force the bouncer regardless of a successful face auth
if (biometricSourceType == BiometricSourceType.FACE
- && mBypassController.canBypass()) {
+ && mBypassController.canBypass()
+ && !mKeyguardUpdateMonitor.userNeedsStrongAuth()) {
mView.animateDisappear();
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 619bf1b..ef052c4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -64,9 +64,10 @@
private float mDarkAmount;
/**
- * Boolean value indicating if notifications are visible on lock screen.
+ * Boolean value indicating if notifications are visible on lock screen. Use null to signify
+ * it is uninitialized.
*/
- private boolean mHasVisibleNotifications = true;
+ private Boolean mHasVisibleNotifications = null;
private AnimatorSet mClockInAnim = null;
private AnimatorSet mClockOutAnim = null;
@@ -263,7 +264,8 @@
* the smaller version.
*/
boolean willSwitchToLargeClock(boolean hasVisibleNotifications) {
- if (hasVisibleNotifications == mHasVisibleNotifications) {
+ if (mHasVisibleNotifications != null
+ && hasVisibleNotifications == mHasVisibleNotifications) {
return false;
}
boolean useLargeClock = !hasVisibleNotifications;
@@ -286,20 +288,6 @@
}
/**
- * Returns the preferred Y position of the clock.
- *
- * @param totalHeight Height of the parent container.
- * @return preferred Y position.
- */
- int getPreferredY(int totalHeight) {
- if (mClockPlugin != null) {
- return mClockPlugin.getPreferredY(totalHeight);
- } else {
- return totalHeight / 2;
- }
- }
-
- /**
* Refresh the time of the clock, due to either time tick broadcast or doze time tick alarm.
*/
public void refresh() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index a7239ca..ef6212d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -257,16 +257,6 @@
}
/**
- * Returns the preferred Y position of the clock.
- *
- * @param totalHeight The height available to position the clock.
- * @return Y position of clock.
- */
- public int getClockPreferredY(int totalHeight) {
- return mView.getPreferredY(totalHeight);
- }
-
- /**
* Refresh clock. Called in response to TIME_TICK broadcasts.
*/
void refresh() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 96eda3d..2362a1a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -20,17 +20,10 @@
import android.app.IActivityManager;
import android.content.Context;
import android.graphics.Color;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridLayout;
-import android.widget.TextView;
import androidx.core.graphics.ColorUtils;
@@ -45,26 +38,18 @@
/**
* View consisting of:
* - keyguard clock
- * - logout button (on certain managed devices)
- * - owner information (if set)
* - media player (split shade mode only)
*/
public class KeyguardStatusView extends GridLayout {
private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final String TAG = "KeyguardStatusView";
- private static final int MARQUEE_DELAY_MS = 2000;
private final LockPatternUtils mLockPatternUtils;
private final IActivityManager mIActivityManager;
private ViewGroup mStatusViewContainer;
- private TextView mLogoutView;
private KeyguardClockSwitch mClockView;
- private TextView mOwnerInfo;
- private boolean mCanShowOwnerInfo = true; // by default, try to show the owner information here
private KeyguardSliceView mKeyguardSlice;
- private Runnable mPendingMarqueeStart;
- private Handler mHandler;
private View mMediaHostContainer;
private float mDarkAmount = 0;
@@ -91,64 +76,17 @@
super(context, attrs, defStyle);
mIActivityManager = ActivityManager.getService();
mLockPatternUtils = new LockPatternUtils(getContext());
- mHandler = new Handler();
- onDensityOrFontScaleChanged();
- }
-
- void setEnableMarquee(boolean enabled) {
- if (DEBUG) Log.v(TAG, "Schedule setEnableMarquee: " + (enabled ? "Enable" : "Disable"));
- if (enabled) {
- if (mPendingMarqueeStart == null) {
- mPendingMarqueeStart = () -> {
- setEnableMarqueeImpl(true);
- mPendingMarqueeStart = null;
- };
- mHandler.postDelayed(mPendingMarqueeStart, MARQUEE_DELAY_MS);
- }
- } else {
- if (mPendingMarqueeStart != null) {
- mHandler.removeCallbacks(mPendingMarqueeStart);
- mPendingMarqueeStart = null;
- }
- setEnableMarqueeImpl(false);
- }
- }
-
- private void setEnableMarqueeImpl(boolean enabled) {
- if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee");
- if (mOwnerInfo != null) mOwnerInfo.setSelected(enabled);
- }
-
- void setCanShowOwnerInfo(boolean canShowOwnerInfo) {
- mCanShowOwnerInfo = canShowOwnerInfo;
- mOwnerInfo = findViewById(R.id.owner_info);
- if (mOwnerInfo != null) {
- if (mCanShowOwnerInfo) {
- mOwnerInfo.setVisibility(VISIBLE);
- updateOwnerInfo();
- } else {
- mOwnerInfo.setVisibility(GONE);
- mOwnerInfo = null;
- }
- }
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mStatusViewContainer = findViewById(R.id.status_view_container);
- mLogoutView = findViewById(R.id.logout);
- if (mLogoutView != null) {
- mLogoutView.setOnClickListener(this::onLogoutClicked);
- }
mClockView = findViewById(R.id.keyguard_clock_container);
if (KeyguardClockAccessibilityDelegate.isNeeded(mContext)) {
mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
}
- if (mCanShowOwnerInfo) {
- mOwnerInfo = findViewById(R.id.owner_info);
- }
mKeyguardSlice = findViewById(R.id.keyguard_status_area);
mTextColor = mClockView.getCurrentTextColor();
@@ -158,7 +96,6 @@
mMediaHostContainer = findViewById(R.id.status_view_media_container);
- updateOwnerInfo();
updateDark();
}
@@ -173,60 +110,6 @@
mShowingHeader = hasHeader;
}
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- layoutOwnerInfo();
- }
-
- int getLogoutButtonHeight() {
- if (mLogoutView == null) {
- return 0;
- }
- return mLogoutView.getVisibility() == VISIBLE ? mLogoutView.getHeight() : 0;
- }
-
- int getOwnerInfoHeight() {
- if (mOwnerInfo == null) {
- return 0;
- }
- return mOwnerInfo.getVisibility() == VISIBLE ? mOwnerInfo.getHeight() : 0;
- }
-
- void updateLogoutView(boolean shouldShowLogout) {
- if (mLogoutView == null) {
- return;
- }
- mLogoutView.setVisibility(shouldShowLogout ? VISIBLE : GONE);
- // Logout button will stay in language of user 0 if we don't set that manually.
- mLogoutView.setText(mContext.getResources().getString(
- com.android.internal.R.string.global_action_logout));
- }
-
- void onDensityOrFontScaleChanged() {
- if (mOwnerInfo != null) {
- mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- getResources().getDimensionPixelSize(
- com.android.systemui.R.dimen.widget_label_font_size));
- loadBottomMargin();
- }
- }
-
- void updateOwnerInfo() {
- if (mOwnerInfo == null) return;
- String info = mLockPatternUtils.getDeviceOwnerInfo();
- if (info == null) {
- // Use the current user owner information if enabled.
- final boolean ownerInfoEnabled = mLockPatternUtils.isOwnerInfoEnabled(
- KeyguardUpdateMonitor.getCurrentUser());
- if (ownerInfoEnabled) {
- info = mLockPatternUtils.getOwnerInfo(KeyguardUpdateMonitor.getCurrentUser());
- }
- }
- mOwnerInfo.setText(info);
- updateDark();
- }
-
void setDarkAmount(float darkAmount) {
if (mDarkAmount == darkAmount) {
return;
@@ -238,17 +121,6 @@
}
void updateDark() {
- boolean dark = mDarkAmount == 1;
- if (mLogoutView != null) {
- mLogoutView.setAlpha(dark ? 0 : 1);
- }
-
- if (mOwnerInfo != null) {
- boolean hasText = !TextUtils.isEmpty(mOwnerInfo.getText());
- mOwnerInfo.setVisibility(hasText ? VISIBLE : GONE);
- layoutOwnerInfo();
- }
-
final int blendedTextColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
mKeyguardSlice.setDarkAmount(mDarkAmount);
mClockView.setTextColor(blendedTextColor);
@@ -277,13 +149,8 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("KeyguardStatusView:");
- pw.println(" mOwnerInfo: " + (mOwnerInfo == null
- ? "null" : mOwnerInfo.getVisibility() == VISIBLE));
pw.println(" mDarkAmount: " + mDarkAmount);
pw.println(" mTextColor: " + Integer.toHexString(mTextColor));
- if (mLogoutView != null) {
- pw.println(" logout visible: " + (mLogoutView.getVisibility() == VISIBLE));
- }
if (mClockView != null) {
mClockView.dump(fd, pw, args);
}
@@ -297,28 +164,4 @@
mIconTopMarginWithHeader = getResources().getDimensionPixelSize(
R.dimen.widget_vertical_padding_with_header);
}
-
- private void layoutOwnerInfo() {
- if (mOwnerInfo != null && mOwnerInfo.getVisibility() != GONE) {
- // Animate owner info during wake-up transition
- mOwnerInfo.setAlpha(1f - mDarkAmount);
-
- float ratio = mDarkAmount;
- // Calculate how much of it we should crop in order to have a smooth transition
- int collapsed = mOwnerInfo.getTop() - mOwnerInfo.getPaddingTop();
- int expanded = mOwnerInfo.getBottom() + mOwnerInfo.getPaddingBottom();
- int toRemove = (int) ((expanded - collapsed) * ratio);
- setBottom(getMeasuredHeight() - toRemove);
- }
- }
-
- private void onLogoutClicked(View view) {
- int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
- try {
- mIActivityManager.switchUser(UserHandle.USER_SYSTEM);
- mIActivityManager.stopUser(currentUserId, true /*force*/, null);
- } catch (RemoteException re) {
- Log.e(TAG, "Failed to logout user", re);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index e4cabcb..123c0e6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -17,7 +17,6 @@
package com.android.keyguard;
import android.graphics.Rect;
-import android.os.UserHandle;
import android.util.Slog;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
@@ -77,7 +76,7 @@
mDozeParameters = dozeParameters;
mKeyguardStateController = keyguardStateController;
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController,
- dozeParameters, unlockedScreenOffAnimationController);
+ dozeParameters, unlockedScreenOffAnimationController, /* animateYPos= */ true);
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mSmartspaceTransitionController = smartspaceTransitionController;
@@ -97,8 +96,6 @@
@Override
public void onInit() {
mKeyguardClockSwitchController.init();
- mView.setEnableMarquee(mKeyguardUpdateMonitor.isDeviceInteractive());
- mView.updateLogoutView(shouldShowLogout());
}
@Override
@@ -143,20 +140,6 @@
}
/**
- * Get the height of the logout button.
- */
- public int getLogoutButtonHeight() {
- return mView.getLogoutButtonHeight();
- }
-
- /**
- * Get the height of the owner information view.
- */
- public int getOwnerInfoHeight() {
- return mView.getOwnerInfoHeight();
- }
-
- /**
* Set keyguard status view alpha.
*/
public void setAlpha(float alpha) {
@@ -204,16 +187,6 @@
}
/**
- * Returns the preferred Y position of the clock.
- *
- * @param totalHeight The height available to position the clock.
- * @return Y position of clock.
- */
- public int getClockPreferredY(int totalHeight) {
- return mKeyguardClockSwitchController.getClockPreferredY(totalHeight);
- }
-
- /**
* Get the height of the keyguard status view.
*/
public int getHeight() {
@@ -254,11 +227,6 @@
mKeyguardClockSwitchController.refresh();
}
- private boolean shouldShowLogout() {
- return mKeyguardUpdateMonitor.isLogoutEnabled()
- && KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM;
- }
-
private final ConfigurationController.ConfigurationListener mConfigurationListener =
new ConfigurationController.ConfigurationListener() {
@Override
@@ -269,7 +237,6 @@
@Override
public void onDensityOrFontScaleChanged() {
mKeyguardClockSwitchController.onDensityOrFontScaleChanged();
- mView.onDensityOrFontScaleChanged();
}
};
@@ -277,8 +244,6 @@
@Override
public void onLockScreenModeChanged(int mode) {
mKeyguardSliceViewController.updateLockScreenMode(mode);
- mView.setCanShowOwnerInfo(false);
- mView.updateLogoutView(false);
}
@Override
@@ -301,31 +266,12 @@
if (showing) {
if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
refreshTime();
- mView.updateOwnerInfo();
- mView.updateLogoutView(shouldShowLogout());
}
}
@Override
- public void onStartedWakingUp() {
- mView.setEnableMarquee(true);
- }
-
- @Override
- public void onFinishedGoingToSleep(int why) {
- mView.setEnableMarquee(false);
- }
-
- @Override
public void onUserSwitchComplete(int userId) {
mKeyguardClockSwitchController.refreshFormat();
- mView.updateOwnerInfo();
- mView.updateLogoutView(shouldShowLogout());
- }
-
- @Override
- public void onLogoutEnabledChanged() {
- mView.updateLogoutView(shouldShowLogout());
}
};
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index 7edecc8..28a54d5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -19,6 +19,7 @@
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import android.view.View;
+import android.view.ViewPropertyAnimator;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.StatusBarState;
@@ -40,6 +41,7 @@
private final KeyguardStateController mKeyguardStateController;
private final DozeParameters mDozeParameters;
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+ private boolean mAnimateYPos;
private boolean mKeyguardViewVisibilityAnimating;
private boolean mLastOccludedState = false;
private final AnimationProperties mAnimationProperties = new AnimationProperties();
@@ -47,11 +49,13 @@
public KeyguardVisibilityHelper(View view,
KeyguardStateController keyguardStateController,
DozeParameters dozeParameters,
- UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
+ UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
+ boolean animateYPos) {
mView = view;
mKeyguardStateController = keyguardStateController;
mDozeParameters = dozeParameters;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+ mAnimateYPos = animateYPos;
}
public boolean isVisibilityAnimating() {
@@ -98,23 +102,25 @@
} else if (statusBarState == KEYGUARD) {
if (keyguardFadingAway) {
mKeyguardViewVisibilityAnimating = true;
- float target = mView.getY() - mView.getHeight() * 0.05f;
- int delay = 0;
- int duration = 125;
- // We animate the Y properly separately using the PropertyAnimator, as the panel
- // view als needs to update the end position.
- mAnimationProperties.setDuration(duration).setDelay(delay);
- PropertyAnimator.cancelAnimation(mView, AnimatableProperty.Y);
- PropertyAnimator.setProperty(mView, AnimatableProperty.Y, target,
- mAnimationProperties,
- true /* animate */);
- mView.animate()
+ ViewPropertyAnimator animator = mView.animate()
.alpha(0)
.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
- .setDuration(duration)
- .setStartDelay(delay)
- .withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable)
- .start();
+ .withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable);
+ if (mAnimateYPos) {
+ float target = mView.getY() - mView.getHeight() * 0.05f;
+ int delay = 0;
+ int duration = 125;
+ // We animate the Y property separately using the PropertyAnimator, as the panel
+ // view also needs to update the end position.
+ mAnimationProperties.setDuration(duration).setDelay(delay);
+ PropertyAnimator.cancelAnimation(mView, AnimatableProperty.Y);
+ PropertyAnimator.setProperty(mView, AnimatableProperty.Y, target,
+ mAnimationProperties,
+ true /* animate */);
+ animator.setDuration(duration)
+ .setStartDelay(delay);
+ }
+ animator.start();
} else if (mLastOccludedState && !isOccluded) {
// An activity was displayed over the lock screen, and has now gone away
mView.setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt b/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt
index cdb39ef..5e874ae 100644
--- a/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt
+++ b/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt
@@ -21,7 +21,9 @@
import android.animation.TimeInterpolator
import android.animation.ValueAnimator
import android.graphics.Canvas
+import android.graphics.Typeface
import android.text.Layout
+import android.util.SparseArray
private const val TAG_WGHT = "wght"
private const val DEFAULT_ANIMATION_DURATION: Long = 300
@@ -72,6 +74,8 @@
})
}
+ private val typefaceCache = SparseArray<Typeface?>()
+
fun updateLayout(layout: Layout) {
textInterpolator.layout = layout
}
@@ -120,7 +124,12 @@
textInterpolator.targetPaint.textSize = textSize
}
if (weight >= 0) {
- textInterpolator.targetPaint.fontVariationSettings = "'$TAG_WGHT' $weight"
+ // Paint#setFontVariationSettings creates Typeface instance from scratch. To reduce the
+ // memory impact, cache the typeface result.
+ textInterpolator.targetPaint.typeface = typefaceCache.getOrElse(weight) {
+ textInterpolator.targetPaint.fontVariationSettings = "'$TAG_WGHT' $weight"
+ textInterpolator.targetPaint.typeface
+ }
}
if (color != null) {
textInterpolator.targetPaint.color = color
@@ -155,3 +164,12 @@
}
}
}
+
+private fun <V> SparseArray<V>.getOrElse(key: Int, defaultValue: () -> V): V {
+ var v = get(key)
+ if (v == null) {
+ v = defaultValue()
+ put(key, v)
+ }
+ return v
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index 9c5a40c..186917f 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -46,6 +46,9 @@
ACTION_FINGERPRINT_WAKE =
"com.android.systemui.latency.ACTION_FINGERPRINT_WAKE";
private static final String
+ ACTION_FACE_WAKE =
+ "com.android.systemui.latency.ACTION_FACE_WAKE";
+ private static final String
ACTION_TURN_ON_SCREEN =
"com.android.systemui.latency.ACTION_TURN_ON_SCREEN";
private final BiometricUnlockController mBiometricUnlockController;
@@ -70,13 +73,16 @@
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_FINGERPRINT_WAKE);
+ filter.addAction(ACTION_FACE_WAKE);
filter.addAction(ACTION_TURN_ON_SCREEN);
mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_FINGERPRINT_WAKE.equals(action)) {
- fakeWakeAndUnlock();
+ fakeWakeAndUnlock(BiometricSourceType.FINGERPRINT);
+ } else if (ACTION_FACE_WAKE.equals(action)) {
+ fakeWakeAndUnlock(BiometricSourceType.FACE);
} else if (ACTION_TURN_ON_SCREEN.equals(action)) {
fakeTurnOnScreen();
}
@@ -93,10 +99,9 @@
SystemClock.uptimeMillis(), WAKE_REASON_UNKNOWN, "android.policy:LATENCY_TESTS");
}
- private void fakeWakeAndUnlock() {
- mBiometricUnlockController.onBiometricAcquired(BiometricSourceType.FINGERPRINT);
+ private void fakeWakeAndUnlock(BiometricSourceType type) {
+ mBiometricUnlockController.onBiometricAcquired(type);
mBiometricUnlockController.onBiometricAuthenticated(
- KeyguardUpdateMonitor.getCurrentUser(), BiometricSourceType.FINGERPRINT,
- true /* isStrongBiometric */);
+ KeyguardUpdateMonitor.getCurrentUser(), type, true /* isStrongBiometric */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index fcb090a..717c715 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -66,6 +66,7 @@
import java.io.PrintWriter;
import java.text.NumberFormat;
+import java.util.Collections;
import java.util.Locale;
/**
@@ -178,7 +179,13 @@
// Initialize listeners.
mMirrorViewRunnable = () -> {
if (mMirrorView != null) {
+ final Rect oldViewBounds = new Rect(mMirrorViewBounds);
mMirrorView.getBoundsOnScreen(mMirrorViewBounds);
+ if (oldViewBounds.width() != mMirrorViewBounds.width()
+ || oldViewBounds.height() != mMirrorViewBounds.height()) {
+ mMirrorView.setSystemGestureExclusionRects(Collections.singletonList(
+ new Rect(0, 0, mMirrorViewBounds.width(), mMirrorViewBounds.height())));
+ }
updateSystemUIStateIfNeeded();
mWindowMagnifierCallback.onWindowMagnifierBoundsChanged(
mDisplayId, mMirrorViewBounds);
@@ -269,6 +276,7 @@
if (mMirrorWindowControl != null) {
mMirrorWindowControl.destroyControl();
}
+ mMirrorViewBounds.setEmpty();
updateSystemUIStateIfNeeded();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
index ca59393..76fb49a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
@@ -130,19 +130,29 @@
@Override
public void onAuthenticationFailed(
@Modality int modality, @Nullable String failureReason) {
- if (modality == TYPE_FACE && mActiveSensorType == TYPE_FACE) {
- // switching from face -> fingerprint mode, suppress soft error messages
- failureReason = mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead);
+ super.onAuthenticationFailed(modality, checkErrorForFallback(failureReason));
+ }
+
+ @Override
+ public void onError(int modality, String error) {
+ super.onError(modality, checkErrorForFallback(error));
+ }
+
+ private String checkErrorForFallback(String message) {
+ if (mActiveSensorType == TYPE_FACE) {
+ Log.d(TAG, "Falling back to fingerprint: " + message);
+
+ // switching from face -> fingerprint mode, suppress root error messages
+ mCallback.onAction(Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR);
+ return mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead);
}
- super.onAuthenticationFailed(modality, failureReason);
+ return message;
}
@Override
@BiometricState
protected int getStateForAfterError() {
if (mActiveSensorType == TYPE_FACE) {
- mHandler.post(() -> mCallback.onAction(
- Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
return STATE_AUTHENTICATING;
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index d1cb6ec..c4f78e7 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -376,6 +376,17 @@
addView(mFrameLayout);
+ // init view before showing
+ if (mBiometricView != null) {
+ mBiometricView.setRequireConfirmation(mConfig.mRequireConfirmation);
+ mBiometricView.setPanelController(mPanelController);
+ mBiometricView.setPromptInfo(mConfig.mPromptInfo);
+ mBiometricView.setCallback(mBiometricCallback);
+ mBiometricView.setBackgroundView(mBackgroundView);
+ mBiometricView.setUserId(mConfig.mUserId);
+ mBiometricView.setEffectiveUserId(mEffectiveUserId);
+ }
+
// TODO: De-dupe the logic with AuthCredentialPasswordView
setOnKeyListener((v, keyCode, event) -> {
if (keyCode != KeyEvent.KEYCODE_BACK) {
@@ -404,13 +415,6 @@
}
private void addBiometricView() {
- mBiometricView.setRequireConfirmation(mConfig.mRequireConfirmation);
- mBiometricView.setPanelController(mPanelController);
- mBiometricView.setPromptInfo(mConfig.mPromptInfo);
- mBiometricView.setCallback(mBiometricCallback);
- mBiometricView.setBackgroundView(mBackgroundView);
- mBiometricView.setUserId(mConfig.mUserId);
- mBiometricView.setEffectiveUserId(mEffectiveUserId);
mBiometricScrollView.addView(mBiometricView);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 01fbe39..75373ab 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -110,7 +110,8 @@
visibility = GONE
}
})
- vibrate()
+ // TODO (b/185124905): custom haptic TBD
+ // vibrate()
animatorSet.start()
visibility = VISIBLE
rippleInProgress = true
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index cef3e7d..f975a80 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -211,6 +211,12 @@
}
}
+ void onAcquiredGood() {
+ if (mEnrollHelper != null) {
+ mEnrollHelper.animateIfLastStep();
+ }
+ }
+
void onEnrollmentHelp() {
if (mEnrollHelper != null) {
mEnrollHelper.onEnrollmentHelp();
@@ -260,6 +266,11 @@
}
mGoodCaptureReceived = true;
mView.stopIllumination();
+ if (mServerRequest != null) {
+ mServerRequest.onAcquiredGood();
+ } else {
+ Log.e(TAG, "Null serverRequest when onAcquiredGood");
+ }
});
}
@@ -394,9 +405,8 @@
? event.getPointerId(0)
: event.findPointerIndex(mActivePointerId);
if (idx == event.getActionIndex()) {
- final float x = event.getX(idx);
- final float y = event.getY(idx);
- if (isWithinSensorArea(udfpsView, x, y, fromUdfpsView)) {
+ if (isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx),
+ fromUdfpsView)) {
if (mVelocityTracker == null) {
// touches could be injected, so the velocity tracker may not have
// been initialized (via ACTION_DOWN).
@@ -416,7 +426,8 @@
final long sinceLastLog = SystemClock.elapsedRealtime() - mTouchLogTime;
if (!isIlluminationRequested && !mGoodCaptureReceived &&
!exceedsVelocityThreshold) {
- onFingerDown((int) x, (int) y, minor, major);
+ onFingerDown((int) event.getRawX(), (int) event.getRawY(), minor,
+ major);
Log.v(TAG, "onTouch | finger down: " + touchInfo);
mTouchLogTime = SystemClock.elapsedRealtime();
mPowerManager.userActivity(SystemClock.uptimeMillis(),
@@ -658,8 +669,7 @@
// during a11y.
if (reason == IUdfpsOverlayController.REASON_ENROLL_FIND_SENSOR
|| reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING) {
- mView.setImportantForAccessibility(
- View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+ mView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
mWindowManager.addView(mView, computeLayoutParams(animation));
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java
index 6b6e0f1..ea69b1d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java
@@ -47,7 +47,6 @@
@NonNull private final Drawable mMovingTargetFpIcon;
@NonNull private final Paint mSensorOutlinePaint;
@NonNull private final Paint mBlueFill;
- @NonNull private final Paint mBlueStroke;
@Nullable private RectF mSensorRect;
@Nullable private UdfpsEnrollHelper mEnrollHelper;
@@ -76,12 +75,6 @@
mBlueFill.setColor(context.getColor(R.color.udfps_moving_target_fill));
mBlueFill.setStyle(Paint.Style.FILL);
- mBlueStroke = new Paint(0 /* flags */);
- mBlueStroke.setAntiAlias(true);
- mBlueStroke.setColor(context.getColor(R.color.udfps_moving_target_stroke));
- mBlueStroke.setStyle(Paint.Style.STROKE);
- mBlueStroke.setStrokeWidth(12);
-
mMovingTargetFpIcon = context.getResources().getDrawable(R.drawable.ic_fingerprint, null);
mMovingTargetFpIcon.setTint(Color.WHITE);
mMovingTargetFpIcon.mutate();
@@ -146,6 +139,10 @@
}
}
+ void onLastStepAcquired() {
+ mProgressDrawable.onLastStepAcquired();
+ }
+
@Override
public void draw(@NonNull Canvas canvas) {
mProgressDrawable.draw(canvas);
@@ -163,7 +160,6 @@
canvas.scale(mCurrentScale, mCurrentScale,
mSensorRect.centerX(), mSensorRect.centerY());
canvas.drawOval(mSensorRect, mBlueFill);
- canvas.drawOval(mSensorRect, mBlueStroke);
}
mMovingTargetFpIcon.draw(canvas);
@@ -188,7 +184,6 @@
super.setAlpha(alpha);
mSensorOutlinePaint.setAlpha(alpha);
mBlueFill.setAlpha(alpha);
- mBlueStroke.setAlpha(alpha);
mMovingTargetFpIcon.setAlpha(alpha);
invalidateSelf();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
index 470fb8c..412b776 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
@@ -21,8 +21,11 @@
import android.content.Context;
import android.graphics.PointF;
import android.hardware.fingerprint.IUdfpsOverlayController;
+import android.media.AudioAttributes;
import android.os.Build;
import android.os.UserHandle;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.provider.Settings;
import android.util.Log;
import android.util.TypedValue;
@@ -47,8 +50,15 @@
// Enroll with two center touches before going to guided enrollment
private static final int NUM_CENTER_TOUCHES = 2;
+ private static final AudioAttributes VIBRATION_SONFICATION_ATTRIBUTES =
+ new AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ .build();
+
interface Listener {
void onEnrollmentProgress(int remaining, int totalSteps);
+ void onLastStepAcquired();
}
@NonNull private final Context mContext;
@@ -56,6 +66,9 @@
private final int mEnrollReason;
private final boolean mAccessibilityEnabled;
@NonNull private final List<PointF> mGuidedEnrollmentPoints;
+ @NonNull private final Vibrator mVibrator;
+ @NonNull private final VibrationEffect mEffectClick =
+ VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
private int mTotalSteps = -1;
private int mRemainingSteps = -1;
@@ -69,6 +82,7 @@
public UdfpsEnrollHelper(@NonNull Context context, int reason) {
mContext = context;
mEnrollReason = reason;
+ mVibrator = context.getSystemService(Vibrator.class);
final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
mAccessibilityEnabled = am.isEnabled();
@@ -127,6 +141,7 @@
if (remaining != mRemainingSteps) {
mLocationsEnrolled++;
+ vibrateSuccess();
}
mRemainingSteps = remaining;
@@ -178,4 +193,20 @@
.get(index % mGuidedEnrollmentPoints.size());
return new PointF(originalPoint.x * scale, originalPoint.y * scale);
}
+
+ void animateIfLastStep() {
+ if (mListener == null) {
+ Log.e(TAG, "animateIfLastStep, null listener");
+ return;
+ }
+
+ if (mRemainingSteps <= 2 && mRemainingSteps >= 0) {
+ mListener.onLastStepAcquired();
+ vibrateSuccess();
+ }
+ }
+
+ private void vibrateSuccess() {
+ mVibrator.vibrate(mEffectClick, VIBRATION_SONFICATION_ATTRIBUTES);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
index 5c9e52f..4195009 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
@@ -23,6 +23,7 @@
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
+import android.util.Log;
import android.util.TypedValue;
import androidx.annotation.NonNull;
@@ -46,6 +47,8 @@
@Nullable private ValueAnimator mProgressAnimator;
private float mProgress;
+ private int mRotation; // After last step, rotate the progress bar once
+ private boolean mLastStepAcquired;
public UdfpsEnrollProgressBarDrawable(@NonNull Context context,
@NonNull UdfpsEnrollDrawable parent) {
@@ -81,13 +84,34 @@
// Add one so that the first steps actually changes progress, but also so that the last
// step ends at 1.0
final float progress = (totalSteps - remaining + 1) / (float) (totalSteps + 1);
+ setEnrollmentProgress(progress);
+ }
+
+ private void setEnrollmentProgress(float progress) {
+ if (mLastStepAcquired) {
+ return;
+ }
+
+ long animationDuration = 150;
+
+ if (progress == 1.f) {
+ animationDuration = 400;
+ final ValueAnimator rotationAnimator = ValueAnimator.ofInt(0, 400);
+ rotationAnimator.setDuration(animationDuration);
+ rotationAnimator.addUpdateListener(animation -> {
+ Log.d(TAG, "Rotation: " + mRotation);
+ mRotation = (int) animation.getAnimatedValue();
+ mParent.invalidateSelf();
+ });
+ rotationAnimator.start();
+ }
if (mProgressAnimator != null && mProgressAnimator.isRunning()) {
mProgressAnimator.cancel();
}
mProgressAnimator = ValueAnimator.ofFloat(mProgress, progress);
- mProgressAnimator.setDuration(150);
+ mProgressAnimator.setDuration(animationDuration);
mProgressAnimator.addUpdateListener(animation -> {
mProgress = (float) animation.getAnimatedValue();
// Use the parent to invalidate, since it's the one that's attached as the view's
@@ -99,12 +123,17 @@
mProgressAnimator.start();
}
+ void onLastStepAcquired() {
+ setEnrollmentProgress(1.f);
+ mLastStepAcquired = true;
+ }
+
@Override
public void draw(@NonNull Canvas canvas) {
canvas.save();
// Progress starts from the top, instead of the right
- canvas.rotate(-90, getBounds().centerX(), getBounds().centerY());
+ canvas.rotate(-90 + mRotation, getBounds().centerX(), getBounds().centerY());
// Progress bar "background track"
final float halfPaddingPx = Utils.dpToPixels(mContext, PROGRESS_BAR_THICKNESS_DP) / 2;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
index 3b30220..7f4d7fe0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
@@ -63,8 +63,10 @@
}
void onEnrollmentProgress(int remaining, int totalSteps) {
- mHandler.post(() -> {
- mFingerprintDrawable.onEnrollmentProgress(remaining, totalSteps);
- });
+ mHandler.post(() -> mFingerprintDrawable.onEnrollmentProgress(remaining, totalSteps));
+ }
+
+ void onLastStepAcquired() {
+ mHandler.post(mFingerprintDrawable::onLastStepAcquired);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
index 953448d..91cc149 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
@@ -32,7 +32,17 @@
private final int mEnrollProgressBarRadius;
@NonNull private final UdfpsEnrollHelper mEnrollHelper;
@NonNull private final UdfpsEnrollHelper.Listener mEnrollHelperListener =
- mView::onEnrollmentProgress;
+ new UdfpsEnrollHelper.Listener() {
+ @Override
+ public void onEnrollmentProgress(int remaining, int totalSteps) {
+ mView.onEnrollmentProgress(remaining, totalSteps);
+ }
+
+ @Override
+ public void onLastStepAcquired() {
+ mView.onLastStepAcquired();
+ }
+ };
protected UdfpsEnrollViewController(
@NonNull UdfpsEnrollView view,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 9a32412..00888df 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -62,7 +62,6 @@
private boolean mQsExpanded;
private boolean mFaceDetectRunning;
private boolean mHintShown;
- private boolean mTransitioningFromHome;
private int mStatusBarState;
/**
@@ -112,11 +111,11 @@
mStatusBarState = mStatusBarStateController.getState();
mQsExpanded = mKeyguardViewManager.isQsExpanded();
mInputBouncerHiddenAmount = KeyguardBouncer.EXPANSION_HIDDEN;
+ mIsBouncerVisible = mKeyguardViewManager.bouncerIsOrWillBeShowing();
updateAlpha();
updatePauseAuth();
mKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
- mIsBouncerVisible = mKeyguardViewManager.bouncerIsOrWillBeShowing();
}
@Override
@@ -127,7 +126,6 @@
mStatusBarStateController.removeCallback(mStateListener);
mKeyguardViewManager.removeAlternateAuthInterceptor(mAlternateAuthInterceptor);
- mTransitioningFromHome = false;
mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(false);
if (mCancelDelayedHintRunnable != null) {
@@ -141,7 +139,6 @@
super.dump(fd, pw, args);
pw.println("mShowingUdfpsBouncer=" + mShowingUdfpsBouncer);
pw.println("mFaceDetectRunning=" + mFaceDetectRunning);
- pw.println("mTransitioningFromHomeToKeyguard=" + mTransitioningFromHome);
pw.println("mStatusBarState=" + StatusBarState.toShortString(mStatusBarState));
pw.println("mQsExpanded=" + mQsExpanded);
pw.println("mIsBouncerVisible=" + mIsBouncerVisible);
@@ -195,10 +192,6 @@
return true;
}
- if (mTransitioningFromHome && mKeyguardViewMediator.isAnimatingScreenOff()) {
- return true;
- }
-
if (mQsExpanded) {
return true;
}
@@ -277,17 +270,6 @@
public void onDozeAmountChanged(float linear, float eased) {
if (linear != 0) showUdfpsBouncer(false);
mView.onDozeAmountChanged(linear, eased);
- if (linear == 1f) {
- // transition has finished
- mTransitioningFromHome = false;
- }
- updatePauseAuth();
- }
-
- @Override
- public void onStatePreChange(int oldState, int newState) {
- mTransitioningFromHome = oldState == StatusBarState.SHADE
- && newState == StatusBarState.KEYGUARD;
updatePauseAuth();
}
@@ -373,10 +355,13 @@
@Override
public void onBouncerVisibilityChanged() {
- mIsBouncerVisible = mKeyguardViewManager.bouncerIsOrWillBeShowing();
+ mIsBouncerVisible = mKeyguardViewManager.isBouncerShowing();
if (!mIsBouncerVisible) {
mInputBouncerHiddenAmount = 1f;
+ } else if (mKeyguardViewManager.isBouncerShowing()) {
+ mInputBouncerHiddenAmount = 0f;
}
+ updateAlpha();
updatePauseAuth();
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 821a171..567d0cb 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -399,6 +399,12 @@
val baseLayout = inflater.inflate(
R.layout.controls_base_item, lastRow, false) as ViewGroup
lastRow.addView(baseLayout)
+
+ // Use ConstraintLayout in the future... for now, manually adjust margins
+ if (lastRow.getChildCount() == 1) {
+ val lp = baseLayout.getLayoutParams() as ViewGroup.MarginLayoutParams
+ lp.setMarginStart(0)
+ }
val cvh = ControlViewHolder(
baseLayout,
controlsController.get(),
@@ -416,8 +422,12 @@
// add spacers if necessary to keep control size consistent
val mod = selectedStructure.controls.size % maxColumns
var spacersToAdd = if (mod == 0) 0 else maxColumns - mod
+ val margin = context.resources.getDimensionPixelSize(R.dimen.control_spacing)
while (spacersToAdd > 0) {
- lastRow.addView(Space(context), LinearLayout.LayoutParams(0, 0, 1f))
+ val lp = LinearLayout.LayoutParams(0, 0, 1f).apply {
+ setMarginStart(margin)
+ }
+ lastRow.addView(Space(context), lp)
spacersToAdd--
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index c45eb35..ff95604 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -307,7 +307,7 @@
// Since the gesture won't be received by the UDFPS view, manually inject an
// event.
mAuthController.onAodInterrupt((int) screenX, (int) screenY,
- rawValues[2] /* major */, rawValues[3] /* minor */);
+ rawValues[3] /* major */, rawValues[4] /* minor */);
} else {
mDozeHost.extendPulse(pulseReason);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 4418696..ff3cb21 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -62,6 +62,7 @@
private final DozeParameters mDozeParameters;
private final DozeLog mDozeLog;
private final Lazy<StatusBarStateController> mStatusBarStateController;
+ private final TunerService mTunerService;
private boolean mKeyguardShowing;
private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback =
@@ -102,8 +103,15 @@
mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
mDozeLog = dozeLog;
- tunerService.addTunable(this, Settings.Secure.DOZE_ALWAYS_ON);
+ mTunerService = tunerService;
mStatusBarStateController = statusBarStateController;
+
+ mTunerService.addTunable(this, Settings.Secure.DOZE_ALWAYS_ON);
+ }
+
+ @Override
+ public void destroy() {
+ mTunerService.removeTunable(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 5a5cce8f..70837385 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -51,6 +51,7 @@
import com.android.internal.policy.IKeyguardService;
import com.android.internal.policy.IKeyguardStateCallback;
import com.android.systemui.SystemUIApplication;
+import com.android.wm.shell.transition.Transitions;
import javax.inject.Inject;
@@ -62,16 +63,29 @@
* Run Keyguard animation as remote animation in System UI instead of local animation in
* the server process.
*
+ * 0: Runs all keyguard animation as local animation
+ * 1: Only runs keyguard going away animation as remote animation
+ * 2: Runs all keyguard animation as remote animation
+ *
* Note: Must be consistent with WindowManagerService.
*/
private static final String ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY =
"persist.wm.enable_remote_keyguard_animation";
+ private static final int sEnableRemoteKeyguardAnimation =
+ SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 1);
+
/**
* @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
*/
- public static boolean sEnableRemoteKeyguardAnimation =
- SystemProperties.getBoolean(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, false);
+ public static boolean sEnableRemoteKeyguardGoingAwayAnimation =
+ !Transitions.ENABLE_SHELL_TRANSITIONS && sEnableRemoteKeyguardAnimation >= 1;
+
+ /**
+ * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
+ */
+ public static boolean sEnableRemoteKeyguardOccludeAnimation =
+ !Transitions.ENABLE_SHELL_TRANSITIONS && sEnableRemoteKeyguardAnimation >= 2;
private final KeyguardViewMediator mKeyguardViewMediator;
private final KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
@@ -83,20 +97,22 @@
mKeyguardViewMediator = keyguardViewMediator;
mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
- if (sEnableRemoteKeyguardAnimation) {
- RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
+ RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
+ if (sEnableRemoteKeyguardGoingAwayAnimation) {
final RemoteAnimationAdapter exitAnimationAdapter =
new RemoteAnimationAdapter(mExitAnimationRunner, 0, 0);
definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, exitAnimationAdapter);
definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
exitAnimationAdapter);
+ }
+ if (sEnableRemoteKeyguardOccludeAnimation) {
final RemoteAnimationAdapter occludeAnimationAdapter =
new RemoteAnimationAdapter(mOccludeAnimationRunner, 0, 0);
definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_OCCLUDE, occludeAnimationAdapter);
definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_UNOCCLUDE, occludeAnimationAdapter);
- ActivityTaskManager.getInstance().registerRemoteAnimationsForDisplay(
- DEFAULT_DISPLAY, definition);
}
+ ActivityTaskManager.getInstance().registerRemoteAnimationsForDisplay(
+ DEFAULT_DISPLAY, definition);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 665376a..38d153e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -162,7 +162,8 @@
// If the surface alpha is 0f, it's no longer visible so we can safely be done with
// the animation.
if (surfaceBehindAlpha == 0f) {
- keyguardViewMediator.get().finishSurfaceBehindRemoteAnimation()
+ keyguardViewMediator.get().finishSurfaceBehindRemoteAnimation(
+ false /* cancelled */)
}
}
})
@@ -175,7 +176,8 @@
}
surfaceBehindEntryAnimator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
- keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished()
+ keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
+ false /* cancelled */)
}
})
@@ -317,7 +319,7 @@
}
override fun onKeyguardDismissAmountChanged() {
- if (!KeyguardService.sEnableRemoteKeyguardAnimation) {
+ if (!KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation) {
return
}
@@ -370,7 +372,7 @@
} else if (keyguardViewMediator.get()
.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe &&
reachedHideKeyguardThreshold) {
- keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished()
+ keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(false /* cancelled */)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index a159984..3276983 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1651,14 +1651,20 @@
Trace.endSection();
}
- /** Hide the keyguard and let {@code runner} handle the animation. */
+ /**
+ * Hide the keyguard and let {@code runner} handle the animation.
+ *
+ * This method should typically be called after {@link ViewMediatorCallback#keyguardDonePending}
+ * was called, when we are ready to hide the keyguard. It will do nothing if we were not
+ * expecting the keyguard to go away when called.
+ */
public void hideWithAnimation(IRemoteAnimationRunner runner) {
- if (!mShowing) {
+ if (!mKeyguardDonePending) {
return;
}
mKeyguardExitAnimationRunner = runner;
- hideLocked();
+ mViewMediatorCallback.readyForKeyguardDone();
}
/**
@@ -2017,6 +2023,7 @@
}
mHiding = false;
+ mKeyguardExitAnimationRunner = null;
mWakeAndUnlocking = false;
mPendingLock = false;
setShowingLocked(true);
@@ -2152,6 +2159,8 @@
return;
}
mHiding = false;
+ IRemoteAnimationRunner runner = mKeyguardExitAnimationRunner;
+ mKeyguardExitAnimationRunner = null;
if (mWakeAndUnlocking && mDrawnCallback != null) {
@@ -2172,17 +2181,18 @@
LatencyTracker.getInstance(mContext)
.onActionEnd(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
- IRemoteAnimationRunner runner = mKeyguardExitAnimationRunner;
- mKeyguardExitAnimationRunner = null;
-
- if (KeyguardService.sEnableRemoteKeyguardAnimation && runner != null
+ if (KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation && runner != null
&& finishedCallback != null) {
// Wrap finishedCallback to clean up the keyguard state once the animation is done.
IRemoteAnimationFinishedCallback callback =
new IRemoteAnimationFinishedCallback() {
@Override
public void onAnimationFinished() throws RemoteException {
- finishedCallback.onAnimationFinished();
+ try {
+ finishedCallback.onAnimationFinished();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onAnimationFinished", e);
+ }
onKeyguardExitFinished();
mKeyguardViewControllerLazy.get().hide(0 /* startTime */,
0 /* fadeoutDuration */);
@@ -2206,7 +2216,7 @@
// When remaining on the shade, there's no need to do a fancy remote animation,
// it will dismiss the panel in that case.
- } else if (KeyguardService.sEnableRemoteKeyguardAnimation
+ } else if (KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation
&& !mStatusBarStateController.leaveOpenOnKeyguardHide()
&& apps != null && apps.length > 0) {
mSurfaceBehindRemoteAnimationFinishedCallback = finishedCallback;
@@ -2310,15 +2320,15 @@
}
/**
- * Called if the keyguard exit animation has been cancelled and we should return to the
+ * Called if the keyguard exit animation has been cancelled and we should dismiss to the
* keyguard.
*
- * This can happen due to the system cancelling the RemoteAnimation (due to a timeout), or the
- * user cancelling the unlock swipe gesture.
+ * This can happen due to the system cancelling the RemoteAnimation (due to a timeout, a new
+ * app transition before finishing the current RemoteAnimation).
*/
private void handleCancelKeyguardExitAnimation() {
- hideSurfaceBehindKeyguard();
- mKeyguardUnlockAnimationControllerLazy.get().notifyCancelKeyguardExitAnimation();
+ showSurfaceBehindKeyguard();
+ onKeyguardExitRemoteAnimationFinished(true /* cancelled */);
}
/**
@@ -2327,8 +2337,10 @@
* This will call {@link #mSurfaceBehindRemoteAnimationFinishedCallback} to let WM know that
* we're done with the RemoteAnimation, actually hide the keyguard, and clean up state related
* to the keyguard exit animation.
+ *
+ * @param cancelled {@code true} if the animation was cancelled before it finishes.
*/
- public void onKeyguardExitRemoteAnimationFinished() {
+ public void onKeyguardExitRemoteAnimationFinished(boolean cancelled) {
if (!mSurfaceBehindRemoteAnimationRunning && !mSurfaceBehindRemoteAnimationRequested) {
return;
}
@@ -2342,7 +2354,7 @@
mKeyguardUnlockAnimationControllerLazy.get().hideKeyguardViewAfterRemoteAnimation();
}
- finishSurfaceBehindRemoteAnimation();
+ finishSurfaceBehindRemoteAnimation(cancelled);
mSurfaceBehindRemoteAnimationRequested = false;
mKeyguardUnlockAnimationControllerLazy.get().notifyFinishedKeyguardExitAnimation();
InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
@@ -2384,12 +2396,14 @@
}
/** If it's running, finishes the RemoteAnimation on the surface behind the keyguard. */
- public void finishSurfaceBehindRemoteAnimation() {
+ public void finishSurfaceBehindRemoteAnimation(boolean cancelled) {
mSurfaceBehindRemoteAnimationRunning = false;
if (mSurfaceBehindRemoteAnimationFinishedCallback != null) {
try {
- mSurfaceBehindRemoteAnimationFinishedCallback.onAnimationFinished();
+ if (!cancelled) {
+ mSurfaceBehindRemoteAnimationFinishedCallback.onAnimationFinished();
+ }
mSurfaceBehindRemoteAnimationFinishedCallback = null;
} catch (RemoteException e) {
e.printStackTrace();
@@ -2633,10 +2647,10 @@
}
/**
- * Cancel the keyguard exit animation, usually because we were swiping to unlock and the swipe
- * gesture was cancelled.
+ * Cancel the keyguard exit animation, usually because we were swiping to unlock but WM starts
+ * a new remote animation before finishing the keyguard exit animation.
*
- * This will re-show the keyguard and animate out the app/launcher surface behind the keyguard.
+ * This will dismiss the keyguard.
*/
public void cancelKeyguardExitAnimation() {
Trace.beginSection("KeyguardViewMediator#cancelKeyguardExitAnimation");
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 18d2c91..1004e25 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -171,7 +171,7 @@
visualStabilityCallback = VisualStabilityManager.Callback {
if (needsReordering) {
needsReordering = false
- reorderAllPlayers()
+ reorderAllPlayers(previousVisiblePlayerKey = null)
}
keysNeedRemoval.forEach { removePlayer(it) }
@@ -285,7 +285,7 @@
return mediaCarousel
}
- private fun reorderAllPlayers() {
+ private fun reorderAllPlayers(previousVisiblePlayerKey: MediaPlayerData.MediaSortKey?) {
mediaContent.removeAllViews()
for (mediaPlayer in MediaPlayerData.players()) {
mediaPlayer.playerViewHolder?.let {
@@ -299,9 +299,16 @@
// Automatically scroll to the active player if needed
if (shouldScrollToActivePlayer) {
shouldScrollToActivePlayer = false
- val activeMediaIndex = MediaPlayerData.activeMediaIndex()
+ val activeMediaIndex = MediaPlayerData.firstActiveMediaIndex()
if (activeMediaIndex != -1) {
- mediaCarouselScrollHandler.scrollToActivePlayer(activeMediaIndex)
+ previousVisiblePlayerKey?.let {
+ val previousVisibleIndex = MediaPlayerData.playerKeys()
+ .indexOfFirst { key -> it == key }
+ mediaCarouselScrollHandler
+ .scrollToPlayer(previousVisibleIndex, activeMediaIndex)
+ } ?: {
+ mediaCarouselScrollHandler.scrollToPlayer(destIndex = activeMediaIndex)
+ }
}
}
}
@@ -310,6 +317,8 @@
private fun addOrUpdatePlayer(key: String, oldKey: String?, data: MediaData): Boolean {
val dataCopy = data.copy(backgroundColor = bgColor)
val existingPlayer = MediaPlayerData.getMediaPlayer(key, oldKey)
+ val curVisibleMediaKey = MediaPlayerData.playerKeys()
+ .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
if (existingPlayer == null) {
var newPlayer = mediaControlPanelFactory.get()
newPlayer.attachPlayer(
@@ -322,12 +331,12 @@
newPlayer.setListening(currentlyExpanded)
MediaPlayerData.addMediaPlayer(key, dataCopy, newPlayer)
updatePlayerToState(newPlayer, noAnimation = true)
- reorderAllPlayers()
+ reorderAllPlayers(curVisibleMediaKey)
} else {
existingPlayer.bindPlayer(dataCopy, key)
MediaPlayerData.addMediaPlayer(key, dataCopy, existingPlayer)
if (visualStabilityManager.isReorderingAllowed || shouldScrollToActivePlayer) {
- reorderAllPlayers()
+ reorderAllPlayers(curVisibleMediaKey)
} else {
needsReordering = true
}
@@ -367,9 +376,11 @@
ViewGroup.LayoutParams.WRAP_CONTENT)
newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp)
newRecs.bindRecommendation(data.copy(backgroundColor = bgColor))
+ val curVisibleMediaKey = MediaPlayerData.playerKeys()
+ .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
MediaPlayerData.addMediaRecommendation(key, data, newRecs, shouldPrioritize)
updatePlayerToState(newRecs, noAnimation = true)
- reorderAllPlayers()
+ reorderAllPlayers(curVisibleMediaKey)
updatePageIndicator()
mediaCarousel.requiresRemeasuring = true
// Check postcondition: mediaContent should have the same number of children as there are
@@ -719,9 +730,8 @@
)
private val comparator =
- compareByDescending<MediaSortKey>
- { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec }
- .thenByDescending { it.data.isPlaying }
+ compareByDescending<MediaSortKey> { it.data.isPlaying }
+ .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec }
.thenByDescending { it.data.isLocalSession }
.thenByDescending { !it.data.resumption }
.thenByDescending { it.updateTime }
@@ -771,8 +781,10 @@
fun players() = mediaPlayers.values
+ fun playerKeys() = mediaPlayers.keys
+
/** Returns the index of the first non-timeout media. */
- fun activeMediaIndex(): Int {
+ fun firstActiveMediaIndex(): Int {
mediaPlayers.entries.forEachIndexed { index, e ->
if (!e.key.isSsMediaRec && e.key.data.active) {
return index
@@ -791,8 +803,6 @@
return null
}
- fun playerKeys() = mediaPlayers.keys
-
@VisibleForTesting
fun clear() {
mediaData.clear()
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt
index 45ceceb..eb354978 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt
@@ -559,8 +559,17 @@
scrollView.relativeScrollX = 0
}
- fun scrollToActivePlayer(activePlayerIndex: Int) {
- val destIndex = Math.min(mediaContent.getChildCount() - 1, activePlayerIndex)
+ /**
+ * Smooth scroll to the destination player.
+ *
+ * @param sourceIndex optional source index to indicate where the scroll should begin.
+ * @param destIndex destination index to indicate where the scroll should end.
+ */
+ fun scrollToPlayer(sourceIndex: Int = -1, destIndex: Int) {
+ if (sourceIndex >= 0 && sourceIndex < mediaContent.childCount) {
+ scrollView.relativeScrollX = sourceIndex * playerWidthPlusPadding
+ }
+ val destIndex = Math.min(mediaContent.getChildCount() - 1, destIndex)
val view = mediaContent.getChildAt(destIndex)
// We need to post this to wait for the active player becomes visible.
mainExecutor.executeDelayed({
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index d698142..c2b5807 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -36,6 +36,7 @@
import android.text.Layout;
import android.util.Log;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
@@ -45,7 +46,6 @@
import androidx.annotation.UiThread;
import androidx.constraintlayout.widget.ConstraintSet;
-import com.android.settingslib.Utils;
import com.android.settingslib.widget.AdaptiveIcon;
import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
@@ -71,12 +71,14 @@
*/
public class MediaControlPanel {
private static final String TAG = "MediaControlPanel";
+
private static final float DISABLED_ALPHA = 0.38f;
private static final String EXTRAS_SMARTSPACE_INTENT =
"com.google.android.apps.gsa.smartspace.extra.SMARTSPACE_INTENT";
- private static final String KEY_SMARTSPACE_OPEN_IN_FOREGROUND = "KEY_OPEN_IN_FOREGROUND";
private static final int MEDIA_RECOMMENDATION_ITEMS_PER_ROW = 3;
private static final int MEDIA_RECOMMENDATION_MAX_NUM = 6;
+ private static final String KEY_SMARTSPACE_ARTIST_NAME = "artist_name";
+ private static final String KEY_SMARTSPACE_OPEN_IN_FOREGROUND = "KEY_OPEN_IN_FOREGROUND";
private static final Intent SETTINGS_INTENT = new Intent(ACTION_MEDIA_CONTROLS_SETTINGS);
@@ -292,6 +294,12 @@
});
}
+ // Accessibility label
+ mPlayerViewHolder.getPlayer().setContentDescription(
+ mContext.getString(
+ R.string.controls_media_playing_item_description,
+ data.getSong(), data.getArtist(), data.getApp()));
+
ImageView albumView = mPlayerViewHolder.getAlbumView();
boolean hasArtwork = data.getArtwork() != null;
if (hasArtwork) {
@@ -330,7 +338,6 @@
}
// Song name
-
TextView titleText = mPlayerViewHolder.getTitleText();
titleText.setText(data.getSong());
@@ -497,8 +504,8 @@
mInstanceId = data.getTargetId().hashCode();
mBackgroundColor = data.getBackgroundColor();
- mRecommendationViewHolder.getRecommendations()
- .setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
+ TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations();
+ recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
List<SmartspaceAction> mediaRecommendationList = data.getRecommendations();
if (mediaRecommendationList == null || mediaRecommendationList.isEmpty()) {
@@ -522,18 +529,23 @@
icon.setColorFilter(getGrayscaleFilter());
ImageView headerLogoImageView = mRecommendationViewHolder.getCardIcon();
headerLogoImageView.setImageDrawable(icon);
- // Set up media source app's label text. Fallback to "Play" if the found label is empty.
+ // Set up media source app's label text.
CharSequence appLabel = packageManager.getApplicationLabel(applicationInfo);
if (appLabel.length() != 0) {
TextView headerTitleText = mRecommendationViewHolder.getCardText();
headerTitleText.setText(appLabel);
}
- // Set up media card's tap action if applicable.
- setSmartspaceRecItemOnClickListener(
- mRecommendationViewHolder.getRecommendations(), data.getCardAction());
+ // Set up media rec card's tap action if applicable.
+ setSmartspaceRecItemOnClickListener(recommendationCard, data.getCardAction());
+ // Set up media rec card's accessibility label.
+ recommendationCard.setContentDescription(
+ mContext.getString(R.string.controls_media_smartspace_rec_description, appLabel));
List<ImageView> mediaCoverItems = mRecommendationViewHolder.getMediaCoverItems();
+ List<ViewGroup> mediaCoverContainers = mRecommendationViewHolder.getMediaCoverContainers();
List<Integer> mediaCoverItemsResIds = mRecommendationViewHolder.getMediaCoverItemsResIds();
+ List<Integer> mediaCoverContainersResIds =
+ mRecommendationViewHolder.getMediaCoverContainersResIds();
ConstraintSet expandedSet = mMediaViewController.getExpandedLayout();
ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout();
int mediaRecommendationNum = Math.min(mediaRecommendationList.size(),
@@ -552,17 +564,39 @@
mediaCoverImageView.setImageIcon(recommendation.getIcon());
// Set up the media item's click listener if applicable.
- setSmartspaceRecItemOnClickListener(mediaCoverImageView, recommendation);
+ ViewGroup mediaCoverContainer = mediaCoverContainers.get(uiComponentIndex);
+ setSmartspaceRecItemOnClickListener(mediaCoverContainer, recommendation);
+
+ // Set up the accessibility label for the media item.
+ String artistName = recommendation.getExtras()
+ .getString(KEY_SMARTSPACE_ARTIST_NAME, "");
+ if (artistName.isEmpty()) {
+ mediaCoverImageView.setContentDescription(
+ mContext.getString(
+ R.string.controls_media_smartspace_rec_item_no_artist_description,
+ recommendation.getTitle(), appLabel));
+ } else {
+ mediaCoverImageView.setContentDescription(
+ mContext.getString(
+ R.string.controls_media_smartspace_rec_item_description,
+ recommendation.getTitle(), artistName, appLabel));
+ }
if (uiComponentIndex < MEDIA_RECOMMENDATION_ITEMS_PER_ROW) {
setVisibleAndAlpha(collapsedSet,
mediaCoverItemsResIds.get(uiComponentIndex), true);
+ setVisibleAndAlpha(collapsedSet,
+ mediaCoverContainersResIds.get(uiComponentIndex), true);
} else {
setVisibleAndAlpha(collapsedSet,
mediaCoverItemsResIds.get(uiComponentIndex), false);
+ setVisibleAndAlpha(collapsedSet,
+ mediaCoverContainersResIds.get(uiComponentIndex), false);
}
setVisibleAndAlpha(expandedSet,
mediaCoverItemsResIds.get(uiComponentIndex), true);
+ setVisibleAndAlpha(expandedSet,
+ mediaCoverContainersResIds.get(uiComponentIndex), true);
uiComponentIndex++;
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 13c7f71..5b1e039 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -437,10 +437,10 @@
* connection session.
*/
fun dismissSmartspaceRecommendation(key: String, delay: Long) {
- Log.d(TAG, "Dismissing Smartspace media target")
if (smartspaceMediaData.targetId != key) {
return
}
+ Log.d(TAG, "Dismissing Smartspace media target")
if (smartspaceMediaData.isActive) {
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
targetId = smartspaceMediaData.targetId)
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
index 9aeb63d..0da84fb 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
@@ -163,8 +163,10 @@
) {
if (useMediaResumption) {
// If this had been started from a resume state, disconnect now that it's live
- mediaBrowser?.disconnect()
- mediaBrowser = null
+ if (!key.equals(oldKey)) {
+ mediaBrowser?.disconnect()
+ mediaBrowser = null
+ }
// If we don't have a resume action, check if we haven't already
if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession) {
// TODO also check for a media button receiver intended for restarting (b/154127084)
@@ -194,6 +196,9 @@
*/
private fun tryUpdateResumptionList(key: String, componentName: ComponentName) {
Log.d(TAG, "Testing if we can connect to $componentName")
+ // Set null action to prevent additional attempts to connect
+ mediaDataManager.setResumeAction(key, null)
+ mediaBrowser?.disconnect()
mediaBrowser = mediaBrowserFactory.create(
object : ResumeMediaBrowser.Callback() {
override fun onConnected() {
@@ -202,7 +207,6 @@
override fun onError() {
Log.e(TAG, "Cannot resume with $componentName")
- mediaDataManager.setResumeAction(key, null)
mediaBrowser = null
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
index 78619d6..142628c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
@@ -40,6 +40,13 @@
itemView.requireViewById(R.id.media_cover4),
itemView.requireViewById(R.id.media_cover5),
itemView.requireViewById(R.id.media_cover6))
+ val mediaCoverContainers = listOf<ViewGroup>(
+ itemView.requireViewById(R.id.media_cover1_container),
+ itemView.requireViewById(R.id.media_cover2_container),
+ itemView.requireViewById(R.id.media_cover3_container),
+ itemView.requireViewById(R.id.media_cover4_container),
+ itemView.requireViewById(R.id.media_cover5_container),
+ itemView.requireViewById(R.id.media_cover6_container))
val mediaCoverItemsResIds = listOf<@IntegerRes Int>(
R.id.media_cover1,
R.id.media_cover2,
@@ -47,6 +54,13 @@
R.id.media_cover4,
R.id.media_cover5,
R.id.media_cover6)
+ val mediaCoverContainersResIds = listOf<@IntegerRes Int>(
+ R.id.media_cover1_container,
+ R.id.media_cover2_container,
+ R.id.media_cover3_container,
+ R.id.media_cover4_container,
+ R.id.media_cover5_container,
+ R.id.media_cover6_container)
// Settings/Guts screen
val longPressText = itemView.requireViewById<TextView>(R.id.remove_text)
@@ -58,7 +72,7 @@
init {
(recommendations.background as IlluminationDrawable).let { background ->
- mediaCoverItems.forEach { background.registerLightSource(it) }
+ mediaCoverContainers.forEach { background.registerLightSource(it) }
background.registerLightSource(cancel)
background.registerLightSource(dismiss)
background.registerLightSource(dismissLabel)
@@ -100,7 +114,13 @@
R.id.media_cover3,
R.id.media_cover4,
R.id.media_cover5,
- R.id.media_cover6
+ R.id.media_cover6,
+ R.id.media_cover1_container,
+ R.id.media_cover2_container,
+ R.id.media_cover3_container,
+ R.id.media_cover4_container,
+ R.id.media_cover5_container,
+ R.id.media_cover6_container
)
// Res Ids for the components on the guts panel.
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index d8b342a..da09793 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -512,6 +512,7 @@
lp.windowAnimations = 0;
lp.setTitle("NavigationBar" + mContext.getDisplayId());
lp.setFitInsetsTypes(0 /* types */);
+ lp.setTrustedOverlay();
NavigationBarFrame frame = (NavigationBarFrame) LayoutInflater.from(mContext).inflate(
R.layout.navigation_bar_window, null);
@@ -1447,10 +1448,14 @@
private void updateAssistantEntrypoints() {
mAssistantAvailable = mAssistManagerLazy.get()
.getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
+ boolean longPressDefault = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault);
mLongPressHomeEnabled = Settings.Secure.getInt(mContentResolver,
- Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, 1) != 0;
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0) != 0;
+ boolean gestureDefault = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_assistTouchGestureEnabledDefault);
mAssistantTouchGestureEnabled = Settings.Secure.getInt(mContentResolver,
- Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, 1) != 0;
+ Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0) != 0;
if (mOverviewProxyService.getProxy() != null) {
try {
mOverviewProxyService.getProxy().onAssistantAvailable(mAssistantAvailable
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 8838d7e..0d9749e 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -104,7 +104,7 @@
private static final int MAX_NUM_LOGGED_GESTURES = 10;
// Temporary log until b/176302696 is resolved
- static final boolean DEBUG_MISSING_GESTURE = true;
+ static final boolean DEBUG_MISSING_GESTURE = false;
static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture";
private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
@@ -147,6 +147,16 @@
mPackageName = "_UNKNOWN";
}
}
+
+ @Override
+ public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
+ mIsInPipMode = true;
+ }
+
+ @Override
+ public void onActivityUnpinned() {
+ mIsInPipMode = false;
+ }
};
private DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
@@ -220,6 +230,7 @@
private boolean mIsNavBarShownTransiently;
private boolean mIsBackGestureAllowed;
private boolean mGestureBlockingActivityRunning;
+ private boolean mIsInPipMode;
private InputMonitor mInputMonitor;
private InputChannelCompat.InputEventReceiver mInputEventReceiver;
@@ -533,16 +544,16 @@
resources.getDimensionPixelSize(R.dimen.navigation_edge_panel_height),
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
+ layoutParams.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
+ layoutParams.windowAnimations = 0;
layoutParams.privateFlags |=
WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
layoutParams.setTitle(TAG + mContext.getDisplayId());
- layoutParams.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
- layoutParams.windowAnimations = 0;
layoutParams.setFitInsetsTypes(0 /* types */);
+ layoutParams.setTrustedOverlay();
return layoutParams;
}
@@ -636,7 +647,8 @@
// If the point is inside the PiP or Nav bar overlay excluded bounds, then ignore the back
// gesture
- if (mPipExcludedBounds.contains(x, y) || mNavBarOverlayExcludedBounds.contains(x, y)) {
+ final boolean isInsidePip = mIsInPipMode && mPipExcludedBounds.contains(x, y);
+ if (isInsidePip || mNavBarOverlayExcludedBounds.contains(x, y)) {
return false;
}
@@ -898,6 +910,7 @@
pw.println(" mInRejectedExclusion" + mInRejectedExclusion);
pw.println(" mExcludeRegion=" + mExcludeRegion);
pw.println(" mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion);
+ pw.println(" mIsInPipMode=" + mIsInPipMode);
pw.println(" mPipExcludedBounds=" + mPipExcludedBounds);
pw.println(" mNavBarOverlayExcludedBounds=" + mNavBarOverlayExcludedBounds);
pw.println(" mEdgeWidthLeft=" + mEdgeWidthLeft);
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
index 72d382a..32fdf0e 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
@@ -282,13 +282,18 @@
}
private void setMaxLines(RemoteViews views, boolean showSender) {
- int nameHeight = getLineHeightFromResource(R.dimen.name_text_size_for_content);
+ int textSizeResId;
+ int nameHeight;
+ if (mLayoutSize == LAYOUT_LARGE) {
+ textSizeResId = R.dimen.content_text_size_for_large;
+ nameHeight = getLineHeightFromResource(R.dimen.name_text_size_for_large_content);
+ } else {
+ textSizeResId = R.dimen.content_text_size_for_medium;
+ nameHeight = getLineHeightFromResource(R.dimen.name_text_size_for_medium_content);
+ }
boolean isStatusLayout =
views.getLayoutId() == R.layout.people_tile_large_with_status_content;
int contentHeight = getContentHeightForLayout(nameHeight, isStatusLayout);
- int textSizeResId = mLayoutSize == LAYOUT_LARGE
- ? R.dimen.content_text_size_for_large
- : R.dimen.content_text_size_for_medium;
int lineHeight = getLineHeightFromResource(textSizeResId);
int maxAdaptiveLines = Math.floorDiv(contentHeight, lineHeight);
int maxLines = Math.max(MIN_CONTENT_MAX_LINES, maxAdaptiveLines);
@@ -348,8 +353,8 @@
if (mWidth >= getSizeInDp(R.dimen.required_width_for_medium)) {
int spaceAvailableForPadding =
mHeight - (getSizeInDp(R.dimen.avatar_size_for_medium)
- + getLineHeightFromResource(
- R.dimen.name_text_size_for_content));
+ + 4 + getLineHeightFromResource(
+ R.dimen.name_text_size_for_medium_content));
if (DEBUG) {
Log.d(TAG, "Medium view for mWidth: " + mWidth + " mHeight: " + mHeight
+ " with padding space: " + spaceAvailableForPadding);
@@ -558,9 +563,6 @@
}
views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
views.setTextViewText(R.id.text_content, statusText);
- if (mLayoutSize == LAYOUT_LARGE) {
- views.setInt(R.id.content, "setGravity", Gravity.BOTTOM);
- }
Icon statusIcon = status.getIcon();
if (statusIcon != null) {
@@ -570,6 +572,7 @@
// Show 1-line subtext on large layout with status images.
if (mLayoutSize == LAYOUT_LARGE) {
if (DEBUG) Log.d(TAG, "Remove name for large");
+ views.setInt(R.id.content, "setGravity", Gravity.BOTTOM);
views.setViewVisibility(R.id.name, View.GONE);
views.setColorAttr(R.id.text_content, "setTextColor",
android.R.attr.textColorPrimary);
@@ -830,6 +833,8 @@
views.setViewPadding(R.id.name, 0, 0, 0,
mContext.getResources().getDimensionPixelSize(
R.dimen.below_name_text_padding));
+ // All large layouts besides missed calls & statuses with images, have gravity top.
+ views.setInt(R.id.content, "setGravity", Gravity.TOP);
}
// For all layouts except Missed Calls, ensure predefined icon is regular sized.
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index 39faf5a..6888847 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -183,6 +183,7 @@
filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
mBroadcastDispatcher.registerReceiver(mBaseBroadcastReceiver, filter,
+
null /* executor */, UserHandle.ALL);
mRegisteredReceivers = true;
}
@@ -199,7 +200,8 @@
"Received updated conversation: "
+ conversation.getShortcutInfo().getLabel());
}
- updateWidgetsWithConversationChanged(conversation);
+ mBgExecutor.execute(() ->
+ updateWidgetsWithConversationChanged(conversation));
}
}
@@ -234,6 +236,10 @@
* Updates People Space widgets.
*/
public void updateWidgets(int[] widgetIds) {
+ mBgExecutor.execute(() -> updateWidgetsInBackground(widgetIds));
+ }
+
+ private void updateWidgetsInBackground(int[] widgetIds) {
try {
if (DEBUG) Log.d(TAG, "updateWidgets called");
if (widgetIds.length == 0) {
@@ -674,8 +680,8 @@
if (icon != null) {
updatedTile.setUserIcon(icon);
}
- if (DEBUG) Log.d(TAG, "Statuses: " + conversation.getStatuses().toString());
- NotificationChannel channel = conversation.getParentNotificationChannel();
+ if (DEBUG) Log.d(TAG, "Statuses: " + conversation.getStatuses());
+ NotificationChannel channel = conversation.getNotificationChannel();
if (channel != null) {
if (DEBUG) Log.d(TAG, "Important:" + channel.isImportantConversation());
updatedTile.setIsImportantConversation(channel.isImportantConversation());
@@ -1094,17 +1100,18 @@
NotificationManager.Policy.areAllVisualEffectsSuppressed(
policy.suppressedVisualEffects);
int notificationPolicyState = 0;
+ // If the user sees notifications in DND, we do not need to evaluate the current DND
+ // state, just always show notifications.
+ if (!suppressVisualEffects) {
+ if (DEBUG) Log.d(TAG, "Visual effects not suppressed.");
+ return PeopleSpaceTile.SHOW_CONVERSATIONS;
+ }
switch (mNotificationManager.getCurrentInterruptionFilter()) {
case INTERRUPTION_FILTER_ALL:
if (DEBUG) Log.d(TAG, "All interruptions allowed");
return PeopleSpaceTile.SHOW_CONVERSATIONS;
case INTERRUPTION_FILTER_PRIORITY:
if (policy.allowConversations()) {
- // If the user sees notifications in DND, show notifications in tiles in DND.
- if (!suppressVisualEffects) {
- if (DEBUG) Log.d(TAG, "Visual effects not suppressed.");
- return PeopleSpaceTile.SHOW_CONVERSATIONS;
- }
if (policy.priorityConversationSenders == CONVERSATION_SENDERS_ANYONE) {
if (DEBUG) Log.d(TAG, "All conversations allowed");
// We only show conversations, so we can show everything.
@@ -1139,11 +1146,6 @@
case INTERRUPTION_FILTER_NONE:
case INTERRUPTION_FILTER_ALARMS:
default:
- // If the user sees notifications in DND, show notifications in tiles in DND.
- if (!suppressVisualEffects) {
- if (DEBUG) Log.d(TAG, "Visual effects not suppressed.");
- return PeopleSpaceTile.SHOW_CONVERSATIONS;
- }
if (DEBUG) Log.d(TAG, "Block conversations");
return PeopleSpaceTile.BLOCK_CONVERSATIONS;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 1010b6a..14bf8ab 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -379,10 +379,10 @@
brightness.getMeasuredHeight() * 0.5f, 0);
mBrightnessAnimator = new TouchAnimator.Builder()
.addFloat(brightness, "alpha", 0, 1)
- .addFloat(brightness, "scaleY", 0.3f, 1)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .addFloat(brightness, "sliderScaleY", 0.3f, 1)
+ .setInterpolator(Interpolators.ALPHA_IN)
+ .setStartDelay(0.3f)
.build();
- brightness.setPivotY(0);
mAllViews.add(brightness);
} else {
mBrightnessAnimator = null;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 1c5fa43..e1a66b2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -615,10 +615,10 @@
public void notifyCustomizeChanged() {
// The customize state changed, so our height changed.
mContainer.updateExpansion();
- mQSPanelScrollView.setVisibility(!mQSCustomizerController.isCustomizing() ? View.VISIBLE
- : View.INVISIBLE);
- mFooter.setVisibility(
- !mQSCustomizerController.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
+ boolean customizing = isCustomizing();
+ mQSPanelScrollView.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
+ mFooter.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
+ mHeader.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
// Let the panel know the position changed and it needs to update where notifications
// and whatnot are.
mPanelView.onQsHeightChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 01a6684..0bb0a3f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.animation.UniqueObjectHostView;
import java.util.ArrayList;
import java.util.List;
@@ -96,7 +97,7 @@
private BrightnessMirrorController mBrightnessMirrorController;
private LinearLayout mHorizontalLinearLayout;
- private LinearLayout mHorizontalContentContainer;
+ protected LinearLayout mHorizontalContentContainer;
// Only used with media
private QSTileLayout mHorizontalTileLayout;
@@ -131,7 +132,7 @@
mHorizontalContentContainer = new RemeasuringLinearLayout(mContext);
mHorizontalContentContainer.setOrientation(LinearLayout.VERTICAL);
- mHorizontalContentContainer.setClipChildren(false);
+ mHorizontalContentContainer.setClipChildren(true);
mHorizontalContentContainer.setClipToPadding(false);
mHorizontalTileLayout = createHorizontalTileLayout();
@@ -384,12 +385,17 @@
private void switchSecurityFooter() {
if (mSecurityFooter != null) {
if (mContext.getResources().getConfiguration().orientation
- == Configuration.ORIENTATION_LANDSCAPE && mHeaderContainer != null
- && !mSecurityFooter.getParent().equals(mHeaderContainer)) {
+ == Configuration.ORIENTATION_LANDSCAPE && mHeaderContainer != null) {
// Adding the security view to the header, that enables us to avoid scrolling
switchToParent(mSecurityFooter, mHeaderContainer, 0);
} else {
- switchToParent(mSecurityFooter, this, -1);
+ // Where should this go? If there's media, right before it. Otherwise, at the end.
+ View mediaView = findViewByPredicate(v -> v instanceof UniqueObjectHostView);
+ int index = -1;
+ if (mediaView != null) {
+ index = indexOfChild(mediaView);
+ }
+ switchToParent(mSecurityFooter, this, index);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 9a697b1..e24acf2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -53,6 +53,14 @@
}
@Override
+ void initialize() {
+ super.initialize();
+ if (mHorizontalContentContainer != null) {
+ mHorizontalContentContainer.setClipChildren(false);
+ }
+ }
+
+ @Override
public TileLayout createRegularTileLayout() {
return new QQSSideLabelTileLayout(mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index f668722..08a68bc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -68,7 +68,9 @@
private Space mDatePrivacySeparator;
private View mClockIconsSeparator;
private boolean mShowClockIconsSeparator;
- private ViewGroup mRightLayout;
+ private View mRightLayout;
+ private View mDateContainer;
+ private View mPrivacyContainer;
private BatteryMeterView mBatteryRemainingIcon;
private StatusIconContainer mIconContainer;
@@ -129,6 +131,8 @@
mSecurityHeaderView = findViewById(R.id.header_text_container);
mClockIconsSeparator = findViewById(R.id.separator);
mRightLayout = findViewById(R.id.rightLayout);
+ mDateContainer = findViewById(R.id.date_container);
+ mPrivacyContainer = findViewById(R.id.privacy_container);
mClockView = findViewById(R.id.clock);
mDatePrivacySeparator = findViewById(R.id.space);
@@ -179,6 +183,7 @@
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateResources();
+ setDatePrivacyContainersWidth(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE);
}
@Override
@@ -187,6 +192,18 @@
updateResources();
}
+ private void setDatePrivacyContainersWidth(boolean landscape) {
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mDateContainer.getLayoutParams();
+ lp.width = landscape ? WRAP_CONTENT : 0;
+ lp.weight = landscape ? 0f : 1f;
+ mDateContainer.setLayoutParams(lp);
+
+ lp = (LinearLayout.LayoutParams) mPrivacyContainer.getLayoutParams();
+ lp.width = landscape ? WRAP_CONTENT : 0;
+ lp.weight = landscape ? 0f : 1f;
+ mPrivacyContainer.setLayoutParams(lp);
+ }
+
void updateResources() {
Resources resources = mContext.getResources();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index 1a828e4..cbdcad5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -16,9 +16,7 @@
package com.android.systemui.qs;
-import android.content.Intent;
import android.os.Bundle;
-import android.provider.AlarmClock;
import android.view.View;
import android.view.View.OnClickListener;
@@ -113,10 +111,7 @@
private View.OnClickListener mOnClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
- if (v == mClockView) {
- mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
- AlarmClock.ACTION_SHOW_ALARMS), 0);
- } else if (v == mPrivacyChip) {
+ if (v == mPrivacyChip) {
// If the privacy chip is visible, it means there were some indicators
mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK);
mPrivacyDialogController.showDialog(getContext());
@@ -167,7 +162,6 @@
@Override
protected void onViewAttached() {
- mClockView.setOnClickListener(mOnClickListener);
mPrivacyChip.setOnClickListener(mOnClickListener);
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
@@ -188,7 +182,6 @@
@Override
protected void onViewDetached() {
- mClockView.setOnClickListener(null);
mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
mPrivacyChip.setOnClickListener(null);
mStatusBarIconController.removeIconGroup(mIconManager);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index f56a2bb..49d18e6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -20,9 +20,11 @@
import static com.android.systemui.qs.customize.QSCustomizer.MENU_RESET;
import android.content.res.Configuration;
+import android.graphics.Rect;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
+import android.widget.TextView;
import android.widget.Toolbar;
import android.widget.Toolbar.OnMenuItemClickListener;
@@ -139,6 +141,20 @@
RecyclerView.State state, View host, AccessibilityNodeInfoCompat info) {
// Do not read row and column every time it changes.
}
+
+ public void calculateItemDecorationsForChild(View child, Rect outRect) {
+ // There's only a single item decoration that cares about the itemOffsets, so
+ // we just call it manually so they are never cached. This way, it's updated as the
+ // tiles are moved around.
+ // It only sets the left and right margin and only cares about tiles (not TextView).
+ if (!(child instanceof TextView)) {
+ outRect.setEmpty();
+ mTileAdapter.getMarginItemDecoration().getItemOffsets(outRect, child,
+ recyclerView, new RecyclerView.State());
+ ((LayoutParams) child.getLayoutParams()).leftMargin = outRect.left;
+ ((LayoutParams) child.getLayoutParams()).rightMargin = outRect.right;
+ }
+ }
};
layout.setSpanSizeLookup(mTileAdapter.getSizeLookup());
recyclerView.setLayoutManager(layout);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index ba65d51..d017c74 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -369,6 +369,7 @@
holder.getTileAsCustomizeView().setShowAppLabel(position > mEditIndex && !info.isSystem);
// Don't show the side view for third party tiles, as we don't have the actual state.
holder.getTileAsCustomizeView().setShowSideView(position < mEditIndex || info.isSystem);
+ holder.mTileView.setSelected(true);
holder.mTileView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
holder.mTileView.setClickable(true);
holder.mTileView.setOnClickListener(null);
@@ -690,9 +691,7 @@
if (parent.getLayoutManager() == null) return;
GridLayoutManager lm = ((GridLayoutManager) parent.getLayoutManager());
- SpanSizeLookup span = lm.getSpanSizeLookup();
- ViewHolder holder = parent.getChildViewHolder(view);
- int column = span.getSpanIndex(holder.getBindingAdapterPosition(), lm.getSpanCount());
+ int column = ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex();
if (view instanceof TextView) {
super.getItemOffsets(outRect, view, parent, state);
@@ -702,14 +701,30 @@
// columns).
outRect.left = mHalfMargin;
outRect.right = mHalfMargin;
- } else if (column == 0) {
- // Leftmost column when not using side margins. Should only have margin on the
- // right.
- outRect.right = mHalfMargin;
} else {
- // Rightmost column when not using side margins. Should only have margin on the
- // left.
- outRect.left = mHalfMargin;
+ // Leftmost or rightmost column
+ if (parent.isLayoutRtl()) {
+ if (column == 0) {
+ // Rightmost column
+ outRect.left = mHalfMargin;
+ outRect.right = 0;
+ } else {
+ // Leftmost column
+ outRect.left = 0;
+ outRect.right = mHalfMargin;
+ }
+ } else {
+ // Non RTL
+ if (column == 0) {
+ // Leftmost column
+ outRect.left = 0;
+ outRect.right = mHalfMargin;
+ } else {
+ // Rightmost column
+ outRect.left = mHalfMargin;
+ outRect.right = 0;
+ }
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
index c2a6255..69d49d4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
@@ -24,7 +24,6 @@
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.FeatureFlags
import com.android.systemui.statusbar.policy.NextAlarmController
import java.util.Locale
import javax.inject.Inject
@@ -38,7 +37,6 @@
statusBarStateController: StatusBarStateController,
activityStarter: ActivityStarter,
qsLogger: QSLogger,
- private val featureFlags: FeatureFlags,
private val userTracker: UserTracker,
nextAlarmController: NextAlarmController
) : QSTileImpl<QSTile.State>(
@@ -65,10 +63,6 @@
nextAlarmController.observe(this, callback)
}
- override fun isAvailable(): Boolean {
- return featureFlags.isAlarmTileAvailable
- }
-
override fun newTileState(): QSTile.State {
return QSTile.State().apply {
handlesLongClick = false
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index 7fab0f5..0e4434b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -49,7 +49,6 @@
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
@@ -71,7 +70,6 @@
private final PackageManager mPackageManager;
private final SecureSettings mSecureSettings;
private final QuickAccessWalletController mController;
- private final FeatureFlags mFeatureFlags;
private WalletCard mSelectedCard;
@VisibleForTesting Drawable mCardViewDrawable;
@@ -89,15 +87,13 @@
KeyguardStateController keyguardStateController,
PackageManager packageManager,
SecureSettings secureSettings,
- QuickAccessWalletController quickAccessWalletController,
- FeatureFlags featureFlags) {
+ QuickAccessWalletController quickAccessWalletController) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
mController = quickAccessWalletController;
mKeyguardStateController = keyguardStateController;
mPackageManager = packageManager;
mSecureSettings = secureSettings;
- mFeatureFlags = featureFlags;
}
@@ -192,8 +188,7 @@
@Override
public boolean isAvailable() {
- return mFeatureFlags.isQuickAccessWalletEnabled()
- && mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
+ return mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
&& !mPackageManager.hasSystemFeature(FEATURE_CHROME_OS)
&& mSecureSettings.getString(NFC_PAYMENT_DEFAULT_COMPONENT) != null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index f4c15fb..cb0c411 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -560,8 +560,6 @@
mSmartspaceTransitionController.createExternalInterface().asBinder());
try {
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.onInitialize: curUser="
- + mCurrentBoundedUserId);
mOverviewProxy.onInitialize(params);
} catch (RemoteException e) {
mCurrentBoundedUserId = -1;
@@ -646,7 +644,6 @@
// Listen for nav bar mode changes
mNavBarMode = navModeController.addListener(this);
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService: mode=" + mNavBarMode);
// Listen for launcher package changes
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
@@ -807,7 +804,6 @@
mOverviewServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
UserHandle.of(getCurrentUserId()));
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.connect: bound=" + mBound);
} catch (SecurityException e) {
Log.e(TAG_OPS, "Unable to bind because of security error", e);
}
@@ -860,9 +856,6 @@
private void disconnectFromLauncherService() {
if (mBound) {
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.disconnect: curUser="
- + mCurrentBoundedUserId);
-
// Always unbind the service (ie. if called through onNullBinding or onBindingDied)
mContext.unbindService(mOverviewServiceConnection);
mBound = false;
@@ -993,14 +986,11 @@
final int currentUser = ActivityManagerWrapper.getInstance().getCurrentUserId();
mIsEnabled = mContext.getPackageManager().resolveServiceAsUser(mQuickStepIntent,
MATCH_SYSTEM_ONLY, currentUser) != null;
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.updateEnabledState: curUser="
- + currentUser + " enabled=" + mIsEnabled);
}
@Override
public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
- Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.onNavModeChanged: mode=" + mode);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index 30c9b44..d5b4032 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.HardwareRenderer;
+import android.graphics.Matrix;
import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.RenderNode;
@@ -31,9 +32,12 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
import android.util.Log;
import android.view.ScrollCaptureResponse;
import android.view.View;
+import android.view.ViewTreeObserver;
import android.widget.ImageView;
import androidx.constraintlayout.widget.ConstraintLayout;
@@ -74,6 +78,7 @@
private ImageView mPreview;
private ImageView mTransitionView;
+ private ImageView mEnterTransitionView;
private View mSave;
private View mEdit;
private View mShare;
@@ -111,7 +116,7 @@
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate(savedInstanceState = " + savedInstanceState + ")");
super.onCreate(savedInstanceState);
-
+ postponeEnterTransition();
setContentView(R.layout.long_screenshot);
mPreview = requireViewById(R.id.preview);
@@ -122,6 +127,7 @@
mMagnifierView = requireViewById(R.id.magnifier);
mCropView.setCropInteractionListener(mMagnifierView);
mTransitionView = requireViewById(R.id.transition);
+ mEnterTransitionView = requireViewById(R.id.enter_transition);
mSave.setOnClickListener(this::onClicked);
mEdit.setOnClickListener(this::onClicked);
@@ -184,8 +190,8 @@
private void onLongScreenshotReceived(LongScreenshot longScreenshot) {
Log.d(TAG, "onLongScreenshotReceived(longScreenshot=" + longScreenshot + ")");
mLongScreenshot = longScreenshot;
- mPreview.setImageDrawable(mLongScreenshot.getDrawable());
- updateImageDimensions();
+ Drawable drawable = mLongScreenshot.getDrawable();
+ mPreview.setImageDrawable(drawable);
mCropView.setVisibility(View.VISIBLE);
mMagnifierView.setDrawable(mLongScreenshot.getDrawable(),
mLongScreenshot.getWidth(), mLongScreenshot.getHeight());
@@ -196,9 +202,35 @@
float bottomFraction = Math.min(1f,
1 - (mLongScreenshot.getBottom() - mLongScreenshot.getPageHeight())
/ (float) mLongScreenshot.getHeight());
- mCropView.animateBoundaryTo(CropView.CropBoundary.TOP, topFraction);
- mCropView.animateBoundaryTo(CropView.CropBoundary.BOTTOM, bottomFraction);
- setButtonsEnabled(true);
+
+ mEnterTransitionView.setImageDrawable(drawable);
+
+ mEnterTransitionView.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mEnterTransitionView.getViewTreeObserver().removeOnPreDrawListener(this);
+ updateImageDimensions();
+ startPostponedEnterTransition();
+ if (isActivityTransitionRunning()) {
+ getWindow().getSharedElementEnterTransition().addListener(
+ new TransitionListenerAdapter() {
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ super.onTransitionEnd(transition);
+ mPreview.animate().alpha(1f);
+ mCropView.animateBoundaryTo(
+ CropView.CropBoundary.TOP, topFraction);
+ mCropView.animateBoundaryTo(
+ CropView.CropBoundary.BOTTOM, bottomFraction);
+ setButtonsEnabled(true);
+ mEnterTransitionView.setVisibility(View.GONE);
+ }
+ });
+ }
+ return true;
+ }
+ });
// Immediately export to temp image file for saved state
mCacheSaveFuture = mImageExporter.exportAsTempFile(mBackgroundExecutor,
@@ -412,22 +444,26 @@
// The image width and height on screen
int imageHeight = previewHeight;
int imageWidth = previewWidth;
+ float scale;
+ int extraPadding = 0;
if (imageRatio > viewRatio) {
// Image is full width and height is constrained, compute extra padding to inform
// CropView
imageHeight = (int) (previewHeight * viewRatio / imageRatio);
- int extraPadding = (previewHeight - imageHeight) / 2;
+ extraPadding = (previewHeight - imageHeight) / 2;
mCropView.setExtraPadding(extraPadding + mPreview.getPaddingTop(),
extraPadding + mPreview.getPaddingBottom());
imageTop += (previewHeight - imageHeight) / 2;
mCropView.setExtraPadding(extraPadding, extraPadding);
mCropView.setImageWidth(previewWidth);
+ scale = previewWidth / (float) mPreview.getDrawable().getIntrinsicWidth();
} else {
imageWidth = (int) (previewWidth * imageRatio / viewRatio);
imageLeft += (previewWidth - imageWidth) / 2;
// Image is full height
mCropView.setExtraPadding(mPreview.getPaddingTop(), mPreview.getPaddingBottom());
mCropView.setImageWidth((int) (previewHeight * imageRatio));
+ scale = previewHeight / (float) mPreview.getDrawable().getIntrinsicHeight();
}
// Update transition view's position and scale.
@@ -439,5 +475,20 @@
params.width = boundaries.width();
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);
+
+ 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 1f9221c..bda198e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -16,7 +16,6 @@
package com.android.systemui.screenshot;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
@@ -62,7 +61,6 @@
import android.view.DisplayAddress;
import android.view.KeyEvent;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.ScrollCaptureResponse;
import android.view.SurfaceControl;
import android.view.View;
@@ -289,6 +287,7 @@
mWindowLayoutParams.setTitle("ScreenshotAnimation");
mWindowLayoutParams.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ mWindowLayoutParams.setFitInsetsTypes(0);
// This is needed to let touches pass through outside the touchable areas
mWindowLayoutParams.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
@@ -402,11 +401,6 @@
Log.d(TAG, "reloadAssets()");
}
- // respect the display cutout in landscape (since we'd otherwise overlap) but not portrait
- int orientation = mContext.getResources().getConfiguration().orientation;
- mWindowLayoutParams.setFitInsetsTypes(
- orientation == ORIENTATION_PORTRAIT ? 0 : WindowInsets.Type.displayCutout());
-
// Inflate the screenshot layout
mScreenshotView = (ScreenshotView)
LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null);
@@ -420,18 +414,12 @@
public void onDismiss() {
finishDismiss();
}
- });
- // TODO(159460485): Remove this when focus is handled properly in the system
- mScreenshotView.setOnTouchListener((v, event) -> {
- if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) {
- if (DEBUG_INPUT) {
- Log.d(TAG, "onTouch: ACTION_OUTSIDE");
- }
- // Once the user touches outside, stop listening for input
+ @Override
+ public void onTouchOutside() {
+ // TODO(159460485): Remove this when focus is handled properly in the system
setWindowFocusable(false);
}
- return false;
});
mScreenshotView.setOnKeyListener((v, keyCode, event) -> {
@@ -494,17 +482,6 @@
saveScreenshot(screenshot, finisher, screenRect, Insets.NONE, true);
}
- private void updateDisplayCutout() {
- // respect the display cutout in landscape (since we'd otherwise overlap) but not portrait
- int orientation = mContext.getResources().getConfiguration().orientation;
- mWindowLayoutParams.setFitInsetsTypes(
- orientation == ORIENTATION_PORTRAIT ? 0 : WindowInsets.Type.displayCutout());
- final View decorView = mWindow.peekDecorView();
- if (decorView != null && decorView.isAttachedToWindow()) {
- mWindowManager.updateViewLayout(decorView, mWindowLayoutParams);
- }
- }
-
private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
Insets screenInsets, boolean showFlash) {
if (mAccessibilityManager.isEnabled()) {
@@ -528,8 +505,8 @@
mScreenshotView.reset();
}
- int orientation = mContext.getResources().getConfiguration().orientation;
- mScreenshotView.updateOrientation(orientation == ORIENTATION_PORTRAIT);
+ mScreenshotView.updateOrientation(mWindowManager.getCurrentWindowMetrics()
+ .getWindowInsets().getDisplayCutout());
mScreenBitmap = screenshot;
@@ -554,17 +531,18 @@
// Wait until this window is attached to request because it is
// the reference used to locate the target window (below).
withWindowAttached(() -> {
- mScrollCaptureClient.setHostWindowToken(mWindow.getDecorView().getWindowToken());
- if (mLastScrollCaptureRequest != null) {
- mLastScrollCaptureRequest.cancel(true);
- }
- mLastScrollCaptureRequest = mScrollCaptureClient.request(DEFAULT_DISPLAY);
- mLastScrollCaptureRequest.addListener(() ->
- onScrollCaptureResponseReady(mLastScrollCaptureRequest), mMainExecutor);
+ requestScrollCapture();
mWindow.peekDecorView().getViewRootImpl().setActivityConfigCallback(
(overrideConfig, newDisplayId) -> {
if (mConfigChanges.applyNewConfig(mContext.getResources())) {
- updateDisplayCutout();
+ // Hide the scroll chip until we know it's available in this orientation
+ mScreenshotView.hideScrollChip();
+ // Delay scroll capture eval a bit to allow the underlying activity
+ // to set up in the new orientation.
+ mScreenshotHandler.postDelayed(this::requestScrollCapture, 150);
+ mScreenshotView.updateDisplayCutoutMargins(
+ mWindowManager.getCurrentWindowMetrics().getWindowInsets()
+ .getDisplayCutout());
}
});
});
@@ -593,6 +571,16 @@
cancelTimeout(); // restarted after animation
}
+ private void requestScrollCapture() {
+ mScrollCaptureClient.setHostWindowToken(mWindow.getDecorView().getWindowToken());
+ if (mLastScrollCaptureRequest != null) {
+ mLastScrollCaptureRequest.cancel(true);
+ }
+ mLastScrollCaptureRequest = mScrollCaptureClient.request(DEFAULT_DISPLAY);
+ mLastScrollCaptureRequest.addListener(() ->
+ onScrollCaptureResponseReady(mLastScrollCaptureRequest), mMainExecutor);
+ }
+
private void onScrollCaptureResponseReady(Future<ScrollCaptureResponse> responseFuture) {
try {
if (mLastScrollCaptureResponse != null) {
@@ -603,7 +591,7 @@
// No connection means that the target window wasn't found
// or that it cannot support scroll capture.
Log.d(TAG, "ScrollCapture: " + mLastScrollCaptureResponse.getDescription() + " ["
- + mLastScrollCaptureResponse.getWindowTitle() + "]");
+ + mLastScrollCaptureResponse.getWindowTitle() + "]");
return;
}
Log.d(TAG, "ScrollCapture: connected to window ["
@@ -611,6 +599,7 @@
final ScrollCaptureResponse response = mLastScrollCaptureResponse;
mScreenshotView.showScrollChip(/* onClick */ () -> {
+ mScreenshotView.prepareScrollingTransition(response, mScreenBitmap);
// Clear the reference to prevent close() in dismissScreenshot
mLastScrollCaptureResponse = null;
final ListenableFuture<ScrollCaptureController.LongScreenshot> future =
@@ -628,9 +617,14 @@
final Intent intent = new Intent(mContext, LongScreenshotActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- mContext.startActivity(intent);
- dismissScreenshot(false);
+ Pair<ActivityOptions, ExitTransitionCoordinator> transition =
+ ActivityOptions.startSharedElementAnimation(
+ mWindow, new ScreenshotExitTransitionCallbacks(), null,
+ Pair.create(mScreenshotView.getScrollablePreview(),
+ ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME));
+ transition.second.startExit();
+ mContext.startActivity(intent, transition.first.toBundle());
}, mMainExecutor);
});
} catch (CancellationException e) {
@@ -654,7 +648,8 @@
}
@Override
- public void onWindowDetached() { }
+ public void onWindowDetached() {
+ }
});
}
@@ -852,24 +847,9 @@
*/
private Supplier<ActionTransition> getActionTransitionSupplier() {
return () -> {
- ExitTransitionCallbacks cb = new ExitTransitionCallbacks() {
- @Override
- public boolean isReturnTransitionAllowed() {
- return false;
- }
-
- @Override
- public void hideSharedElements() {
- finishDismiss();
- }
-
- @Override
- public void onFinish() {
- }
- };
-
Pair<ActivityOptions, ExitTransitionCoordinator> transition =
- ActivityOptions.startSharedElementAnimation(mWindow, cb, null,
+ ActivityOptions.startSharedElementAnimation(
+ mWindow, new ScreenshotExitTransitionCallbacks(), null,
Pair.create(mScreenshotView.getScreenshotPreview(),
ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME));
transition.second.startExit();
@@ -955,4 +935,20 @@
}
return matchWithinTolerance;
}
+
+ private class ScreenshotExitTransitionCallbacks implements ExitTransitionCallbacks {
+ @Override
+ public boolean isReturnTransitionAllowed() {
+ return false;
+ }
+
+ @Override
+ public void hideSharedElements() {
+ finishDismiss();
+ }
+
+ @Override
+ public void onFinish() {
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index facebee..2a22179 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -40,6 +40,7 @@
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Insets;
+import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
@@ -49,19 +50,26 @@
import android.graphics.drawable.Icon;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.LayerDrawable;
+import android.os.Looper;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.MathUtils;
+import android.view.Choreographer;
+import android.view.Display;
+import android.view.DisplayCutout;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.ScrollCaptureResponse;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
@@ -71,9 +79,12 @@
import android.widget.ImageView;
import android.widget.LinearLayout;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition;
+import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.QuickStepContract;
import java.util.ArrayList;
@@ -89,6 +100,9 @@
void onUserInteraction();
void onDismiss();
+
+ /** DOWN motion event was observed outside of the touchable areas of this view. */
+ void onTouchOutside();
}
private static final String TAG = logTag(ScreenshotView.class);
@@ -119,15 +133,15 @@
private final AccessibilityManager mAccessibilityManager;
private int mNavMode;
- private int mLeftInset;
- private int mRightInset;
private boolean mOrientationPortrait;
private boolean mDirectionLTR;
private ScreenshotSelectorView mScreenshotSelectorView;
+ private ImageView mScrollingScrim;
private View mScreenshotStatic;
private ImageView mScreenshotPreview;
private View mScreenshotPreviewBorder;
+ private ImageView mScrollablePreview;
private ImageView mScreenshotFlash;
private ImageView mActionsContainerBackground;
private HorizontalScrollView mActionsContainer;
@@ -145,6 +159,7 @@
private boolean mPendingSharedTransition;
private GestureDetector mSwipeDetector;
private SwipeDismissHandler mSwipeDismissHandler;
+ private InputMonitorCompat mInputMonitor;
private final ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>();
private PendingInteraction mPendingInteraction;
@@ -202,6 +217,21 @@
});
mSwipeDetector.setIsLongpressEnabled(false);
mSwipeDismissHandler = new SwipeDismissHandler();
+ addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ startInputListening();
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ stopInputListening();
+ }
+ });
+ }
+
+ public void hideScrollChip() {
+ mScrollChip.setVisibility(View.GONE);
}
/**
@@ -227,6 +257,10 @@
@Override // ViewTreeObserver.OnComputeInternalInsetsListener
public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) {
inoutInfo.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+ inoutInfo.touchableRegion.set(getTouchRegion());
+ }
+
+ private Region getTouchRegion() {
Region touchRegion = new Region();
final Rect tmpRect = new Rect();
@@ -240,15 +274,41 @@
touchRegion.op(tmpRect, Region.Op.UNION);
if (QuickStepContract.isGesturalMode(mNavMode)) {
+ final WindowManager wm = mContext.getSystemService(WindowManager.class);
+ final WindowMetrics windowMetrics = wm.getCurrentWindowMetrics();
+ final Insets gestureInsets = windowMetrics.getWindowInsets().getInsets(
+ WindowInsets.Type.systemGestures());
// Receive touches in gesture insets such that they don't cause TOUCH_OUTSIDE
- Rect inset = new Rect(0, 0, mLeftInset, mDisplayMetrics.heightPixels);
+ Rect inset = new Rect(0, 0, gestureInsets.left, mDisplayMetrics.heightPixels);
touchRegion.op(inset, Region.Op.UNION);
- inset.set(mDisplayMetrics.widthPixels - mRightInset, 0, mDisplayMetrics.widthPixels,
- mDisplayMetrics.heightPixels);
+ inset.set(mDisplayMetrics.widthPixels - gestureInsets.right, 0,
+ mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels);
touchRegion.op(inset, Region.Op.UNION);
}
+ return touchRegion;
+ }
- inoutInfo.touchableRegion.set(touchRegion);
+ private void startInputListening() {
+ stopInputListening();
+ mInputMonitor = new InputMonitorCompat("Screenshot", Display.DEFAULT_DISPLAY);
+ mInputMonitor.getInputReceiver(Looper.getMainLooper(), Choreographer.getInstance(),
+ ev -> {
+ if (ev instanceof MotionEvent) {
+ MotionEvent event = (MotionEvent) ev;
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN
+ && !getTouchRegion().contains(
+ (int) event.getRawX(), (int) event.getRawY())) {
+ mCallbacks.onTouchOutside();
+ }
+ }
+ });
+ }
+
+ private void stopInputListening() {
+ if (mInputMonitor != null) {
+ mInputMonitor.dispose();
+ mInputMonitor = null;
+ }
}
@Override // ViewGroup
@@ -262,6 +322,7 @@
@Override // View
protected void onFinishInflate() {
+ mScrollingScrim = requireNonNull(findViewById(R.id.screenshot_scrolling_scrim));
mScreenshotStatic = requireNonNull(findViewById(R.id.global_screenshot_static));
mScreenshotPreview = requireNonNull(findViewById(R.id.global_screenshot_preview));
mScreenshotPreviewBorder = requireNonNull(
@@ -275,6 +336,7 @@
mBackgroundProtection = requireNonNull(
findViewById(R.id.global_screenshot_actions_background));
mDismissButton = requireNonNull(findViewById(R.id.global_screenshot_dismiss_button));
+ mScrollablePreview = requireNonNull(findViewById(R.id.screenshot_scrollable_preview));
mScreenshotFlash = requireNonNull(findViewById(R.id.global_screenshot_flash));
mScreenshotSelectorView = requireNonNull(findViewById(R.id.global_screenshot_selector));
mShareChip = requireNonNull(mActionsContainer.findViewById(R.id.screenshot_share_chip));
@@ -303,17 +365,6 @@
mDirectionLTR =
getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
- setOnApplyWindowInsetsListener((v, insets) -> {
- if (QuickStepContract.isGesturalMode(mNavMode)) {
- Insets gestureInsets = insets.getInsets(WindowInsets.Type.systemGestures());
- mLeftInset = gestureInsets.left;
- mRightInset = gestureInsets.right;
- } else {
- mLeftInset = mRightInset = 0;
- }
- return ScreenshotView.this.onApplyWindowInsets(insets);
- });
-
// Get focus so that the key events go to the layout.
setFocusableInTouchMode(true);
requestFocus();
@@ -323,6 +374,10 @@
return mScreenshotPreview;
}
+ View getScrollablePreview() {
+ return mScrollablePreview;
+ }
+
/**
* Set up the logger and callback on dismissal.
*
@@ -344,12 +399,35 @@
mScreenshotPreview.setImageDrawable(createScreenDrawable(mResources, bitmap, screenInsets));
}
- void updateOrientation(boolean portrait) {
- mOrientationPortrait = portrait;
+ void updateDisplayCutoutMargins(DisplayCutout cutout) {
+ int orientation = mContext.getResources().getConfiguration().orientation;
+ mOrientationPortrait = (orientation == ORIENTATION_PORTRAIT);
+ FrameLayout.LayoutParams p =
+ (FrameLayout.LayoutParams) mScreenshotStatic.getLayoutParams();
+ if (cutout == null) {
+ p.setMargins(0, 0, 0, 0);
+ } else {
+ Insets waterfall = cutout.getWaterfallInsets();
+ if (mOrientationPortrait) {
+ p.setMargins(waterfall.left, Math.max(cutout.getSafeInsetTop(), waterfall.top),
+ waterfall.right, Math.max(cutout.getSafeInsetBottom(), waterfall.bottom));
+ } else {
+ p.setMargins(Math.max(cutout.getSafeInsetLeft(), waterfall.left), waterfall.top,
+ Math.max(cutout.getSafeInsetRight(), waterfall.right), waterfall.bottom);
+ }
+ }
+ mScreenshotStatic.setLayoutParams(p);
+ mScreenshotStatic.requestLayout();
+ }
+
+ void updateOrientation(DisplayCutout cutout) {
+ int orientation = mContext.getResources().getConfiguration().orientation;
+ mOrientationPortrait = (orientation == ORIENTATION_PORTRAIT);
+ updateDisplayCutoutMargins(cutout);
int screenshotFixedSize =
mContext.getResources().getDimensionPixelSize(R.dimen.global_screenshot_x_scale);
ViewGroup.LayoutParams params = mScreenshotPreview.getLayoutParams();
- if (portrait) {
+ if (mOrientationPortrait) {
params.width = screenshotFixedSize;
params.height = LayoutParams.WRAP_CONTENT;
mScreenshotPreview.setScaleType(ImageView.ScaleType.FIT_START);
@@ -358,6 +436,7 @@
params.height = screenshotFixedSize;
mScreenshotPreview.setScaleType(ImageView.ScaleType.FIT_END);
}
+
mScreenshotPreview.setLayoutParams(params);
}
@@ -672,6 +751,38 @@
}
}
+ private Rect scrollableAreaOnScreen(ScrollCaptureResponse response) {
+ Rect r = new Rect(response.getBoundsInWindow());
+ Rect windowInScreen = response.getWindowBounds();
+ r.offset(windowInScreen.left, windowInScreen.top);
+ r.intersect(new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
+ return r;
+ }
+
+ void prepareScrollingTransition(ScrollCaptureResponse response, Bitmap screenBitmap) {
+ Rect scrollableArea = scrollableAreaOnScreen(response);
+ float scale = mCornerSizeX
+ / (mOrientationPortrait ? screenBitmap.getWidth() : screenBitmap.getHeight());
+ ConstraintLayout.LayoutParams params =
+ (ConstraintLayout.LayoutParams) mScrollablePreview.getLayoutParams();
+
+ params.width = (int) (scale * scrollableArea.width());
+ params.height = (int) (scale * scrollableArea.height());
+ Matrix matrix = new Matrix();
+ matrix.setScale(scale, scale);
+ matrix.postTranslate(0, -scrollableArea.top * scale);
+
+ mScrollablePreview.setTranslationX(scale * scrollableArea.left);
+ mScrollablePreview.setTranslationY(scale * scrollableArea.top);
+ mScrollablePreview.setImageMatrix(matrix);
+
+ mScrollingScrim.setImageBitmap(screenBitmap);
+ mScrollingScrim.setVisibility(View.VISIBLE);
+ mScrollablePreview.setImageBitmap(screenBitmap);
+ mScrollablePreview.setVisibility(View.VISIBLE);
+ createScreenshotFadeDismissAnimation(true).start();
+ }
+
boolean isDismissing() {
return (mDismissAnimation != null && mDismissAnimation.isRunning());
}
@@ -772,7 +883,7 @@
transition.action.actionIntent.send();
// fade out non-preview UI
- createScreenshotFadeDismissAnimation().start();
+ createScreenshotFadeDismissAnimation(false).start();
} catch (PendingIntent.CanceledException e) {
mPendingSharedTransition = false;
if (transition.onCancelRunnable != null) {
@@ -810,7 +921,7 @@
return animSet;
}
- private ValueAnimator createScreenshotFadeDismissAnimation() {
+ ValueAnimator createScreenshotFadeDismissAnimation(boolean fadePreview) {
ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1);
alphaAnim.addUpdateListener(animation -> {
float alpha = 1 - animation.getAnimatedFraction();
@@ -818,6 +929,10 @@
mActionsContainerBackground.setAlpha(alpha);
mActionsContainer.setAlpha(alpha);
mBackgroundProtection.setAlpha(alpha);
+ mScreenshotPreviewBorder.setAlpha(alpha);
+ if (fadePreview) {
+ mScreenshotPreview.setAlpha(alpha);
+ }
});
alphaAnim.setDuration(600);
return alphaAnim;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java
index 2863074..94e3149 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java
@@ -405,6 +405,10 @@
return new Rect(mWindowBounds);
}
+ public Rect getBoundsInWindow() {
+ return new Rect(mBoundsInWindow);
+ }
+
@Override
public int getMaxTiles() {
return mMaxTiles;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index b60fd13..8dd6c89 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -17,6 +17,10 @@
package com.android.systemui.settings.brightness;
import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableWrapper;
+import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -24,6 +28,7 @@
import android.widget.SeekBar.OnSeekBarChangeListener;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.settingslib.RestrictedLockUtils;
import com.android.systemui.Gefingerpoken;
@@ -39,6 +44,9 @@
private ToggleSeekBar mSlider;
private DispatchTouchEventListener mListener;
private Gefingerpoken mOnInterceptListener;
+ @Nullable
+ private Drawable mProgressDrawable;
+ private float mScale = 1f;
public BrightnessSliderView(Context context) {
this(context, null);
@@ -55,6 +63,17 @@
mSlider = requireViewById(R.id.slider);
mSlider.setAccessibilityLabel(getContentDescription().toString());
+
+ // Finds the progress drawable. Assumes brightness_progress_drawable.xml
+ try {
+ LayerDrawable progress = (LayerDrawable) mSlider.getProgressDrawable();
+ DrawableWrapper progressSlider = (DrawableWrapper) progress
+ .findDrawableByLayerId(android.R.id.progress);
+ LayerDrawable actualProgressSlider = (LayerDrawable) progressSlider.getDrawable();
+ mProgressDrawable = actualProgressSlider.findDrawableByLayerId(R.id.slider_foreground);
+ } catch (Exception e) {
+ // Nothing to do, mProgressDrawable will be null.
+ }
}
/**
@@ -151,6 +170,37 @@
return super.onInterceptTouchEvent(ev);
}
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ applySliderScale();
+ }
+
+ /**
+ * Sets the scale for the progress bar (for brightness_progress_drawable.xml)
+ *
+ * This will only scale the thick progress bar and not the icon inside
+ */
+ public void setSliderScaleY(float scale) {
+ if (scale != mScale) {
+ mScale = scale;
+ applySliderScale();
+ }
+ }
+
+ private void applySliderScale() {
+ if (mProgressDrawable != null) {
+ final Rect r = mProgressDrawable.getBounds();
+ int height = (int) (mProgressDrawable.getIntrinsicHeight() * mScale);
+ int inset = (mProgressDrawable.getIntrinsicHeight() - height) / 2;
+ mProgressDrawable.setBounds(r.left, inset, r.right, inset + height);
+ }
+ }
+
+ public float getSliderScaleY() {
+ return mScale;
+ }
+
/**
* Interface to attach a listener for {@link View#dispatchTouchEvent}.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index 0df69a0..9fa4609 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -204,6 +204,12 @@
return;
}
NotificationEntry entry = alertEntry.mEntry;
+
+ // If the notification is animating, we will remove it at the end of the animation.
+ if (entry != null && entry.isExpandAnimationRunning()) {
+ return;
+ }
+
mAlertEntries.remove(key);
onAlertEntryRemoved(alertEntry);
entry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
index 071e947..ce796d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
@@ -107,6 +107,8 @@
it.println("minBlurRadius: $minBlurRadius")
it.println("maxBlurRadius: $maxBlurRadius")
it.println("supportsBlursOnWindows: ${supportsBlursOnWindows()}")
+ it.println("CROSS_WINDOW_BLUR_SUPPORTED: $CROSS_WINDOW_BLUR_SUPPORTED")
+ it.println("isHighEndGfx: ${ActivityManager.isHighEndGfx()}")
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index c7b6e67..7e67619 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -65,18 +65,10 @@
return mFlagReader.isEnabled(R.bool.flag_monet);
}
- public boolean isQuickAccessWalletEnabled() {
- return mFlagReader.isEnabled(R.bool.flag_wallet);
- }
-
public boolean isPMLiteEnabled() {
return mFlagReader.isEnabled(R.bool.flag_pm_lite);
}
- public boolean isAlarmTileAvailable() {
- return mFlagReader.isEnabled(R.bool.flag_alarm_tile);
- }
-
public boolean isChargingRippleEnabled() {
return mFlagReader.isEnabled(R.bool.flag_charging_ripple);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index ca81a7b..0b67e7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -221,12 +221,10 @@
buttonIndex = actionGroup.indexOfChild(view);
}
final int count = mEntryManager.getActiveNotificationsCount();
- final int rank = mEntryManager
- .getActiveNotificationUnfiltered(key).getRanking().getRank();
+ final int rank = entry.getRanking().getRank();
NotificationVisibility.NotificationLocation location =
- NotificationLogger.getNotificationLocation(
- mEntryManager.getActiveNotificationUnfiltered(key));
+ NotificationLogger.getNotificationLocation(entry);
final NotificationVisibility nv =
NotificationVisibility.obtain(key, rank, count, true, location);
mClickNotifier.onNotificationActionClick(key, buttonIndex, action, nv, false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index f7b3a35..085a076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -26,6 +26,8 @@
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
@@ -53,6 +55,11 @@
private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
private static final String TAG = "NotificationShelf";
+ // More extreme version of SLOW_OUT_LINEAR_IN which keeps the icon nearly invisible until after
+ // the next icon has translated out of the way, to avoid overlapping.
+ private static final Interpolator ICON_ALPHA_INTERPOLATOR =
+ new PathInterpolator(0.6f, 0f, 0.6f, 0f);
+
private NotificationIconContainer mShelfIcons;
private int[] mTmp = new int[2];
private boolean mHideBackground;
@@ -659,7 +666,7 @@
if (iconState == null) {
return;
}
- iconState.alpha = transitionAmount;
+ iconState.alpha = ICON_ALPHA_INTERPOLATOR.getInterpolation(transitionAmount);
boolean isAppearing = row.isDrawingAppearAnimation() && !row.isInShelf();
iconState.hidden = isAppearing
|| (view instanceof ExpandableNotificationRow
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
index bce39ce..c248670 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
@@ -7,6 +7,7 @@
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController
+import com.android.systemui.statusbar.policy.HeadsUpUtil
import kotlin.math.ceil
import kotlin.math.max
@@ -22,8 +23,8 @@
return NotificationLaunchAnimatorController(
notificationShadeWindowViewController,
notificationListContainer,
- notification,
- headsUpManager
+ headsUpManager,
+ notification
)
}
}
@@ -36,10 +37,11 @@
class NotificationLaunchAnimatorController(
private val notificationShadeWindowViewController: NotificationShadeWindowViewController,
private val notificationListContainer: NotificationListContainer,
- private val notification: ExpandableNotificationRow,
- private val headsUpManager: HeadsUpManagerPhone
+ private val headsUpManager: HeadsUpManagerPhone,
+ private val notification: ExpandableNotificationRow
) : ActivityLaunchAnimator.Controller {
- private val notificationKey = notification.entry.sbn.key
+ private val notificationEntry = notification.entry
+ private val notificationKey = notificationEntry.sbn.key
override var launchContainer: ViewGroup
get() = notification.rootView as ViewGroup
@@ -82,6 +84,7 @@
override fun onIntentStarted(willAnimate: Boolean) {
notificationShadeWindowViewController.setExpandAnimationRunning(willAnimate)
+ notificationEntry.isExpandAnimationRunning = willAnimate
if (!willAnimate) {
removeHun(animate = true)
@@ -93,6 +96,7 @@
return
}
+ HeadsUpUtil.setNeedsHeadsUpDisappearAnimationAfterClick(notification, animate)
headsUpManager.removeNotification(notificationKey, true /* releaseImmediately */, animate)
}
@@ -100,6 +104,7 @@
// TODO(b/184121838): Should we call InteractionJankMonitor.cancel if the animation started
// here?
notificationShadeWindowViewController.setExpandAnimationRunning(false)
+ notificationEntry.isExpandAnimationRunning = false
removeHun(animate = true)
}
@@ -116,6 +121,7 @@
notification.isExpandAnimationRunning = false
notificationShadeWindowViewController.setExpandAnimationRunning(false)
+ notificationEntry.isExpandAnimationRunning = false
notificationListContainer.setExpandingNotification(null)
applyParams(null)
removeHun(animate = false)
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 84728f6..760bee2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -98,8 +98,6 @@
}
}
- private var animatingScreenOff = false
-
private var collapsedEnoughToHide: Boolean = false
var pulsing: Boolean = false
@@ -236,11 +234,11 @@
}
override fun onDozeAmountChanged(linear: Float, eased: Float) {
- if (overrideDozeAmountIfBypass()) {
+ if (overrideDozeAmountIfAnimatingScreenOff(linear)) {
return
}
- if (overrideDozeAmountIfAnimatingScreenOff(linear)) {
+ if (overrideDozeAmountIfBypass()) {
return
}
@@ -267,7 +265,7 @@
override fun onStateChanged(newState: Int) {
if (unlockedScreenOffAnimationController.shouldPlayScreenOffAnimation()) {
- if (animatingScreenOff &&
+ if (unlockedScreenOffAnimationController.isScreenOffAnimationPlaying() &&
state == StatusBarState.KEYGUARD &&
newState == StatusBarState.SHADE) {
// If we're animating the screen off and going from KEYGUARD back to SHADE, the
@@ -275,12 +273,16 @@
// dozing) so that the notifications are no longer hidden.
setDozeAmount(0f, 0f)
}
-
- animatingScreenOff =
- state == StatusBarState.SHADE && newState == StatusBarState.KEYGUARD
}
- overrideDozeAmountIfBypass()
+ if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) {
+ return
+ }
+
+ if (overrideDozeAmountIfBypass()) {
+ return
+ }
+
if (bypassController.bypassEnabled &&
newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED &&
(!statusBarStateController.isDozing || shouldAnimateVisibility())) {
@@ -330,12 +332,7 @@
* animation. If true, the original doze amount should be ignored.
*/
private fun overrideDozeAmountIfAnimatingScreenOff(linearDozeAmount: Float): Boolean {
- if (animatingScreenOff) {
- if (linearDozeAmount == 1f) {
- animatingScreenOff = false
- return false
- }
-
+ if (unlockedScreenOffAnimationController.isScreenOffAnimationPlaying()) {
setDozeAmount(1f, 1f)
return true
}
@@ -395,11 +392,6 @@
override fun onDozingChanged(isDozing: Boolean) {
if (isDozing) {
setNotificationsVisible(visible = false, animate = false, increaseSpeed = false)
- } else {
- // We only unset the flag once we fully went asleep. If the user interrupts the
- // animation in the middle, we have to abort the animation as well to make sure
- // the notifications are visible again.
- animatingScreenOff = false
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 5f93f480..9f82152 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -179,6 +179,7 @@
private boolean mIsAlerting;
public boolean mRemoteEditImeVisible;
+ private boolean mExpandAnimationRunning;
/**
* @param sbn the StatusBarNotification from system server
@@ -952,6 +953,16 @@
return mIsAlerting;
}
+ /** Set whether this notification is currently used to animate a launch. */
+ public void setExpandAnimationRunning(boolean expandAnimationRunning) {
+ mExpandAnimationRunning = expandAnimationRunning;
+ }
+
+ /** Whether this notification is currently used to animate a launch. */
+ public boolean isExpandAnimationRunning() {
+ return mExpandAnimationRunning;
+ }
+
/** Information about a suggestion that is being edited. */
public static class EditedSuggestionInfo {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index b18f191..4136624 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -61,12 +61,6 @@
private static final float HORIZONTAL_ANIMATION_END = 0.2f;
/**
- * At which point from [0,1] does the alpha animation end (or start when
- * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
- */
- private static final float ALPHA_ANIMATION_END = 0.0f;
-
- /**
* At which point from [0,1] does the horizontal collapse animation start (or start when
* expanding)? 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
*/
@@ -497,10 +491,10 @@
float targetValue;
if (isAppearing) {
- mCurrentAppearInterpolator = mSlowOutFastInInterpolator;
+ mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN;
targetValue = 1.0f;
} else {
- mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN;
+ mCurrentAppearInterpolator = mSlowOutFastInInterpolator;
targetValue = 0.0f;
}
mAppearAnimator = ValueAnimator.ofFloat(mAppearAnimationFraction,
@@ -584,19 +578,21 @@
}
private void updateAppearRect() {
- float inverseFraction = (1.0f - mAppearAnimationFraction);
- float translationFraction = mCurrentAppearInterpolator.getInterpolation(inverseFraction);
- float translateYTotalAmount = translationFraction * mAnimationTranslationY;
- mAppearAnimationTranslation = translateYTotalAmount;
+ float interpolatedFraction = mCurrentAppearInterpolator.getInterpolation(
+ mAppearAnimationFraction);
+ mAppearAnimationTranslation = (1.0f - interpolatedFraction) * mAnimationTranslationY;
final int actualHeight = getActualHeight();
- float bottom = actualHeight * mAppearAnimationFraction;
+ float bottom = actualHeight * interpolatedFraction;
- setOutlineRect(0, mAppearAnimationTranslation,
- getWidth(), bottom + mAppearAnimationTranslation);
+ setOutlineRect(0, mAppearAnimationTranslation, getWidth(),
+ bottom + mAppearAnimationTranslation);
}
- private float getAppearAnimationFraction() {
- return mAppearAnimationFraction >= 0 ? mAppearAnimationFraction : 1;
+ private float getInterpolatedAppearAnimationFraction() {
+ if (mAppearAnimationFraction >= 0) {
+ return mCurrentAppearInterpolator.getInterpolation(mAppearAnimationFraction);
+ }
+ return 1.0f;
}
private void updateAppearAnimationAlpha() {
@@ -629,18 +625,14 @@
@Override
public float getCurrentBackgroundRadiusTop() {
- float fraction = getAppearAnimationFraction();
- return isHeadsUpAnimatingAway() || isHeadsUp()
- ? mOutlineRadius * fraction
- : super.getCurrentBackgroundRadiusTop();
+ float fraction = getInterpolatedAppearAnimationFraction();
+ return MathUtils.lerp(0, super.getCurrentBackgroundRadiusTop(), fraction);
}
@Override
public float getCurrentBackgroundRadiusBottom() {
- float fraction = getAppearAnimationFraction();
- return isHeadsUpAnimatingAway() || isHeadsUp()
- ? mOutlineRadius * fraction
- : super.getCurrentBackgroundRadiusBottom();
+ float fraction = getInterpolatedAppearAnimationFraction();
+ return MathUtils.lerp(0, super.getCurrentBackgroundRadiusBottom(), fraction);
}
private void applyBackgroundRoundness(float topRadius, float bottomRadius) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index 3728388..5134c62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -249,9 +249,18 @@
@Override
public boolean setTopRoundness(float topRoundness, boolean animate) {
if (mTopRoundness != topRoundness) {
+ float diff = Math.abs(topRoundness - mTopRoundness);
mTopRoundness = topRoundness;
+ boolean shouldAnimate = animate;
+ if (PropertyAnimator.isAnimating(this, TOP_ROUNDNESS) && diff > 0.5f) {
+ // Fail safe:
+ // when we've been animating previously and we're now getting an update in the
+ // other direction, make sure to animate it too, otherwise, the localized updating
+ // may make the start larger than 1.0.
+ shouldAnimate = true;
+ }
PropertyAnimator.setProperty(this, TOP_ROUNDNESS, topRoundness,
- ROUNDNESS_PROPERTIES, animate);
+ ROUNDNESS_PROPERTIES, shouldAnimate);
return true;
}
return false;
@@ -286,9 +295,18 @@
@Override
public boolean setBottomRoundness(float bottomRoundness, boolean animate) {
if (mBottomRoundness != bottomRoundness) {
+ float diff = Math.abs(bottomRoundness - mBottomRoundness);
mBottomRoundness = bottomRoundness;
+ boolean shouldAnimate = animate;
+ if (PropertyAnimator.isAnimating(this, BOTTOM_ROUNDNESS) && diff > 0.5f) {
+ // Fail safe:
+ // when we've been animating previously and we're now getting an update in the
+ // other direction, make sure to animate it too, otherwise, the localized updating
+ // may make the start larger than 1.0.
+ shouldAnimate = true;
+ }
PropertyAnimator.setProperty(this, BOTTOM_ROUNDNESS, bottomRoundness,
- ROUNDNESS_PROPERTIES, animate);
+ ROUNDNESS_PROPERTIES, shouldAnimate);
return true;
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 3190927..763d197 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -488,7 +488,8 @@
@Override
public void setLayerType(int layerType, Paint paint) {
- if (hasOverlappingRendering()) {
+ // Allow resetting the layerType to NONE regardless of overlappingRendering
+ if (layerType == LAYER_TYPE_NONE || hasOverlappingRendering()) {
super.setLayerType(layerType, paint);
}
}
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 a189177..0c86262 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
@@ -83,7 +83,7 @@
private ExpandableNotificationRow mTrackedHeadsUpRow;
private float mAppearFraction;
private boolean mIsShadeOpening;
- private float mSectionPadding;
+ private float mOverExpansion;
/** Distance of top of notifications panel from top of screen. */
private float mStackY = 0;
@@ -182,12 +182,12 @@
return mIsShadeOpening;
}
- void setSectionPadding(float padding) {
- mSectionPadding = padding;
+ void setOverExpansion(float overExpansion) {
+ mOverExpansion = overExpansion;
}
- float getSectionPadding() {
- return mSectionPadding;
+ float getOverExpansion() {
+ return mOverExpansion;
}
private static int getZDistanceBetweenElements(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java
deleted file mode 100644
index 24e1f32..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification.stack;
-
-import android.graphics.Path;
-import android.view.animation.PathInterpolator;
-
-/**
- * An interpolator specifically designed for the appear animation of heads up notifications.
- */
-public class HeadsUpAppearInterpolator extends PathInterpolator {
-
- private static float X1 = 250f;
- private static float X2 = 200f;
- private static float XTOT = (X1 + X2);;
-
- public HeadsUpAppearInterpolator() {
- super(getAppearPath());
- }
-
- private static Path getAppearPath() {
- Path path = new Path();
- path.moveTo(0, 0);
- float y1 = 90f;
- float y2 = 80f;
- path.cubicTo(X1 * 0.8f / XTOT, y1 / y2,
- X1 * 0.8f / XTOT, y1 / y2,
- X1 / XTOT, y1 / y2);
- path.cubicTo((X1 + X2 * 0.4f) / XTOT, y1 / y2,
- (X1 + X2 * 0.2f) / XTOT, 1.0f,
- 1.0f , 1.0f);
- return path;
- }
-
- public static float getFractionUntilOvershoot() {
- return X1 / XTOT;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index 4b49e3a..23aefd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -18,7 +18,6 @@
import android.content.res.Resources;
import android.util.MathUtils;
-import android.view.View;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
@@ -199,7 +198,7 @@
mExpanded = expandedHeight != 0.0f;
mAppearFraction = appearFraction;
if (mTrackedHeadsUp != null) {
- updateView(mTrackedHeadsUp, true);
+ updateView(mTrackedHeadsUp, false /* animate */);
}
}
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 64f228f..8277fae 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
@@ -106,6 +106,7 @@
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.ScrollAdapter;
import com.android.systemui.util.Assert;
@@ -119,6 +120,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Named;
@@ -455,6 +457,7 @@
private long mNumHeadsUp;
private NotificationStackScrollLayoutController.TouchHandler mTouchHandler;
private final FeatureFlags mFeatureFlags;
+ private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
private boolean mShouldUseSplitNotificationShade;
private final ExpandableView.OnHeightChangedListener mOnChildHeightChangedListener =
@@ -470,6 +473,7 @@
}
};
+ private Consumer<Integer> mScrollListener;
private final ScrollAdapter mScrollAdapter = new ScrollAdapter() {
@Override
public boolean isScrolledToTop() {
@@ -495,11 +499,13 @@
GroupMembershipManager groupMembershipManager,
GroupExpansionManager groupExpansionManager,
AmbientState ambientState,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
super(context, attrs, 0, 0);
Resources res = getResources();
mSectionsManager = notificationSectionsManager;
mFeatureFlags = featureFlags;
+ mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mShouldUseSplitNotificationShade = shouldUseSplitNotificationShade(mFeatureFlags, res);
mSectionsManager.initialize(this, LayoutInflater.from(context));
mSections = mSectionsManager.createSectionsForBuckets();
@@ -552,8 +558,12 @@
}
}
- void setSectionPadding(float margin) {
- mAmbientState.setSectionPadding(margin);
+ /**
+ * Set the overexpansion of the panel to be applied to the view.
+ */
+ void setOverExpansion(float margin) {
+ mAmbientState.setOverExpansion(margin);
+ updateStackPosition();
requestChildrenUpdate();
}
@@ -600,6 +610,7 @@
RemoteInputController remoteInputController = mRemoteInputManager.getController();
boolean showFooterView = (showDismissView || mController.hasActiveNotifications())
&& mStatusBarState != StatusBarState.KEYGUARD
+ && !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()
&& (remoteInputController == null || !remoteInputController.isRemoteInputActive());
boolean showHistory = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
@@ -1136,7 +1147,8 @@
*/
private void updateStackPosition() {
// Consider interpolating from an mExpansionStartY for use on lockscreen and AOD
- float endTopPosition = mTopPadding + mExtraTopInsetForFullShadeTransition;
+ float endTopPosition = mTopPadding + mExtraTopInsetForFullShadeTransition
+ + mAmbientState.getOverExpansion();
final float fraction = mAmbientState.getExpansionFraction();
final float stackY = MathUtils.lerp(0, endTopPosition, fraction);
mAmbientState.setStackY(stackY);
@@ -1144,7 +1156,6 @@
mOnStackYChanged.run();
}
if (mQsExpansionFraction <= 0) {
- final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mSidePaddings;
final float stackEndHeight = Math.max(0f,
getHeight() - getEmptyBottomMargin() - mTopPadding);
mAmbientState.setStackEndHeight(stackEndHeight);
@@ -1166,7 +1177,7 @@
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
public void setExpandedHeight(float height) {
final float shadeBottom = getHeight() - getEmptyBottomMargin();
- final float expansionFraction = MathUtils.constrain(height / shadeBottom, 0f, 1f);
+ final float expansionFraction = MathUtils.saturate(height / shadeBottom);
mAmbientState.setExpansionFraction(expansionFraction);
updateStackPosition();
@@ -2091,11 +2102,13 @@
if (height != 0) {
height += mPaddingBetweenElements;
}
- height += calculateGapHeight(previousView, expandableView, numShownItems);
+ float gapHeight = calculateGapHeight(previousView, expandableView, numShownNotifs);
+ height += gapHeight;
height += viewHeight;
numShownItems++;
- if (!(expandableView instanceof MediaHeaderView)) {
+ if (viewHeight > 0 || !(expandableView instanceof MediaHeaderView)) {
+ // Only count the media as a notification if it has a positive height.
numShownNotifs++;
}
previousView = expandableView;
@@ -2395,8 +2408,8 @@
float topOverScroll = getCurrentOverScrollAmount(true);
return mScrolledToTopOnFirstDown
&& !mExpandedInThisMotion
- && topOverScroll > mMinTopOverScrollToEscape
- && initialVelocity > 0;
+ && (initialVelocity > mMinimumVelocity
+ || (topOverScroll > mMinTopOverScrollToEscape && initialVelocity > 0));
}
/**
@@ -4552,6 +4565,9 @@
}
private void updateOnScrollChange() {
+ if (mScrollListener != null) {
+ mScrollListener.accept(mOwnScrollY);
+ }
updateForwardAndBackwardScrollability();
requestChildrenUpdate();
}
@@ -4606,7 +4622,7 @@
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@VisibleForTesting
- protected void setStatusBarState(int statusBarState) {
+ public void setStatusBarState(int statusBarState) {
mStatusBarState = statusBarState;
mAmbientState.setStatusBarState(statusBarState);
updateSpeedBumpIndex();
@@ -5163,6 +5179,13 @@
}
/**
+ * Set a listener to when scrolling changes.
+ */
+ public void setOnScrollListener(Consumer<Integer> listener) {
+ mScrollListener = listener;
+ }
+
+ /**
* A listener that is notified when the empty space below the notifications is clicked on
*/
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
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 4432f54..dec9888 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
@@ -124,6 +124,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Named;
@@ -302,8 +303,11 @@
}
};
- public void setSectionPadding(float padding) {
- mView.setSectionPadding(padding);
+ /**
+ * Set the overexpansion of the panel to be applied to the view.
+ */
+ public void setOverExpansion(float overExpansion) {
+ mView.setOverExpansion(overExpansion);
}
private final OnMenuEventListener mMenuEventListener = new OnMenuEventListener() {
@@ -544,7 +548,11 @@
@Override
public void onHeadsUpUnPinned(NotificationEntry entry) {
- mNotificationRoundnessManager.updateView(entry.getRow(), true /* animate */);
+ ExpandableNotificationRow row = entry.getRow();
+ // update the roundedness posted, because we might be animating away the
+ // headsup soon, so no need to set the roundedness to 0 and then back to 1.
+ row.post(() -> mNotificationRoundnessManager.updateView(row,
+ true /* animate */));
}
@Override
@@ -553,7 +561,9 @@
NotificationEntry topEntry = mHeadsUpManager.getTopEntry();
mView.setNumHeadsUp(numEntries);
mView.setTopHeadsUpEntry(topEntry);
- mNotificationRoundnessManager.updateView(entry.getRow(), false /* animate */);
+ generateHeadsUpAnimation(entry, isHeadsUp);
+ ExpandableNotificationRow row = entry.getRow();
+ mNotificationRoundnessManager.updateView(row, true /* animate */);
}
};
@@ -944,10 +954,6 @@
mView.setOverScrollAmount(amount, onTop, animate);
}
- public void setOverScrolledPixels(float numPixels, boolean onTop, boolean animate) {
- mView.setOverScrolledPixels(numPixels, onTop, animate);
- }
-
public void resetScrollPosition() {
mView.resetScrollPosition();
}
@@ -1054,10 +1060,6 @@
return mView.getCurrentOverScrollAmount(top);
}
- public float getCurrentOverScrolledPixels(boolean top) {
- return mView.getCurrentOverScrolledPixels(top);
- }
-
public float calculateAppearFraction(float height) {
return mView.calculateAppearFraction(height);
}
@@ -1238,7 +1240,7 @@
return mView.getFirstChildNotGone();
}
- public void generateHeadsUpAnimation(NotificationEntry entry, boolean isHeadsUp) {
+ private void generateHeadsUpAnimation(NotificationEntry entry, boolean isHeadsUp) {
mView.generateHeadsUpAnimation(entry, isHeadsUp);
}
@@ -1431,6 +1433,13 @@
}
/**
+ * Set a listener to when scrolling changes.
+ */
+ public void setOnScrollListener(Consumer<Integer> listener) {
+ mView.setOnScrollListener(listener);
+ }
+
+ /**
* Enum for UiEvent logged from this class
*/
enum NotificationPanelEvent implements UiEventLogger.UiEventEnum {
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 63c5c80..a02ebbf 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
@@ -403,10 +403,6 @@
}
viewState.yTranslation = algorithmState.mCurrentYPosition;
- if (view instanceof SectionHeaderView) {
- // Add padding before sections for overscroll effect.
- viewState.yTranslation += expansionFraction * ambientState.getSectionPadding();
- }
if (view instanceof FooterView) {
final boolean shadeClosed = !ambientState.isShadeExpanded();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 83dc6df..4fd2064 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -21,7 +21,6 @@
import android.animation.ValueAnimator;
import android.util.Property;
import android.view.View;
-import android.view.animation.Interpolator;
import com.android.keyguard.KeyguardSliceView;
import com.android.systemui.R;
@@ -50,11 +49,8 @@
public static final int ANIMATION_DURATION_SWIPE = 260;
public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220;
public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150;
- public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 550;
- public static final int ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED
- = (int) (ANIMATION_DURATION_HEADS_UP_APPEAR
- * HeadsUpAppearInterpolator.getFractionUntilOvershoot());
- public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 300;
+ public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 400;
+ public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 400;
public static final int ANIMATION_DURATION_PULSE_APPEAR =
KeyguardSliceView.DEFAULT_ANIM_DURATION;
public static final int ANIMATION_DURATION_BLOCKING_HELPER_FADE = 240;
@@ -64,8 +60,6 @@
public static final int ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE = 48;
public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
private static final int MAX_STAGGER_COUNT = 5;
- private static final HeadsUpAppearInterpolator HEADS_UP_APPEAR_INTERPOLATOR =
- new HeadsUpAppearInterpolator();
private final int mGoToFullShadeAppearingTranslation;
private final int mPulsingAppearingTranslation;
@@ -115,14 +109,6 @@
public boolean wasAdded(View view) {
return mNewAddChildren.contains(view);
}
-
- @Override
- public Interpolator getCustomInterpolator(View child, Property property) {
- if (mHeadsUpAppearChildren.contains(child) && View.TRANSLATION_Y.equals(property)) {
- return HEADS_UP_APPEAR_INTERPOLATOR;
- }
- return null;
- }
};
}
@@ -422,7 +408,7 @@
if (event.headsUpFromBottom) {
mTmpState.yTranslation = mHeadsUpAppearHeightBottom;
} else {
- changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED,
+ changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR,
true /* isHeadsUpAppear */);
}
mHeadsUpAppearChildren.add(changingView);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index df86e20..6d82a45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -591,7 +591,7 @@
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- HeadsUpUtil.setIsClickedHeadsUpNotification(child, false);
+ HeadsUpUtil.setNeedsHeadsUpDisappearAnimationAfterClick(child, false);
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
child.setTag(TAG_START_TRANSLATION_Y, null);
child.setTag(TAG_END_TRANSLATION_Y, null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 4d8e7de3..8e3aed4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -368,8 +368,8 @@
updateLeftAffordanceIcon();
lp = mWalletButton.getLayoutParams();
- lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
- lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
+ lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_wallet_width);
+ lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_wallet_width);
mWalletButton.setLayoutParams(lp);
mIndicationPadding = getResources().getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index c911e3d..b5e550a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -83,9 +83,13 @@
private final Runnable mRemoveViewRunnable = this::removeView;
private final KeyguardBypassController mKeyguardBypassController;
private KeyguardHostViewController mKeyguardViewController;
+ private final List<KeyguardResetCallback> mResetCallbacks = new ArrayList<>();
private final Runnable mResetRunnable = ()-> {
if (mKeyguardViewController != null) {
mKeyguardViewController.resetSecurityContainer();
+ for (KeyguardResetCallback callback : mResetCallbacks) {
+ callback.onKeyguardReset();
+ }
}
};
@@ -284,10 +288,19 @@
public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
ensureView();
- mKeyguardViewController.setOnDismissAction(r, cancelAction);
+ setDismissAction(r, cancelAction);
show(false /* resetSecuritySelection */);
}
+ /**
+ * Set the actions to run when the keyguard is dismissed or when the dismiss is cancelled. Those
+ * actions will still be run even if this bouncer is not shown, for instance when authenticating
+ * with an alternate authenticator like the UDFPS.
+ */
+ public void setDismissAction(OnDismissAction r, Runnable cancelAction) {
+ mKeyguardViewController.setOnDismissAction(r, cancelAction);
+ }
+
public void hide(boolean destroyView) {
if (isShowing()) {
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
@@ -573,6 +586,14 @@
}
}
+ public void addKeyguardResetCallback(KeyguardResetCallback callback) {
+ mResetCallbacks.add(callback);
+ }
+
+ public void removeKeyguardResetCallback(KeyguardResetCallback callback) {
+ mResetCallbacks.remove(callback);
+ }
+
public interface BouncerExpansionCallback {
void onFullyShown();
void onStartingToHide();
@@ -593,6 +614,10 @@
default void onVisibilityChanged(boolean isVisible) {}
}
+ public interface KeyguardResetCallback {
+ void onKeyguardReset();
+ }
+
/** Create a {@link KeyguardBouncer} once a container and bouncer callback are available. */
public static class Factory {
private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 7c2723d..3e4177d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -24,7 +24,6 @@
import android.util.MathUtils;
import com.android.keyguard.KeyguardStatusView;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherListView;
@@ -64,11 +63,6 @@
private int mUserSwitchHeight;
/**
- * Preferred Y position of clock.
- */
- private int mClockPreferredY;
-
- /**
* Preferred Y position of user avatar used by the multi-user switcher.
*/
private int mUserSwitchPreferredY;
@@ -153,8 +147,6 @@
*/
private int mUnlockedStackScrollerPadding;
- private int mLockScreenMode;
-
private boolean mIsSplitShade;
/**
@@ -179,8 +171,8 @@
*/
public void setup(int keyguardStatusBarHeaderHeight, int maxShadeBottom,
int notificationStackHeight, float panelExpansion, int parentHeight,
- int keyguardStatusHeight, int userSwitchHeight, int clockPreferredY,
- int userSwitchPreferredY, boolean hasCustomClock, boolean hasVisibleNotifs, float dark,
+ int keyguardStatusHeight, int userSwitchHeight, int userSwitchPreferredY,
+ boolean hasCustomClock, boolean hasVisibleNotifs, float dark,
float overStrechAmount, boolean bypassEnabled, int unlockedStackScrollerPadding,
float qsExpansion, int cutoutTopInset, boolean isSplitShade) {
mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding,
@@ -191,7 +183,6 @@
mHeight = parentHeight;
mKeyguardStatusHeight = keyguardStatusHeight;
mUserSwitchHeight = userSwitchHeight;
- mClockPreferredY = clockPreferredY;
mUserSwitchPreferredY = userSwitchPreferredY;
mHasCustomClock = hasCustomClock;
mHasVisibleNotifs = hasVisibleNotifs;
@@ -228,13 +219,6 @@
}
}
- /**
- * Update lock screen mode for testing different layouts
- */
- public void onLockScreenModeChanged(int mode) {
- mLockScreenMode = mode;
- }
-
public float getMinStackScrollerPadding() {
return mBypassEnabled ? mUnlockedStackScrollerPadding
: mMinTopMargin + mKeyguardStatusHeight + mClockNotificationsMargin;
@@ -245,11 +229,7 @@
}
private int getExpandedPreferredClockY() {
- if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
- return mMinTopMargin + mUserSwitchHeight;
- }
- return (mHasCustomClock && (!mHasVisibleNotifs || mBypassEnabled)) ? mClockPreferredY
- : getExpandedClockPosition();
+ return mMinTopMargin + mUserSwitchHeight;
}
/**
@@ -278,29 +258,20 @@
}
private int getClockY(float panelExpansion, float darkAmount) {
- // Dark: Align the bottom edge of the clock at about half of the screen:
- float clockYDark = (mHasCustomClock ? mClockPreferredY : getMaxClockY())
- + burnInPreventionOffsetY();
- clockYDark = MathUtils.max(0, clockYDark);
-
float clockYRegular = getExpandedPreferredClockY();
float clockYBouncer = -mKeyguardStatusHeight;
// Move clock up while collapsing the shade
float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(panelExpansion);
float clockY = MathUtils.lerp(clockYBouncer, clockYRegular, shadeExpansion);
- clockYDark = MathUtils.lerp(clockYBouncer, clockYDark, shadeExpansion);
- darkAmount = mBypassEnabled && !mHasCustomClock ? 1.0f : darkAmount;
-
- if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
- // This will keep the clock at the top but out of the cutout area
- float shift = 0;
- if (clockY - mBurnInPreventionOffsetYLargeClock < mCutoutTopInset) {
- shift = mCutoutTopInset - (clockY - mBurnInPreventionOffsetYLargeClock);
- }
- clockYDark = clockY + burnInPreventionOffsetY() + shift;
+ // This will keep the clock at the top but out of the cutout area
+ float shift = 0;
+ if (clockY - mBurnInPreventionOffsetYLargeClock < mCutoutTopInset) {
+ shift = mCutoutTopInset - (clockY - mBurnInPreventionOffsetYLargeClock);
}
+ float clockYDark = clockY + burnInPreventionOffsetY() + shift;
+
return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mOverStretchAmount);
}
@@ -333,19 +304,12 @@
}
private float burnInPreventionOffsetY() {
- int offset = mBurnInPreventionOffsetY;
- if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
- offset = mBurnInPreventionOffsetYLargeClock;
- }
+ int offset = mBurnInPreventionOffsetYLargeClock;
return getBurnInOffset(offset * 2, false /* xAxis */) - offset;
}
private float burnInPreventionOffsetX() {
- if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
- return getBurnInOffset(mBurnInPreventionOffsetX * 2, true /* xAxis */)
- - mBurnInPreventionOffsetX;
- }
return getBurnInOffset(mBurnInPreventionOffsetX, true /* xAxis */);
}
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 dc71c10..b3569d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -139,6 +139,7 @@
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
+import com.android.systemui.statusbar.notification.stack.MediaHeaderView;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
@@ -253,12 +254,6 @@
new KeyguardUpdateMonitorCallback() {
@Override
- public void onLockScreenModeChanged(int mode) {
- mLockScreenMode = mode;
- mClockPositionAlgorithm.onLockScreenModeChanged(mode);
- }
-
- @Override
public void onBiometricAuthenticated(int userId,
BiometricSourceType biometricSourceType,
boolean isStrongBiometric) {
@@ -328,7 +323,7 @@
private KeyguardStatusBarView mKeyguardStatusBar;
private KeyguardStatusBarViewController mKeyguarStatusBarViewController;
private ViewGroup mBigClockContainer;
- private QS mQs;
+ @VisibleForTesting QS mQs;
private FrameLayout mQsFrame;
private KeyguardStatusViewController mKeyguardStatusViewController;
private LockIconViewController mLockIconViewController;
@@ -367,7 +362,9 @@
private boolean mStackScrollerOverscrolling;
private boolean mQsExpansionFromOverscroll;
private float mLastOverscroll;
- private boolean mQsExpansionEnabled = true;
+ private boolean mQsExpansionEnabledPolicy = true;
+ private boolean mQsExpansionEnabledAmbient = true;
+ private boolean mQsExpansionEnabled = mQsExpansionEnabledPolicy && mQsExpansionEnabledAmbient;
private ValueAnimator mQsExpansionAnimator;
private FlingAnimationUtils mFlingAnimationUtils;
private int mStatusBarMinHeight;
@@ -510,7 +507,6 @@
private boolean mShowingKeyguardHeadsUp;
private boolean mAllowExpandForSmallExpansion;
private Runnable mExpandAfterLayoutRunnable;
- private float mSectionPadding;
/**
* The padding between the start of notifications and the qs boundary on the lockscreen.
@@ -589,13 +585,11 @@
private NotificationShelfController mNotificationShelfController;
private int mScrimCornerRadius;
private int mScreenCornerRadius;
- private int mNotificationScrimPadding;
private boolean mQSAnimatingHiddenFromCollapsed;
private final Executor mUiExecutor;
private final SecureSettings mSecureSettings;
- private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
private KeyguardMediaController mKeyguardMediaController;
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
@@ -824,6 +818,7 @@
mOnHeightChangedListener);
mNotificationStackScrollLayoutController.setOverscrollTopChangedListener(
mOnOverscrollTopChangedListener);
+ mNotificationStackScrollLayoutController.setOnScrollListener(this::onNotificationScrolled);
mNotificationStackScrollLayoutController.setOnEmptySpaceClickListener(
mOnEmptySpaceClickListener);
addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp);
@@ -908,8 +903,6 @@
mScrimCornerRadius = mResources.getDimensionPixelSize(
R.dimen.notification_scrim_corner_radius);
mScreenCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(mResources);
- mNotificationScrimPadding = mResources.getDimensionPixelSize(
- R.dimen.notification_side_paddings);
mLockscreenNotificationQSPadding = mResources.getDimensionPixelSize(
R.dimen.notification_side_paddings);
}
@@ -1129,10 +1122,7 @@
mKeyguardBottomArea.setStatusBar(mStatusBar);
mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete);
mKeyguardBottomArea.setFalsingManager(mFalsingManager);
-
- if (mFeatureFlags.isQuickAccessWalletEnabled()) {
- mKeyguardBottomArea.initWallet(mQuickAccessWalletController);
- }
+ mKeyguardBottomArea.initWallet(mQuickAccessWalletController);
}
private void updateMaxDisplayedNotifications(boolean recompute) {
@@ -1240,7 +1230,6 @@
private void updateClockAppearance() {
int totalHeight = mView.getHeight();
int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
- int clockPreferredY = mKeyguardStatusViewController.getClockPreferredY(totalHeight);
int userSwitcherPreferredY = mStatusBarHeaderHeightKeyguard;
boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
final boolean hasVisibleNotifications = mNotificationStackScrollLayoutController
@@ -1259,12 +1248,9 @@
mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
expandedFraction,
totalHeight,
- mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1
- ? mKeyguardStatusViewController.getHeight()
- : (int) (mKeyguardStatusViewController.getHeight()
- - mShelfHeight / 2.0f - mDarkIconSize / 2.0f),
+ mKeyguardStatusViewController.getHeight(),
userIconHeight,
- clockPreferredY, userSwitcherPreferredY, hasCustomClock(),
+ userSwitcherPreferredY, hasCustomClock(),
hasVisibleNotifications, darkamount, mOverStretchAmount,
bypassEnabled, getUnlockedStackScrollerPadding(),
computeQsExpansionFraction(),
@@ -1325,28 +1311,33 @@
mNotificationStackScrollLayoutController.getHeight()
- minPadding
- shelfSize
- - bottomPadding
- - mKeyguardStatusViewController.getLogoutButtonHeight();
+ - bottomPadding;
int count = 0;
ExpandableView previousView = null;
for (int i = 0; i < mNotificationStackScrollLayoutController.getChildCount(); i++) {
ExpandableView child = mNotificationStackScrollLayoutController.getChildAt(i);
- if (!(child instanceof ExpandableNotificationRow)) {
- continue;
- }
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- boolean
- suppressedSummary =
- mGroupManager != null && mGroupManager.isSummaryOfSuppressedGroup(
- row.getEntry().getSbn());
- if (suppressedSummary) {
- continue;
- }
- if (!canShowViewOnLockscreen(child)) {
- continue;
- }
- if (row.isRemoved()) {
+ if (child instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ boolean suppressedSummary = mGroupManager != null
+ && mGroupManager.isSummaryOfSuppressedGroup(row.getEntry().getSbn());
+ if (suppressedSummary) {
+ continue;
+ }
+ if (!canShowViewOnLockscreen(child)) {
+ continue;
+ }
+ if (row.isRemoved()) {
+ continue;
+ }
+ } else if (child instanceof MediaHeaderView) {
+ if (child.getVisibility() == GONE) {
+ continue;
+ }
+ if (child.getIntrinsicHeight() == 0) {
+ continue;
+ }
+ } else {
continue;
}
availableSpace -= child.getMinHeight(true /* ignoreTemporaryStates */);
@@ -1438,10 +1429,16 @@
mAnimateNextPositionUpdate = true;
}
- public void setQsExpansionEnabled(boolean qsExpansionEnabled) {
- mQsExpansionEnabled = qsExpansionEnabled;
+ private void setQsExpansionEnabled() {
+ mQsExpansionEnabled = mQsExpansionEnabledPolicy && mQsExpansionEnabledAmbient;
+ Log.d(TAG, "Set qsExpansionEnabled: " + mQsExpansionEnabled);
if (mQs == null) return;
- mQs.setHeaderClickable(qsExpansionEnabled);
+ mQs.setHeaderClickable(mQsExpansionEnabled);
+ }
+
+ public void setQsExpansionEnabledPolicy(boolean qsExpansionEnabledPolicy) {
+ mQsExpansionEnabledPolicy = qsExpansionEnabledPolicy;
+ setQsExpansionEnabled();
}
@Override
@@ -2190,6 +2187,24 @@
}
};
+ private void onNotificationScrolled(int newScrollPosition) {
+ // Since this is an overscroller, sometimes the scrollY can be temporarily negative
+ // (when overscrollng on the top and flinging). Let's
+ updateQSExpansionEnabledAmbient();
+ }
+
+ @Override
+ public void setIsShadeOpening(boolean opening) {
+ mAmbientState.setIsShadeOpening(opening);
+ updateQSExpansionEnabledAmbient();
+ }
+
+ private void updateQSExpansionEnabledAmbient() {
+ mQsExpansionEnabledAmbient =
+ mAmbientState.getScrollY() <= 0 && !mAmbientState.isShadeOpening();
+ setQsExpansionEnabled();
+ }
+
/**
* Updates scrim bounds, QS clipping, and KSV clipping as well based on the bounds of the shade
* and QS state.
@@ -2203,7 +2218,6 @@
final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction());
final boolean visible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0)
&& !mShouldUseSplitNotificationShade;
- setQsExpansionEnabled(mAmbientState.getScrollY() == 0 && !mAmbientState.isShadeOpening());
if (!mShouldUseSplitNotificationShade) {
if (mTransitioningToFullShadeProgress > 0.0f) {
@@ -2221,6 +2235,7 @@
left = 0;
right = getView().getRight() + mDisplayRightInset;
} else if (qsPanelBottomY > 0) { // so bounds are empty on lockscreen
+ mAmbientState.setNotificationScrimTop(mSplitShadeNotificationsTopPadding);
top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding);
bottom = mNotificationStackScrollLayoutController.getHeight();
left = mNotificationStackScrollLayoutController.getLeft();
@@ -2315,8 +2330,6 @@
qsBottomY = (int) MathUtils.lerp(
qsBottomY, mQs.getDesiredHeight(), qsExpansionFraction);
}
- // to account for shade overshooting animation, see setSectionPadding method
- if (mSectionPadding > 0) qsBottomY += mSectionPadding;
return qsBottomY;
}
}
@@ -2521,7 +2534,9 @@
break;
case FLING_HIDE:
default:
- mQs.closeDetail();
+ if (mQs != null) {
+ mQs.closeDetail();
+ }
target = 0;
}
if (target == mQsExpansionHeight) {
@@ -2632,7 +2647,7 @@
int min = mStatusBarMinHeight;
if (!(mBarState == KEYGUARD)
&& mNotificationStackScrollLayoutController.getNotGoneChildCount() == 0) {
- int minHeight = (int) (mQsMinExpansionHeight + getOverExpansionAmount());
+ int minHeight = mQsMinExpansionHeight;
min = Math.max(min, minHeight);
}
int maxHeight;
@@ -2644,8 +2659,8 @@
}
maxHeight = Math.max(min, maxHeight);
if (maxHeight == 0 || isNaN(maxHeight)) {
- Log.wtf(TAG, "maxPanelHeight is invalid. getOverExpansionAmount(): "
- + getOverExpansionAmount() + ", calculatePanelHeightQsExpanded: "
+ Log.wtf(TAG, "maxPanelHeight is invalid. mOverExpansion: "
+ + mOverExpansion + ", calculatePanelHeightQsExpanded: "
+ calculatePanelHeightQsExpanded() + ", calculatePanelHeightShade: "
+ calculatePanelHeightShade() + ", mStatusBarMinHeight = "
+ mStatusBarMinHeight + ", mQsMinExpansionHeight = " + mQsMinExpansionHeight);
@@ -2807,23 +2822,6 @@
return alpha;
}
- @Override
- protected float getOverExpansionAmount() {
- float result = mNotificationStackScrollLayoutController
- .getCurrentOverScrollAmount(true /* top */);
- if (isNaN(result)) {
- Log.wtf(TAG, "OverExpansionAmount is NaN!");
- }
-
- return result;
- }
-
- @Override
- protected float getOverExpansionPixels() {
- return mNotificationStackScrollLayoutController
- .getCurrentOverScrolledPixels(true /* top */);
- }
-
/**
* Hides the header when notifications are colliding with it.
*/
@@ -3018,31 +3016,15 @@
}
@Override
- public void setSectionPadding(float padding) {
- if (padding == mSectionPadding) {
+ public void setOverExpansion(float overExpansion) {
+ if (overExpansion == mOverExpansion) {
return;
}
- mSectionPadding = padding;
- // TODO(b/172289889) update overscroll to spec
- }
-
- @Override
- protected void setOverExpansion(float overExpansion, boolean isPixels) {
- if (mConflictingQsExpansionGesture || mQsExpandImmediate) {
- return;
- }
- if (mBarState != KEYGUARD) {
- mNotificationStackScrollLayoutController.setOnHeightChangedListener(null);
- if (isPixels) {
- mNotificationStackScrollLayoutController.setOverScrolledPixels(
- overExpansion, true /* onTop */, false /* animate */);
- } else {
- mNotificationStackScrollLayoutController.setOverScrollAmount(
- overExpansion, true /* onTop */, false /* animate */);
- }
- mNotificationStackScrollLayoutController
- .setOnHeightChangedListener(mOnHeightChangedListener);
- }
+ super.setOverExpansion(overExpansion);
+ // Translating the quick settings by half the overexpansion to center it in the background
+ // frame
+ mQsFrame.setTranslationY(overExpansion / 2f);
+ mNotificationStackScrollLayoutController.setOverExpansion(overExpansion);
}
@Override
@@ -3066,7 +3048,7 @@
mFalsingCollector.onTrackingStopped();
super.onTrackingStopped(expand);
if (expand) {
- mNotificationStackScrollLayoutController.setOverScrolledPixels(0.0f, true /* onTop */,
+ mNotificationStackScrollLayoutController.setOverScrollAmount(0.0f, true /* onTop */,
true /* animate */);
}
mNotificationStackScrollLayoutController.onPanelTrackingStopped();
@@ -3112,18 +3094,6 @@
}
@Override
- protected boolean fullyExpandedClearAllVisible() {
- return mNotificationStackScrollLayoutController.isFooterViewNotGone()
- && mNotificationStackScrollLayoutController.isScrolledToBottom()
- && !mQsExpandImmediate;
- }
-
- @Override
- protected boolean isClearAllVisible() {
- return mNotificationStackScrollLayoutController.isFooterViewContentVisible();
- }
-
- @Override
protected boolean isTrackingBlocked() {
return mConflictingQsExpansionGesture && mQsExpanded || mBlockingExpansionForCurrentTouch;
}
@@ -3626,11 +3596,6 @@
* security view of the bouncer.
*/
public void onBouncerPreHideAnimation() {
- mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
- mBarState,
- true /* keyguardFadingAway */,
- false /* goingToFullShade */,
- mBarState);
if (mKeyguardQsUserSwitchController != null) {
mKeyguardQsUserSwitchController.setKeyguardQsUserSwitchVisibility(
mBarState,
@@ -3973,10 +3938,15 @@
}
mLastOverscroll = 0f;
mQsExpansionFromOverscroll = false;
+ if (open) {
+ // During overscrolling, qsExpansion doesn't actually change that the qs is
+ // becoming expanded. Any layout could therefore reset the position again. Let's
+ // make sure we can expand
+ setOverScrolling(false);
+ }
setQsExpansion(mQsExpansionHeight);
flingSettings(!mQsExpansionEnabled && open ? 0f : velocity,
open && mQsExpansionEnabled ? FLING_EXPAND : FLING_COLLAPSE, () -> {
- mStackScrollerOverscrolling = false;
setOverScrolling(false);
updateQsState();
}, false /* isClick */);
@@ -4182,11 +4152,6 @@
entry.setHeadsUpIsVisible();
}
}
-
- @Override
- public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
- mNotificationStackScrollLayoutController.generateHeadsUpAnimation(entry, isHeadsUp);
- }
}
private class HeightListener implements QS.HeightListener {
@@ -4314,7 +4279,8 @@
/**
* Reconfigures the shade to show the AOD UI (clock, smartspace, etc). This is called by the
* screen off animation controller in order to animate in AOD without "actually" fully switching
- * to the KEYGUARD state.
+ * to the KEYGUARD state, which is a heavy transition that causes jank as 10+ files react to the
+ * change.
*/
public void showAodUi() {
setDozing(true /* dozing */, false /* animate */, null);
@@ -4392,7 +4358,7 @@
if (mQsMaxExpansionHeight != oldMaxHeight) {
startQsSizeChangeAnimation(oldMaxHeight, mQsMaxExpansionHeight);
}
- } else if (!mQsExpanded) {
+ } else if (!mQsExpanded && mQsExpansionAnimator == null) {
setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
}
updateExpandedHeight(getExpandedHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 64e2c1c..f1b6c7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -53,7 +53,7 @@
if (DEBUG) LOG("go state: %d -> %d", mState, state);
mState = state;
if (mPanel != null) {
- mPanel.getAmbientState().setIsShadeOpening(state == STATE_OPENING);
+ mPanel.setIsShadeOpening(state == STATE_OPENING);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 798e895..323a112 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -68,12 +68,14 @@
public static final String TAG = PanelView.class.getSimpleName();
private static final int NO_FIXED_DURATION = -1;
private static final long SHADE_OPEN_SPRING_OUT_DURATION = 350L;
- private static final long SHADE_OPEN_SPRING_BACK_DURATION = 200L;
- private static final float MIN_OVERSCROLL = -50;
- private static final float MAX_OVERSCROLL = 30;
+ private static final long SHADE_OPEN_SPRING_BACK_DURATION = 400L;
- private float mFlingTarget;
- private float mFlingVelocity;
+ /**
+ * The factor of the usual high velocity that is needed in order to reach the maximum overshoot
+ * when flinging. A low value will make it that most flings will reach the maximum overshoot.
+ */
+ private static final float FACTOR_OF_HIGH_VELOCITY_FOR_MAX_OVERSHOOT = 0.5f;
+
protected long mDownTime;
protected boolean mTouchSlopExceededBeforeDown;
private float mMinExpandHeight;
@@ -83,6 +85,22 @@
protected boolean mIsLaunchAnimationRunning;
private int mFixedDuration = NO_FIXED_DURATION;
protected ArrayList<PanelExpansionListener> mExpansionListeners = new ArrayList<>();
+ protected float mOverExpansion;
+
+ /**
+ * The overshoot amount when the panel flings open
+ */
+ private float mPanelFlingOvershootAmount;
+
+ /**
+ * The amount of pixels that we have overexpanded the last time with a gesture
+ */
+ private float mLastGesturedOverExpansion = -1;
+
+ /**
+ * Is the current animator the spring back animation?
+ */
+ private boolean mIsSpringBackAnimation;
private void logf(String fmt, Object... args) {
Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
@@ -254,6 +272,7 @@
mTouchSlop = configuration.getScaledTouchSlop();
mSlopMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
mHintDistance = mResources.getDimension(R.dimen.hint_move_distance);
+ mPanelFlingOvershootAmount = mResources.getDimension(R.dimen.panel_overshoot_amount);
mUnlockFalsingThreshold = mResources.getDimensionPixelSize(
R.dimen.unlock_falsing_threshold);
}
@@ -529,21 +548,38 @@
protected void flingToHeight(float vel, boolean expand, float target,
float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
- if (target == mExpandedHeight || getOverExpansionAmount() > 0f && expand) {
+ if (target == mExpandedHeight && mOverExpansion == 0.0f) {
+ // We're at the target and didn't fling and there's no overshoot
endJankMonitoring(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
mKeyguardStateController.notifyPanelFlingEnd();
notifyExpandingFinished();
return;
}
mIsFlinging = true;
- mOverExpandedBeforeFling = getOverExpansionAmount() > 0f;
- ValueAnimator animator = createHeightAnimator(target);
- mFlingTarget = target;
+ // we want to perform an overshoot animation when flinging open
+ final boolean addOverscroll = expand
+ && mStatusBarStateController.getState() != StatusBarState.KEYGUARD
+ && mOverExpansion == 0.0f
+ && vel >= 0;
+ final boolean shouldSpringBack = addOverscroll || (mOverExpansion != 0.0f && expand);
+ float overshootAmount = 0.0f;
+ if (addOverscroll) {
+ // Let's overshoot depending on the amount of velocity
+ overshootAmount = MathUtils.lerp(
+ 0.2f,
+ 1.0f,
+ MathUtils.saturate(vel
+ / (mFlingAnimationUtils.getHighVelocityPxPerSecond()
+ * FACTOR_OF_HIGH_VELOCITY_FOR_MAX_OVERSHOOT)));
+ overshootAmount += mOverExpansion / mPanelFlingOvershootAmount;
+ }
+ ValueAnimator animator = createHeightAnimator(target, overshootAmount);
if (expand) {
if (expandBecauseOfFalsing && vel < 0) {
vel = 0;
}
- mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, mView.getHeight());
+ mFlingAnimationUtils.apply(animator, mExpandedHeight,
+ target + overshootAmount * mPanelFlingOvershootAmount, vel, mView.getHeight());
if (vel == 0) {
animator.setDuration(SHADE_OPEN_SPRING_OUT_DURATION);
}
@@ -570,7 +606,6 @@
animator.setDuration(mFixedDuration);
}
}
- mFlingVelocity = vel;
animator.addListener(new AnimatorListenerAdapter() {
private boolean mCancelled;
@@ -586,7 +621,7 @@
@Override
public void onAnimationEnd(Animator animation) {
- if (expand && mFlingVelocity > 0) {
+ if (shouldSpringBack && !mCancelled) {
// After the shade is flinged open to an overscrolled state, spring back
// the shade by reducing section padding to 0.
springBack();
@@ -600,14 +635,19 @@
}
private void springBack() {
- ValueAnimator animator = ValueAnimator.ofFloat(MAX_OVERSCROLL, 0);
+ if (mOverExpansion == 0) {
+ onFlingEnd(false /* cancelled */);
+ return;
+ }
+ mIsSpringBackAnimation = true;
+ ValueAnimator animator = ValueAnimator.ofFloat(mOverExpansion, 0);
animator.addUpdateListener(
animation -> {
- setSectionPadding((float) animation.getAnimatedValue());
- setExpandedHeightInternal(mFlingTarget);
+ setOverExpansionInternal((float) animation.getAnimatedValue(),
+ false /* isFromGesture */);
});
animator.setDuration(SHADE_OPEN_SPRING_BACK_DURATION);
- animator.setInterpolator(Interpolators.LINEAR);
+ animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
animator.addListener(new AnimatorListenerAdapter() {
private boolean mCancelled;
@Override
@@ -616,6 +656,7 @@
}
@Override
public void onAnimationEnd(Animator animation) {
+ mIsSpringBackAnimation = false;
onFlingEnd(mCancelled);
}
});
@@ -625,6 +666,8 @@
private void onFlingEnd(boolean cancelled) {
mIsFlinging = false;
+ // No overshoot when the animation ends
+ setOverExpansionInternal(0, false /* isFromGesture */);
setAnimator(null);
mKeyguardStateController.notifyPanelFlingEnd();
if (!cancelled) {
@@ -644,7 +687,7 @@
public void setExpandedHeight(float height) {
if (DEBUG) logf("setExpandedHeight(%.1f)", height);
- setExpandedHeightInternal(height + getOverExpansionPixels());
+ setExpandedHeightInternal(height);
}
protected void requestPanelHeightUpdate() {
@@ -662,7 +705,7 @@
return;
}
- if (mHeightAnimator != null) {
+ if (mHeightAnimator != null && !mIsSpringBackAnimation) {
mPanelUpdateWhenAnimatorEnds = true;
return;
}
@@ -677,38 +720,24 @@
return stackHeightFraction;
}
- // When the shade is flinged open, add space before sections for overscroll effect.
- private void maybeOverScrollForShadeFlingOpen(float height) {
- if (!mBar.isShadeOpening() || mFlingVelocity <= 0) {
- return;
- }
- final float padding = MathUtils.lerp(
- MIN_OVERSCROLL, MAX_OVERSCROLL, getStackHeightFraction(height));
- setSectionPadding(padding);
- }
-
public void setExpandedHeightInternal(float h) {
if (isNaN(h)) {
Log.wtf(TAG, "ExpandedHeight set to NaN");
}
- maybeOverScrollForShadeFlingOpen(h);
if (mExpandLatencyTracking && h != 0f) {
DejankUtils.postAfterTraversal(
() -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL));
mExpandLatencyTracking = false;
}
- float fhWithoutOverExpansion = getMaxPanelHeight() - getOverExpansionAmount();
+ float maxPanelHeight = getMaxPanelHeight();
if (mHeightAnimator == null) {
- float overExpansionPixels = Math.max(0, h - fhWithoutOverExpansion);
- if (getOverExpansionPixels() != overExpansionPixels && mTracking) {
- setOverExpansion(overExpansionPixels, true /* isPixels */);
+ if (mTracking) {
+ float overExpansionPixels = Math.max(0, h - maxPanelHeight);
+ setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
}
- mExpandedHeight = Math.min(h, fhWithoutOverExpansion) + getOverExpansionAmount();
+ mExpandedHeight = Math.min(h, maxPanelHeight);
} else {
mExpandedHeight = h;
- if (mOverExpandedBeforeFling) {
- setOverExpansion(Math.max(0, h - fhWithoutOverExpansion), false /* isPixels */);
- }
}
// If we are closing the panel and we are almost there due to a slow decelerating
@@ -720,7 +749,7 @@
}
}
mExpandedFraction = Math.min(1f,
- fhWithoutOverExpansion == 0 ? 0 : mExpandedHeight / fhWithoutOverExpansion);
+ maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight);
onHeightUpdated(mExpandedHeight);
notifyBarPanelExpansionChanged();
}
@@ -731,16 +760,31 @@
*/
protected abstract boolean isTrackingBlocked();
- protected abstract void setSectionPadding(float padding);
+ protected void setOverExpansion(float overExpansion) {
+ mOverExpansion = overExpansion;
+ }
- protected abstract void setOverExpansion(float overExpansion, boolean isPixels);
+ /**
+ * Set the current overexpansion
+ *
+ * @param overExpansion the amount of overexpansion to apply
+ * @param isFromGesture is this amount from a gesture and needs to be rubberBanded?
+ */
+ private void setOverExpansionInternal(float overExpansion, boolean isFromGesture) {
+ if (!isFromGesture) {
+ mLastGesturedOverExpansion = -1;
+ setOverExpansion(overExpansion);
+ } else if (mLastGesturedOverExpansion != overExpansion) {
+ mLastGesturedOverExpansion = overExpansion;
+ final float heightForFullOvershoot = mView.getHeight() / 3.0f;
+ float newExpansion = MathUtils.saturate(overExpansion / heightForFullOvershoot);
+ newExpansion = Interpolators.getOvershootInterpolation(newExpansion);
+ setOverExpansion(newExpansion * mPanelFlingOvershootAmount * 2.0f);
+ }
+ }
protected abstract void onHeightUpdated(float expandedHeight);
- protected abstract float getOverExpansionAmount();
-
- protected abstract float getOverExpansionPixels();
-
/**
* This returns the maximum height of the panel. Children should override this if their
* desired height is not the full height.
@@ -977,9 +1021,32 @@
}
private ValueAnimator createHeightAnimator(float targetHeight) {
+ return createHeightAnimator(targetHeight, 0.0f /* performOvershoot */);
+ }
+
+ /**
+ * Create an animator that can also overshoot
+ *
+ * @param targetHeight the target height
+ * @param overshootAmount the amount of overshoot desired
+ */
+ private ValueAnimator createHeightAnimator(float targetHeight, float overshootAmount) {
+ float startExpansion = mOverExpansion;
ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, targetHeight);
animator.addUpdateListener(
- animation -> setExpandedHeightInternal((float) animation.getAnimatedValue()));
+ animation -> {
+ if (overshootAmount > 0.0f
+ // Also remove the overExpansion when collapsing
+ || (targetHeight == 0.0f && startExpansion != 0)) {
+ final float expansion = MathUtils.lerp(
+ startExpansion,
+ mPanelFlingOvershootAmount * overshootAmount,
+ Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
+ animator.getAnimatedFraction()));
+ setOverExpansionInternal(expansion, false /* isFromGesture */);
+ }
+ setExpandedHeightInternal((float) animation.getAnimatedValue());
+ });
return animator;
}
@@ -989,7 +1056,7 @@
mExpandedFraction,
mExpandedFraction > 0f || mInstantExpanding
|| isPanelVisibleBecauseOfHeadsUp() || mTracking
- || mHeightAnimator != null);
+ || mHeightAnimator != null && !mIsSpringBackAnimation);
}
for (int i = 0; i < mExpansionListeners.size(); i++) {
mExpansionListeners.get(i).onPanelExpansionChanged(mExpandedFraction, mTracking);
@@ -1037,14 +1104,6 @@
public abstract void resetViews(boolean animate);
-
- /**
- * @return whether "Clear all" button will be visible when the panel is fully expanded
- */
- protected abstract boolean fullyExpandedClearAllVisible();
-
- protected abstract boolean isClearAllVisible();
-
public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
mHeadsUpManager = headsUpManager;
}
@@ -1080,6 +1139,11 @@
return new OnConfigurationChangedListener();
}
+ /**
+ * Set that the panel is currently opening and not fully opened or closed.
+ */
+ public abstract void setIsShadeOpening(boolean opening);
+
public class TouchHandler implements View.OnTouchListener {
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mInstantExpanding || !mNotificationsDragEnabled || mTouchDisabled || (mMotionAborted
@@ -1108,7 +1172,7 @@
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mStatusBar.userActivity();
- mAnimatingOnDown = mHeightAnimator != null;
+ mAnimatingOnDown = mHeightAnimator != null && !mIsSpringBackAnimation;
mMinExpandHeight = 0.0f;
mDownTime = SystemClock.uptimeMillis();
if (mAnimatingOnDown && mClosing && !mHintAnimationRunning) {
@@ -1227,10 +1291,10 @@
mCollapsedAndHeadsUpOnDown =
isFullyCollapsed() && mHeadsUpManager.hasPinnedHeadsUp();
addMovement(event);
- if (!mGestureWaitForTouchSlop || (mHeightAnimator != null
- && !mHintAnimationRunning)) {
- mTouchSlopExceeded =
- (mHeightAnimator != null && !mHintAnimationRunning)
+ boolean regularHeightAnimationRunning = mHeightAnimator != null
+ && !mHintAnimationRunning && !mIsSpringBackAnimation;
+ if (!mGestureWaitForTouchSlop || regularHeightAnimationRunning) {
+ mTouchSlopExceeded = regularHeightAnimationRunning
|| mTouchSlopExceededBeforeDown;
cancelHeightAnimator();
onTrackingStarted();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 1331829..7a1e5cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -642,7 +642,7 @@
return;
}
- if (mState == ScrimState.UNLOCKED) {
+ if (mState == ScrimState.UNLOCKED || mState == ScrimState.BUBBLE_EXPANDED) {
// Darken scrim as you pull down the shade when unlocked, unless the shade is expanding
// because we're doing the screen off animation.
if (!mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()) {
@@ -657,12 +657,6 @@
}
mInFrontAlpha = 0;
}
- } else if (mState == ScrimState.BUBBLE_EXPANDED) {
- // Darken scrim as you pull down the shade when unlocked
- float behindFraction = getInterpolatedFraction();
- behindFraction = (float) Math.pow(behindFraction, 0.8f);
- mBehindAlpha = behindFraction * mDefaultScrimAlpha;
- mInFrontAlpha = 0;
} else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED
|| mState == ScrimState.PULSING) {
Pair<Integer, Float> result = calculateBackStateForState(mState);
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 06aedaa..5ee5e48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1694,7 +1694,7 @@
&& ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
&& !mDozing
&& !ONLY_CORE_APPS;
- mNotificationPanelViewController.setQsExpansionEnabled(expandEnabled);
+ mNotificationPanelViewController.setQsExpansionEnabledPolicy(expandEnabled);
Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
}
@@ -2096,13 +2096,10 @@
return true;
}
- // If we are locked, only animate if remote unlock animations are enabled and we can dismiss
- // the lock screen without challenging the user. We also don't animate non-activity
- // launches as they can break the animation.
+ // If we are locked, only animate if remote unlock animations are enabled. We also don't
+ // animate non-activity launches as they can break the animation.
// TODO(b/184121838): Support non activity launches on the lockscreen.
- return isActivityIntent
- && KeyguardService.sEnableRemoteKeyguardAnimation
- && mKeyguardStateController.canDismissLockScreen();
+ return isActivityIntent && KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation;
}
@Override
@@ -2112,13 +2109,12 @@
@Override
public void hideKeyguardWithAnimation(IRemoteAnimationRunner runner) {
- if (!mKeyguardStateController.canDismissLockScreen()) {
- Log.wtf(TAG,
- "Unable to hide keyguard with animation as the keyguard can't be dismissed");
- return;
- }
-
- mKeyguardViewMediator.hideWithAnimation(runner);
+ // We post to the main thread for 2 reasons:
+ // 1. KeyguardViewMediator is not thread-safe.
+ // 2. To ensure that ViewMediatorCallback#keyguardDonePending is called before
+ // ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur when doing
+ // dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }.
+ mMainThreadHandler.post(() -> mKeyguardViewMediator.hideWithAnimation(runner));
}
@Override
@@ -2841,12 +2837,13 @@
@Nullable ActivityLaunchAnimator.Controller animationController) {
if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return;
- final boolean afterKeyguardGone = mActivityIntentHelper.wouldLaunchResolverActivity(
- intent, mLockscreenUserManager.getCurrentUserId());
+ final boolean willLaunchResolverActivity =
+ mActivityIntentHelper.wouldLaunchResolverActivity(intent,
+ mLockscreenUserManager.getCurrentUserId());
ActivityLaunchAnimator.Controller animController =
- shouldAnimateLaunch(true /* isActivityIntent */) ? wrapAnimationController(
- animationController, dismissShade) : null;
+ !willLaunchResolverActivity && shouldAnimateLaunch(true /* isActivityIntent */)
+ ? wrapAnimationController(animationController, dismissShade) : null;
// If we animate, we will dismiss the shade only once the animation is done. This is taken
// care of by the StatusBarLaunchAnimationController.
@@ -2910,7 +2907,7 @@
}
};
executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly,
- afterKeyguardGone, true /* deferred */);
+ willLaunchResolverActivity, true /* deferred */);
}
@Nullable
@@ -3516,10 +3513,10 @@
public void fadeKeyguardWhilePulsing() {
mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING,
()-> {
- hideKeyguard();
if (shouldShowCircleReveal()) {
startCircleReveal();
}
+ hideKeyguard();
mStatusBarKeyguardViewManager.onKeyguardFadedAway();
}).start();
}
@@ -3877,9 +3874,7 @@
updateQsExpansionEnabled();
mKeyguardViewMediator.setDozing(mDozing);
- if (!isDozing && shouldShowCircleReveal()) {
- startCircleReveal();
- } else if ((isDozing && mWakefulnessLifecycle.getLastSleepReason()
+ if ((isDozing && mWakefulnessLifecycle.getLastSleepReason()
== PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON)
|| (!isDozing && mWakefulnessLifecycle.getLastWakeReason()
== PowerManager.WAKE_REASON_POWER_BUTTON)) {
@@ -4455,7 +4450,6 @@
} else {
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
}
- updateLightRevealScrimVisibility();
Trace.endSection();
}
@@ -4615,9 +4609,11 @@
*
* @param action The action to execute after dismissing the keyguard.
* @param collapsePanel Whether we should collapse the panel after dismissing the keyguard.
+ * @param deferKeyguardDismiss Whether we should defer the keyguard actual dismissal, for
+ * instance to run animations on the keyguard before hiding it.
*/
private void executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone,
- boolean collapsePanel) {
+ boolean collapsePanel, boolean deferKeyguardDismiss) {
if (!mDeviceProvisionedController.isDeviceProvisioned()) return;
dismissKeyguardThenExecute(() -> {
@@ -4633,8 +4629,7 @@
action.run();
}).start();
- boolean deferred = collapsePanel ? mShadeController.collapsePanel() : false;
- return deferred;
+ return collapsePanel ? mShadeController.collapsePanel() : deferKeyguardDismiss;
}, afterKeyguardGone);
}
@@ -4667,12 +4662,19 @@
public void startPendingIntentDismissingKeyguard(
final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback,
@Nullable ActivityLaunchAnimator.Controller animationController) {
- final boolean afterKeyguardGone = intent.isActivity()
+ final boolean willLaunchResolverActivity = intent.isActivity()
&& mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
- boolean collapse = animationController == null;
- boolean animate = shouldAnimateLaunch(intent.isActivity());
+ boolean animate = !willLaunchResolverActivity
+ && animationController != null
+ && shouldAnimateLaunch(intent.isActivity());
+
+ // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we run
+ // the animation on the keyguard). The animation will take care of (instantly) collapsing
+ // the shade and hiding the keyguard once it is done.
+ boolean collapse = !animate;
+ boolean deferKeyguardDismiss = animate;
executeActionDismissingKeyguard(() -> {
try {
// We wrap animationCallback with a StatusBarLaunchAnimatorController so that the
@@ -4701,7 +4703,7 @@
if (intentSentUiThreadCallback != null) {
postOnUiThread(intentSentUiThreadCallback);
}
- }, afterKeyguardGone, collapse);
+ }, willLaunchResolverActivity, collapse, deferKeyguardDismiss);
}
private void postOnUiThread(Runnable runnable) {
@@ -4890,15 +4892,9 @@
return;
}
- if (mDozeServiceHost.isPulsing()) {
- mLightRevealScrim.setVisibility(View.GONE);
- return;
- }
-
if (mFeatureFlags.useNewLockscreenAnimations()
&& (mDozeParameters.getAlwaysOn() || mDozeParameters.isQuickPickupEnabled())) {
mLightRevealScrim.setVisibility(View.VISIBLE);
- mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
} else {
mLightRevealScrim.setVisibility(View.GONE);
}
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 c0957c0..c7efcb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -26,6 +26,7 @@
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.ColorStateList;
+import android.hardware.biometrics.BiometricSourceType;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.KeyEvent;
@@ -446,7 +447,16 @@
mAfterKeyguardGoneAction = r;
mKeyguardGoneCancelAction = cancelAction;
+
+ // If there is an an alternate auth interceptor (like the UDFPS), show that one instead
+ // of the bouncer.
if (mAlternateAuthInterceptor != null) {
+ if (!afterKeyguardGone) {
+ mBouncer.setDismissAction(mAfterKeyguardGoneAction, mKeyguardGoneCancelAction);
+ mAfterKeyguardGoneAction = null;
+ mKeyguardGoneCancelAction = null;
+ }
+
if (mAlternateAuthInterceptor.showAlternateAuthBouncer()) {
mStatusBar.updateScrimController();
}
@@ -614,6 +624,10 @@
if (mBouncer.isShowing()) {
mBouncer.startPreHideAnimation(finishRunnable);
mStatusBar.onBouncerPreHideAnimation();
+
+ // startPreHideAnimation() will change the visibility of the bouncer, so we have to
+ // make sure to update its state.
+ updateStates();
} else if (finishRunnable != null) {
finishRunnable.run();
}
@@ -768,9 +782,13 @@
private void wakeAndUnlockDejank() {
if (mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK
&& LatencyTracker.isEnabled(mContext)) {
- DejankUtils.postAfterTraversal(() ->
+ BiometricSourceType type = mBiometricUnlockController.getBiometricType();
+ DejankUtils.postAfterTraversal(() -> {
LatencyTracker.getInstance(mContext).onActionEnd(
- LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK));
+ type == BiometricSourceType.FACE
+ ? LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK
+ : LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK);
+ });
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
index b2ab307..14e513a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
@@ -28,8 +28,8 @@
override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
delegate.onLaunchAnimationEnd(isExpandingFullyAbove)
- statusBar.onLaunchAnimationEnd(isExpandingFullyAbove)
statusBar.notificationPanelViewController.setIsLaunchAnimationRunning(false)
+ statusBar.onLaunchAnimationEnd(isExpandingFullyAbove)
}
override fun onLaunchAnimationProgress(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index f5dd195..d93b766 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -252,10 +252,11 @@
}
boolean isActivityIntent = intent != null && intent.isActivity() && !isBubble;
- final boolean afterKeyguardGone = isActivityIntent
+ final boolean willLaunchResolverActivity = isActivityIntent
&& mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
- final boolean animate = mStatusBar.shouldAnimateLaunch(isActivityIntent);
+ final boolean animate = !willLaunchResolverActivity
+ && mStatusBar.shouldAnimateLaunch(isActivityIntent);
boolean showOverLockscreen = mKeyguardStateController.isShowing() && intent != null
&& mActivityIntentHelper.wouldShowOverLockscreen(intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
@@ -268,7 +269,7 @@
postKeyguardAction.onDismiss();
} else {
mActivityStarter.dismissKeyguardThenExecute(
- postKeyguardAction, null /* cancel */, afterKeyguardGone);
+ postKeyguardAction, null /* cancel */, willLaunchResolverActivity);
}
}
@@ -282,15 +283,6 @@
boolean showOverLockscreen) {
mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey());
- // TODO: Some of this code may be able to move to NotificationEntryManager.
- String key = row.getEntry().getSbn().getKey();
- if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(key)) {
- // Release the HUN notification to the shade.
- if (mPresenter.isPresenterFullyCollapsed()) {
- HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
- }
- }
-
final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
entry, row, controller, intent,
isActivityIntent, animate);
@@ -305,7 +297,9 @@
} else {
runnable.run();
}
- return !mNotificationPanel.isFullyCollapsed();
+
+ // Always defer the keyguard dismiss when animating.
+ return animate || !mNotificationPanel.isFullyCollapsed();
}
private void handleNotificationClickAfterPanelCollapsed(
@@ -337,7 +331,7 @@
// bypass work challenge
if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
intent.getIntentSender(), notificationKey)) {
- removeHUN(row);
+ removeHunAfterClick(row);
// Show work challenge, do not run PendingIntent and
// remove notification
collapseOnMainThread();
@@ -357,7 +351,7 @@
final boolean canBubble = entry.canBubble();
if (canBubble) {
mLogger.logExpandingBubble(notificationKey);
- removeHUN(row);
+ removeHunAfterClick(row);
expandBubbleStackOnMainThread(entry);
} else {
startNotificationIntent(intent, fillInIntent, entry, row, animate, isActivityIntent);
@@ -508,9 +502,14 @@
}, null, false /* afterKeyguardGone */);
}
- private void removeHUN(ExpandableNotificationRow row) {
+ private void removeHunAfterClick(ExpandableNotificationRow row) {
String key = row.getEntry().getSbn().getKey();
if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(key)) {
+ // Release the HUN notification to the shade.
+ if (mPresenter.isPresenterFullyCollapsed()) {
+ HeadsUpUtil.setNeedsHeadsUpDisappearAnimationAfterClick(row, true);
+ }
+
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
// become canceled shortly by NoMan, but we can't assume that.
mHeadsUpManager.removeNotification(key, true /* releaseImmediately */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
index 7563b30..3b272da8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
@@ -27,7 +27,6 @@
import com.android.systemui.controls.dagger.ControlsComponent
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.qs.QSTileHost.POSITION_AT_END
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.statusbar.policy.DeviceControlsController.Callback
import com.android.systemui.util.settings.SecureSettings
@@ -64,8 +63,8 @@
companion object {
private const val TAG = "DeviceControlsControllerImpl"
- internal const val QS_PRIORITY_POSITION = 2
- internal const val QS_DEFAULT_POSITION = POSITION_AT_END
+ internal const val QS_PRIORITY_POSITION = 3
+ internal const val QS_DEFAULT_POSITION = 7
internal const val PREFS_CONTROLS_SEEDING_COMPLETED = "SeedingCompleted"
internal const val PREFS_CONTROLS_FILE = "controls_prefs"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpUtil.java
index 1e3c123c..1212585 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpUtil.java
@@ -31,7 +31,7 @@
* @param view The view to be set the flag to.
* @param clicked True to set as clicked. False to not-clicked.
*/
- public static void setIsClickedHeadsUpNotification(View view, boolean clicked) {
+ public static void setNeedsHeadsUpDisappearAnimationAfterClick(View view, boolean clicked) {
view.setTag(TAG_CLICKED_NOTIFICATION, clicked ? true : null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
index 2ecd4b3..1f1817c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
@@ -137,7 +137,8 @@
mConfigurationController = configurationController;
mStatusBarStateController = statusBarStateController;
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView,
- keyguardStateController, dozeParameters, unlockedScreenOffAnimationController);
+ keyguardStateController, dozeParameters,
+ unlockedScreenOffAnimationController, /* animateYPos= */ false);
mUserDetailAdapter = new KeyguardUserDetailAdapter(context, userDetailViewAdapterProvider);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
index 68f2a62..43b2061 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
@@ -173,7 +173,8 @@
mAdapter = new KeyguardUserAdapter(mContext, resources, layoutInflater,
mUserSwitcherController, this);
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView,
- keyguardStateController, dozeParameters, unlockedScreenOffAnimationController);
+ keyguardStateController, dozeParameters,
+ unlockedScreenOffAnimationController, /* animateYPos= */ false);
mBackground = new KeyguardUserSwitcherScrim(context);
}
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 7022fb1..efeeac6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -749,7 +749,10 @@
super.dispatchStartTemporaryDetach();
// Detach the EditText temporarily such that it doesn't get onDetachedFromWindow and
// won't lose IME focus.
- detachViewFromParent(mEditText);
+ final int iEditText = indexOfChild(mEditText);
+ if (iEditText != -1) {
+ detachViewFromParent(iEditText);
+ }
}
@Override
@@ -777,7 +780,8 @@
mOnVisibilityChangedListener.accept(visibility == VISIBLE);
// Hide soft-keyboard when the input view became invisible
// (i.e. The notification shade collapsed by pressing the home key)
- if (visibility != VISIBLE && !mEditText.isVisibleToUser()) {
+ if (visibility != VISIBLE && !mEditText.isVisibleToUser()
+ && !mController.isRemoteInputActive()) {
mEditText.hideIme();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletControllerImpl.kt
index af12844..143ba06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletControllerImpl.kt
@@ -33,7 +33,7 @@
companion object {
private const val TAG = "WalletControllerImpl"
- internal const val QS_PRIORITY_POSITION = 2
+ internal const val QS_PRIORITY_POSITION = 3
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index b9b62b4..753def0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -86,7 +86,9 @@
@Override
public void notifyListeners(SignalCallback callback) {
if (mCurrentState.isCarrierMerged) {
- notifyListenersForCarrierWifi(callback);
+ if (mCurrentState.isDefault) {
+ notifyListenersForCarrierWifi(callback);
+ }
} else {
notifyListenersForNonCarrierWifi(callback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
index d61848c..e0ff88b 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
@@ -75,6 +75,10 @@
static final String COLOR_SOURCE_PRESET = "preset";
+ static final String COLOR_SOURCE_HOME = "home_wallpaper";
+
+ static final String COLOR_SOURCE_LOCK = "lock_wallpaper";
+
static final String TIMESTAMP_FIELD = "_applied_timestamp";
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index c23e0b4..ca1f55e 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -16,6 +16,8 @@
package com.android.systemui.theme;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
+import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_HOME;
+import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_LOCK;
import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_PRESET;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ACCENT_COLOR;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_SYSTEM_PALETTE;
@@ -200,36 +202,37 @@
String overlayPackageJson = mSecureSettings.getStringForUser(
Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
currentUser);
- boolean isDestinationBoth = mWallpaperManager.getWallpaperId(
- WallpaperManager.FLAG_LOCK) < 0;
- if (!TextUtils.isEmpty(overlayPackageJson)) {
- try {
- JSONObject jsonObject = new JSONObject(overlayPackageJson);
- if (!COLOR_SOURCE_PRESET.equals(jsonObject.optString(OVERLAY_COLOR_SOURCE))
- && ((flags & latestWallpaperType) != 0)) {
- mSkipSettingChange = true;
- if (jsonObject.has(OVERLAY_CATEGORY_ACCENT_COLOR) || jsonObject.has(
- OVERLAY_CATEGORY_SYSTEM_PALETTE)) {
- jsonObject.remove(OVERLAY_CATEGORY_ACCENT_COLOR);
- jsonObject.remove(OVERLAY_CATEGORY_SYSTEM_PALETTE);
- jsonObject.remove(OVERLAY_COLOR_SOURCE);
- jsonObject.remove(OVERLAY_COLOR_INDEX);
- }
- // Keep color_both value because users can change either or both home and
- // lock screen wallpapers.
- jsonObject.put(OVERLAY_COLOR_BOTH, isDestinationBoth ? "1" : "0");
-
- jsonObject.put(TIMESTAMP_FIELD, System.currentTimeMillis());
- if (DEBUG) {
- Log.d(TAG, "Updating theme setting from "
- + overlayPackageJson + " to " + jsonObject.toString());
- }
- mSecureSettings.putString(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
- jsonObject.toString());
+ boolean isDestinationBoth = (flags == (WallpaperManager.FLAG_SYSTEM
+ | WallpaperManager.FLAG_LOCK));
+ try {
+ JSONObject jsonObject = (overlayPackageJson == null) ? new JSONObject()
+ : new JSONObject(overlayPackageJson);
+ if (!COLOR_SOURCE_PRESET.equals(jsonObject.optString(OVERLAY_COLOR_SOURCE))
+ && ((flags & latestWallpaperType) != 0)) {
+ mSkipSettingChange = true;
+ if (jsonObject.has(OVERLAY_CATEGORY_ACCENT_COLOR) || jsonObject.has(
+ OVERLAY_CATEGORY_SYSTEM_PALETTE)) {
+ jsonObject.remove(OVERLAY_CATEGORY_ACCENT_COLOR);
+ jsonObject.remove(OVERLAY_CATEGORY_SYSTEM_PALETTE);
+ jsonObject.remove(OVERLAY_COLOR_INDEX);
}
- } catch (JSONException e) {
- Log.i(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e);
+ // Keep color_both value because users can change either or both home and
+ // lock screen wallpapers.
+ jsonObject.put(OVERLAY_COLOR_BOTH, isDestinationBoth ? "1" : "0");
+
+ jsonObject.put(OVERLAY_COLOR_SOURCE,
+ (flags == WallpaperManager.FLAG_LOCK) ? COLOR_SOURCE_LOCK
+ : COLOR_SOURCE_HOME);
+ jsonObject.put(TIMESTAMP_FIELD, System.currentTimeMillis());
+ if (DEBUG) {
+ Log.d(TAG, "Updating theme setting from "
+ + overlayPackageJson + " to " + jsonObject.toString());
+ }
+ mSecureSettings.putString(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
+ jsonObject.toString());
}
+ } catch (JSONException e) {
+ Log.i(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e);
}
reevaluateSystemTheme(false /* forceReload */);
}
@@ -237,11 +240,14 @@
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_USER_STARTED.equals(intent.getAction())
- || Intent.ACTION_MANAGED_PROFILE_ADDED.equals(intent.getAction())) {
- if (!mDeviceProvisionedController.isCurrentUserSetup()) {
+ boolean newWorkProfile = Intent.ACTION_MANAGED_PROFILE_ADDED.equals(intent.getAction());
+ boolean userStarted = Intent.ACTION_USER_STARTED.equals(intent.getAction());
+ boolean isManagedProfile = mUserManager.isManagedProfile(
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ if (userStarted || newWorkProfile) {
+ if (!mDeviceProvisionedController.isCurrentUserSetup() && isManagedProfile) {
Log.i(TAG, "User setup not finished when " + intent.getAction()
- + " was received. Deferring...");
+ + " was received. Deferring... Managed profile? " + isManagedProfile);
return;
}
if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added.");
@@ -323,17 +329,22 @@
Runnable updateColors = () -> {
WallpaperColors systemColor = mWallpaperManager.getWallpaperColors(
getLatestWallpaperType());
- mMainExecutor.execute(() -> {
+ Runnable applyColors = () -> {
if (DEBUG) Log.d(TAG, "Boot colors: " + systemColor);
mCurrentColors = systemColor;
reevaluateSystemTheme(false /* forceReload */);
- });
+ };
+ if (mDeviceProvisionedController.isCurrentUserSetup()) {
+ mMainExecutor.execute(applyColors);
+ } else {
+ applyColors.run();
+ }
};
// Whenever we're going directly to setup wizard, we need to process colors synchronously,
// otherwise we'll see some jank when the activity is recreated.
if (!mDeviceProvisionedController.isCurrentUserSetup()) {
- mMainExecutor.execute(updateColors);
+ updateColors.run();
} else {
mBgExecutor.execute(updateColors);
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java b/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java
index 02a07e4..de5a363 100644
--- a/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java
@@ -37,20 +37,16 @@
private final SparseArray<Boolean> mCallStrengthConfigs = new SparseArray<>();
private final SparseArray<Boolean> mNoCallingConfigs = new SparseArray<>();
private final CarrierConfigManager mCarrierConfigManager;
- private final boolean mDefaultCallStrengthConfig;
- private final boolean mDefaultNoCallingConfig;
+ private boolean mDefaultCallStrengthConfigLoaded;
+ private boolean mDefaultCallStrengthConfig;
+ private boolean mDefaultNoCallingConfigLoaded;
+ private boolean mDefaultNoCallingConfig;
@Inject
public CarrierConfigTracker(Context context) {
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
context.registerReceiver(
this, new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
- mDefaultCallStrengthConfig =
- CarrierConfigManager.getDefaultConfig().getBoolean(
- CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL);
- mDefaultNoCallingConfig =
- CarrierConfigManager.getDefaultConfig().getBoolean(
- CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL);
}
@Override
@@ -81,6 +77,12 @@
if (mCallStrengthConfigs.indexOfKey(subId) >= 0) {
return mCallStrengthConfigs.get(subId);
}
+ if (!mDefaultCallStrengthConfigLoaded) {
+ mDefaultCallStrengthConfig =
+ CarrierConfigManager.getDefaultConfig().getBoolean(
+ CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL);
+ mDefaultCallStrengthConfigLoaded = true;
+ }
return mDefaultCallStrengthConfig;
}
@@ -91,6 +93,12 @@
if (mNoCallingConfigs.indexOfKey(subId) >= 0) {
return mNoCallingConfigs.get(subId);
}
+ if (!mDefaultNoCallingConfigLoaded) {
+ mDefaultNoCallingConfig =
+ CarrierConfigManager.getDefaultConfig().getBoolean(
+ CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL);
+ mDefaultNoCallingConfigLoaded = true;
+ }
return mDefaultNoCallingConfig;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index ed84a59..407b248 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -939,6 +939,13 @@
.start();
}
+ // When the ringer drawer is open, tapping the currently selected ringer will set the ringer
+ // to the current ringer mode. Change the content description to that, instead of the 'tap
+ // to change ringer mode' default.
+ mSelectedRingerContainer.setContentDescription(
+ mContext.getString(getStringDescriptionResourceForRingerMode(
+ mState.ringerModeInternal)));
+
mIsRingerDrawerOpen = true;
}
@@ -983,6 +990,11 @@
.translationY(0f)
.start();
+ // When the drawer is closed, tapping the selected ringer drawer will open it, allowing the
+ // user to change the ringer.
+ mSelectedRingerContainer.setContentDescription(
+ mContext.getString(R.string.volume_ringer_change));
+
mIsRingerDrawerOpen = false;
}
@@ -1471,20 +1483,8 @@
}
private void addAccessibilityDescription(View view, int currState, String hintLabel) {
- int currStateResId;
- switch (currState) {
- case RINGER_MODE_SILENT:
- currStateResId = R.string.volume_ringer_status_silent;
- break;
- case RINGER_MODE_VIBRATE:
- currStateResId = R.string.volume_ringer_status_vibrate;
- break;
- case RINGER_MODE_NORMAL:
- default:
- currStateResId = R.string.volume_ringer_status_normal;
- }
-
- view.setContentDescription(mContext.getString(currStateResId));
+ view.setContentDescription(
+ mContext.getString(getStringDescriptionResourceForRingerMode(currState)));
view.setAccessibilityDelegate(new AccessibilityDelegate() {
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
@@ -1494,6 +1494,18 @@
});
}
+ private int getStringDescriptionResourceForRingerMode(int mode) {
+ switch (mode) {
+ case RINGER_MODE_SILENT:
+ return R.string.volume_ringer_status_silent;
+ case RINGER_MODE_VIBRATE:
+ return R.string.volume_ringer_status_vibrate;
+ case RINGER_MODE_NORMAL:
+ default:
+ return R.string.volume_ringer_status_normal;
+ }
+ }
+
/**
* Toggles enable state of views in a VolumeRow (not including seekbar or icon)
* Hides/shows zen icon
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
index 236954b..2dcc43c 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
@@ -19,8 +19,8 @@
import static android.provider.Settings.ACTION_LOCKSCREEN_SETTINGS;
import android.content.Intent;
-import android.graphics.Color;
import android.graphics.drawable.Drawable;
+import android.hardware.biometrics.BiometricSourceType;
import android.os.Bundle;
import android.os.Handler;
import android.service.quickaccesswallet.QuickAccessWalletClient;
@@ -34,6 +34,9 @@
import androidx.annotation.NonNull;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -63,7 +66,10 @@
private final Handler mHandler;
private final FalsingManager mFalsingManager;
private final UserTracker mUserTracker;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final StatusBarKeyguardViewManager mKeyguardViewManager;
+
+ private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback;
private WalletScreenController mWalletScreenController;
private QuickAccessWalletClient mWalletClient;
private boolean mHasRegisteredListener;
@@ -77,6 +83,7 @@
@Main Handler handler,
FalsingManager falsingManager,
UserTracker userTracker,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarKeyguardViewManager keyguardViewManager) {
mKeyguardStateController = keyguardStateController;
mKeyguardDismissUtil = keyguardDismissUtil;
@@ -85,6 +92,7 @@
mHandler = handler;
mFalsingManager = falsingManager;
mUserTracker = userTracker;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardViewManager = keyguardViewManager;
}
@@ -116,7 +124,17 @@
mHandler,
mUserTracker,
mFalsingManager,
+ mKeyguardUpdateMonitor,
mKeyguardStateController);
+ mKeyguardUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onBiometricRunningStateChanged(
+ boolean running,
+ BiometricSourceType biometricSourceType) {
+ Log.d(TAG, "Biometric running state has changed.");
+ mWalletScreenController.queryWalletCards();
+ }
+ };
walletView.getAppButton().setOnClickListener(
v -> {
@@ -146,7 +164,9 @@
// Click the action button to re-render the screen when the device is unlocked.
walletView.setDeviceLockedActionOnClickListener(
v -> {
+ Log.d(TAG, "Wallet action button is clicked.");
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ Log.d(TAG, "False tap detected on wallet action button.");
return;
}
@@ -164,13 +184,17 @@
mHasRegisteredListener = true;
}
mKeyguardStateController.addCallback(mWalletScreenController);
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
}
@Override
protected void onResume() {
super.onResume();
mWalletScreenController.queryWalletCards();
- mKeyguardViewManager.requestFp(true, Color.BLACK);
+ mKeyguardViewManager.requestFp(
+ true,
+ Utils.getColorAttrDefaultColor(
+ this, com.android.internal.R.attr.colorAccentPrimary));
mKeyguardViewManager.requestFace(true);
}
@@ -195,7 +219,6 @@
public void onWalletServiceEvent(WalletServiceEvent event) {
switch (event.getEventType()) {
case WalletServiceEvent.TYPE_NFC_PAYMENT_STARTED:
- finish();
break;
case WalletServiceEvent.TYPE_WALLET_CARDS_UPDATED:
mWalletScreenController.queryWalletCards();
@@ -224,6 +247,9 @@
@Override
protected void onDestroy() {
mKeyguardStateController.removeCallback(mWalletScreenController);
+ if (mKeyguardUpdateMonitorCallback != null) {
+ mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
+ }
mWalletScreenController.onDismissed();
mWalletClient.removeWalletServiceEventListener(this);
mHasRegisteredListener = false;
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
index 96a3087..ab8ad77 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
@@ -39,6 +39,7 @@
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
@@ -66,6 +67,7 @@
private final ActivityStarter mActivityStarter;
private final Executor mExecutor;
private final Handler mHandler;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final KeyguardStateController mKeyguardStateController;
private final Runnable mSelectionRunnable = this::selectCard;
private final SharedPreferences mPrefs;
@@ -85,6 +87,7 @@
Handler handler,
UserTracker userTracker,
FalsingManager falsingManager,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
KeyguardStateController keyguardStateController) {
mContext = context;
mWalletClient = walletClient;
@@ -92,6 +95,7 @@
mExecutor = executor;
mHandler = handler;
mFalsingManager = falsingManager;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardStateController = keyguardStateController;
mPrefs = userTracker.getUserContext().getSharedPreferences(TAG, Context.MODE_PRIVATE);
mWalletView = walletView;
@@ -134,8 +138,13 @@
Log.w(TAG, "Invalid selected card index, showing empty state.");
showEmptyStateView();
} else {
+ boolean isUdfpsEnabled = mKeyguardUpdateMonitor.isUdfpsEnrolled()
+ && mKeyguardUpdateMonitor.isFingerprintDetectionRunning();
mWalletView.showCardCarousel(
- data, selectedIndex, !mKeyguardStateController.isUnlocked());
+ data,
+ selectedIndex,
+ !mKeyguardStateController.isUnlocked(),
+ isUdfpsEnabled);
}
}
removeMinHeightAndRecordHeightOnLayout();
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 4f83abf..8412a8a 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
@@ -63,6 +63,7 @@
private final ViewGroup mEmptyStateView;
private CharSequence mCenterCardText;
private boolean mIsDeviceLocked = false;
+ private boolean mIsUdfpsEnabled = false;
private OnClickListener mDeviceLockedActionOnClickListener;
public WalletView(Context context) {
@@ -108,7 +109,7 @@
mCardLabel.setText(centerCardText);
mIcon.setImageDrawable(centerCardIcon);
}
- renderActionButton(centerCard, mIsDeviceLocked);
+ renderActionButton(centerCard, mIsDeviceLocked, mIsUdfpsEnabled);
if (TextUtils.equals(centerCardText, getLabelText(nextCard))) {
mCardLabel.setAlpha(1f);
} else {
@@ -128,15 +129,19 @@
* @param isDeviceLocked indicates whether the device is locked.
*/
void showCardCarousel(
- List<WalletCardViewInfo> data, int selectedIndex, boolean isDeviceLocked) {
+ List<WalletCardViewInfo> data,
+ int selectedIndex,
+ boolean isDeviceLocked,
+ boolean isUdfpsEnabled) {
boolean shouldAnimate =
mCardCarousel.setData(data, selectedIndex, mIsDeviceLocked != isDeviceLocked);
mIsDeviceLocked = isDeviceLocked;
+ mIsUdfpsEnabled = isUdfpsEnabled;
mCardCarouselContainer.setVisibility(VISIBLE);
mErrorView.setVisibility(GONE);
mEmptyStateView.setVisibility(GONE);
mIcon.setImageDrawable(getHeaderIcon(mContext, data.get(selectedIndex)));
- renderActionButton(data.get(selectedIndex), isDeviceLocked);
+ renderActionButton(data.get(selectedIndex), isDeviceLocked, mIsUdfpsEnabled);
if (shouldAnimate) {
animateViewsShown(mIcon, mCardLabel, mActionButton);
}
@@ -240,13 +245,14 @@
return icon;
}
- private void renderActionButton(WalletCardViewInfo walletCard, boolean isDeviceLocked) {
+ private void renderActionButton(
+ WalletCardViewInfo walletCard, boolean isDeviceLocked, boolean isUdfpsEnabled) {
CharSequence actionButtonText = getActionButtonText(walletCard);
- if (isDeviceLocked) {
+ if (!isUdfpsEnabled && isDeviceLocked) {
mActionButton.setVisibility(VISIBLE);
mActionButton.setText(R.string.wallet_action_button_label_unlock);
mActionButton.setOnClickListener(mDeviceLockedActionOnClickListener);
- } else if (actionButtonText != null) {
+ } else if (!isDeviceLocked && actionButtonText != null) {
mActionButton.setText(actionButtonText);
mActionButton.setVisibility(VISIBLE);
mActionButton.setOnClickListener(v -> {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/TextAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/TextAnimatorTest.kt
index ad7f0cb..3322414 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/TextAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/TextAnimatorTest.kt
@@ -18,12 +18,14 @@
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
+import android.graphics.Typeface
import android.testing.AndroidTestingRunner
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
@@ -140,4 +142,41 @@
verify(animationEndCallback).run()
verify(valueAnimator).removeListener(eq(captor.value))
}
+
+ @Test
+ fun testCacheTypeface() {
+ val layout = makeLayout("Hello, World", PAINT)
+ val valueAnimator = mock(ValueAnimator::class.java)
+ val textInterpolator = mock(TextInterpolator::class.java)
+ val paint = TextPaint().apply {
+ typeface = Typeface.createFromFile("/system/fonts/Roboto-Regular.ttf")
+ }
+ `when`(textInterpolator.targetPaint).thenReturn(paint)
+
+ val textAnimator = TextAnimator(layout, {}).apply {
+ this.textInterpolator = textInterpolator
+ this.animator = valueAnimator
+ }
+
+ textAnimator.setTextStyle(
+ weight = 400,
+ animate = true
+ )
+
+ val prevTypeface = paint.typeface
+
+ textAnimator.setTextStyle(
+ weight = 700,
+ animate = true
+ )
+
+ assertThat(paint.typeface).isNotSameInstanceAs(prevTypeface)
+
+ textAnimator.setTextStyle(
+ weight = 400,
+ animate = true
+ )
+
+ assertThat(paint.typeface).isSameInstanceAs(prevTypeface)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/TextInterpolatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/TextInterpolatorTest.kt
index 149e179..e42d537 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/TextInterpolatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/TextInterpolatorTest.kt
@@ -18,6 +18,9 @@
import android.graphics.Bitmap
import android.graphics.Canvas
+import android.graphics.Typeface
+import android.graphics.fonts.Font
+import android.graphics.fonts.FontFamily
import android.testing.AndroidTestingRunner
import android.text.Layout
import android.text.StaticLayout
@@ -29,6 +32,7 @@
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
+import java.io.File
import kotlin.math.ceil
private const val TEXT = "Hello, World."
@@ -36,16 +40,24 @@
private const val BMP_WIDTH = 400
private const val BMP_HEIGHT = 300
+// Due to b/189235998 the weight 400 of the default font is no longer variable font. To be able to
+// test variable behavior, create the interpolatable typefaces with manually here.
+private val VF_FONT = Font.Builder(File("/system/fonts/Roboto-Regular.ttf")).build()
+
+private fun Font.toTypeface() =
+ Typeface.CustomFallbackBuilder(FontFamily.Builder(this).build()).build()
+
private val PAINT = TextPaint().apply {
+ typeface = Font.Builder(VF_FONT).setFontVariationSettings("'wght' 400").build().toTypeface()
textSize = 32f
}
private val START_PAINT = TextPaint(PAINT).apply {
- fontVariationSettings = "'wght' 400"
+ typeface = Font.Builder(VF_FONT).setFontVariationSettings("'wght' 400").build().toTypeface()
}
private val END_PAINT = TextPaint(PAINT).apply {
- fontVariationSettings = "'wght' 700"
+ typeface = Font.Builder(VF_FONT).setFontVariationSettings("'wght' 700").build().toTypeface()
}
@RunWith(AndroidTestingRunner::class)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index ad99e4d..f62069d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -77,6 +77,8 @@
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.List;
+
@LargeTest
@RunWith(AndroidTestingRunner.class)
public class WindowMagnificationControllerTest extends SysuiTestCase {
@@ -152,6 +154,19 @@
}
@Test
+ public void enableWindowMagnification_systemGestureExclusionRectsIsSet() {
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ Float.NaN);
+ });
+ // Wait for Rects updated.
+ waitForIdleSync();
+
+ List<Rect> rects = mWindowManager.getAttachedView().getSystemGestureExclusionRects();
+ assertFalse(rects.isEmpty());
+ }
+
+ @Test
public void deleteWindowMagnification_destroyControl() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
index aed0da6..82bf041 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
@@ -22,6 +22,8 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import android.content.Context;
@@ -124,16 +126,50 @@
}
@Test
- public void testModeUpdated_whenSwitchToFingerprint() {
+ public void testModeUpdated_onSoftError_whenSwitchToFingerprint() {
mFaceToFpView.onDialogAnimatedIn();
mFaceToFpView.onAuthenticationFailed(TYPE_FACE, "no face");
waitForIdleSync();
verify(mIndicatorView).setText(
eq(mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead)));
+ verify(mCallback).onAction(
+ eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING, mFaceToFpView.mState);
}
+ @Test
+ public void testModeUpdated_onHardError_whenSwitchToFingerprint() {
+ mFaceToFpView.onDialogAnimatedIn();
+ mFaceToFpView.onError(TYPE_FACE, "oh no!");
+ waitForIdleSync();
+
+ verify(mIndicatorView).setText(
+ eq(mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead)));
+ verify(mCallback).onAction(
+ eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
+ assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING, mFaceToFpView.mState);
+ }
+
+ @Test
+ public void testFingerprintOnlyStartsOnFirstError() {
+ mFaceToFpView.onDialogAnimatedIn();
+ verify(mFaceToFpView.mIconController)
+ .updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));
+
+ mFaceToFpView.onDialogAnimatedIn();
+ mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_ERROR);
+ mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING);
+
+ reset(mCallback);
+
+ mFaceToFpView.onError(TYPE_FACE, "oh no!");
+ mFaceToFpView.onAuthenticationFailed(TYPE_FACE, "no face");
+
+ verify(mCallback, never()).onAction(
+ eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
+ }
+
public class TestableView extends AuthBiometricFaceToFingerprintView {
public TestableView(Context context) {
super(context, null, new MockInjector());
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 4a9d66c..c0b45c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -236,13 +236,14 @@
public void testOnSensor_Fingerprint() {
final int screenX = 100;
final int screenY = 100;
+ final float misc = -1;
final float minor = 2f;
final float major = 3f;
final int reason = DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
- float[] rawValues = new float[]{screenX, screenY, minor, major};
+ float[] rawValues = new float[]{screenX, screenY, misc, major, minor};
mTriggers.onSensor(reason, screenX, screenY, rawValues);
verify(mHost).extendPulse(reason);
- verify(mAuthController).onAodInterrupt(eq(screenX), eq(screenY), eq(minor), eq(major));
+ verify(mAuthController).onAodInterrupt(eq(screenX), eq(screenY), eq(major), eq(minor));
}
private void waitForSensorManager() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
index 4e1627f..150f4545 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
@@ -44,6 +44,7 @@
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.isNotNull
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
@@ -183,6 +184,31 @@
}
@Test
+ fun testOnLoad_checksForResume_badService() {
+ // Set up MBS that will allow connection but not return valid media
+ val pm = mock(PackageManager::class.java)
+ whenever(mockContext.packageManager).thenReturn(pm)
+ val resolveInfo = ResolveInfo()
+ val serviceInfo = ServiceInfo()
+ serviceInfo.packageName = PACKAGE_NAME
+ resolveInfo.serviceInfo = serviceInfo
+ resolveInfo.serviceInfo.name = CLASS_NAME
+ val resumeInfo = listOf(resolveInfo)
+ whenever(pm.queryIntentServices(any(), anyInt())).thenReturn(resumeInfo)
+
+ whenever(resumeBrowser.testConnection()).thenAnswer {
+ callbackCaptor.value.onError()
+ }
+
+ // When media data is loaded that has not been checked yet, and does not have a MBS
+ resumeListener.onMediaDataLoaded(KEY, null, data)
+ executor.runAllReady()
+
+ // Then we report back to the manager
+ verify(mediaDataManager).setResumeAction(eq(KEY), eq(null))
+ }
+
+ @Test
fun testOnLoad_remotePlayback_doesNotCheck() {
// When media data is loaded that has not been checked yet, and is not local
val dataRemote = data.copy(isLocalSession = false)
@@ -217,10 +243,11 @@
// Then we test whether the service is valid
executor.runAllReady()
+ verify(mediaDataManager).setResumeAction(eq(KEY), eq(null))
verify(resumeBrowser).testConnection()
- // And since it is, we report back to the manager
- verify(mediaDataManager).setResumeAction(eq(KEY), any())
+ // And since it is, we send info to the manager
+ verify(mediaDataManager).setResumeAction(eq(KEY), isNotNull())
// But we do not tell it to add new controls
verify(mediaDataManager, never())
@@ -291,8 +318,9 @@
// Then we test whether the service is valid and set the resume action
executor.runAllReady()
+ verify(mediaDataManager).setResumeAction(eq(KEY), eq(null))
verify(resumeBrowser).testConnection()
- verify(mediaDataManager).setResumeAction(eq(KEY), capture(actionCaptor))
+ verify(mediaDataManager, times(2)).setResumeAction(eq(KEY), capture(actionCaptor))
// When the resume action is run
actionCaptor.value.run()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
index 46a60dc..7af3743 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -991,8 +991,9 @@
addSecondWidgetForPersonTile();
mManager.updateWidgets(new int[]{WIDGET_ID_WITH_SHORTCUT, SECOND_WIDGET_ID_WITH_SHORTCUT});
- // Delete only one widget for the conversation.
+ // Delete only one widget for the conversation in background.
mManager.deleteWidgets(new int[]{WIDGET_ID_WITH_SHORTCUT});
+ mClock.advanceTime(MIN_LINGER_DURATION);
// Check deleted storage.
SharedPreferences widgetSp = mContext.getSharedPreferences(
@@ -1010,8 +1011,9 @@
eq(Arrays.asList(SHORTCUT_ID)), eq(UserHandle.of(0)),
eq(LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS));
- // Delete all widgets for the conversation.
+ // Delete all widgets for the conversation in background.
mManager.deleteWidgets(new int[]{SECOND_WIDGET_ID_WITH_SHORTCUT});
+ mClock.advanceTime(MIN_LINGER_DURATION);
// Check deleted storage.
SharedPreferences secondWidgetSp = mContext.getSharedPreferences(
@@ -1341,6 +1343,13 @@
PeopleSpaceTile tile = mManager.mTiles.get(WIDGET_ID_WITH_SHORTCUT);
assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_STARRED_CONTACTS);
+
+ setFinalField("suppressedVisualEffects", SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
+ | SUPPRESSED_EFFECT_AMBIENT);
+ mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED);
+
+ tile = mManager.mTiles.get(WIDGET_ID_WITH_SHORTCUT);
+ assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_CONVERSATIONS);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
index 3c1b36e..7ac6f82 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -127,6 +127,11 @@
}
@Test
+ fun testClockNotClickable() {
+ assertThat(clock.isClickable).isFalse()
+ }
+
+ @Test
fun testIgnoredSlotsOnAttached_noIndicators() {
setPrivacyController(micCamera = false, location = false)
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 a435768..32b1f43 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
@@ -16,7 +16,6 @@
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.FeatureFlags
import com.android.systemui.statusbar.policy.NextAlarmController
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
@@ -47,8 +46,6 @@
@Mock
private lateinit var qsLogger: QSLogger
@Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
private lateinit var userTracker: UserTracker
@Mock
private lateinit var nextAlarmController: NextAlarmController
@@ -79,7 +76,6 @@
statusBarStateController,
activityStarter,
qsLogger,
- featureFlags,
userTracker,
nextAlarmController
)
@@ -90,14 +86,7 @@
}
@Test
- fun testNotAvailableFeatureFlag() {
- `when`(featureFlags.isAlarmTileAvailable).thenReturn(false)
- assertThat(tile.isAvailable).isFalse()
- }
-
- @Test
- fun testAvailableFeatureFlag() {
- `when`(featureFlags.isAlarmTileAvailable).thenReturn(true)
+ fun testAvailable() {
assertThat(tile.isAvailable).isTrue()
}
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 09b0427..e4a9aac 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
@@ -69,7 +69,6 @@
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
@@ -118,8 +117,6 @@
private SecureSettings mSecureSettings;
@Mock
private QuickAccessWalletController mController;
- @Mock
- private FeatureFlags mFeatureFlags;
@Captor
ArgumentCaptor<Intent> mIntentCaptor;
@Captor
@@ -139,7 +136,6 @@
doNothing().when(mSpiedContext).startActivity(any(Intent.class));
when(mHost.getContext()).thenReturn(mSpiedContext);
when(mHost.getUiEventLogger()).thenReturn(mUiEventLogger);
- when(mFeatureFlags.isQuickAccessWalletEnabled()).thenReturn(true);
when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(LABEL);
when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
@@ -158,8 +154,7 @@
mKeyguardStateController,
mPackageManager,
mSecureSettings,
- mController,
- mFeatureFlags);
+ mController);
}
@Test
@@ -168,12 +163,6 @@
}
@Test
- public void testIsAvailable_featureFlagIsOff() {
- when(mFeatureFlags.isQuickAccessWalletEnabled()).thenReturn(false);
- assertFalse(mTile.isAvailable());
- }
-
- @Test
public void testWalletServiceUnavailable_recreateWalletClient() {
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java
index d95063f..3a4bc69 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java
@@ -65,7 +65,6 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- Context context = InstrumentationRegistry.getInstrumentation().getContext();
mWm = mock(IWindowManager.class);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
new file mode 100644
index 0000000..c74437f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
@@ -0,0 +1,99 @@
+package com.android.systemui.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.NotificationTestHelper
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
+import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController
+import com.android.systemui.statusbar.policy.HeadsUpUtil
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class NotificationLaunchAnimatorControllerTest : SysuiTestCase() {
+ @Mock lateinit var notificationShadeWindowViewController: NotificationShadeWindowViewController
+ @Mock lateinit var notificationListContainer: NotificationListContainer
+ @Mock lateinit var headsUpManager: HeadsUpManagerPhone
+
+ private lateinit var notificationTestHelper: NotificationTestHelper
+ private lateinit var notification: ExpandableNotificationRow
+ private lateinit var controller: NotificationLaunchAnimatorController
+
+ private val notificationKey: String
+ get() = notification.entry.sbn.key
+
+ @get:Rule val rule = MockitoJUnit.rule()
+
+ @Before
+ fun setUp() {
+ allowTestableLooperAsMainThread()
+ notificationTestHelper =
+ NotificationTestHelper(mContext, mDependency, TestableLooper.get(this))
+ notification = notificationTestHelper.createRow()
+ controller = NotificationLaunchAnimatorController(
+ notificationShadeWindowViewController,
+ notificationListContainer,
+ headsUpManager,
+ notification
+ )
+ }
+
+ private fun flagNotificationAsHun() {
+ `when`(headsUpManager.isAlerting(notificationKey)).thenReturn(true)
+ }
+
+ @Test
+ fun testHunIsRemovedIfWeDontAnimateLaunch() {
+ flagNotificationAsHun()
+ controller.onIntentStarted(willAnimate = false)
+
+ assertTrue(HeadsUpUtil.isClickedHeadsUpNotification(notification))
+ assertFalse(notification.entry.isExpandAnimationRunning)
+ verify(headsUpManager).removeNotification(
+ notificationKey, true /* releaseImmediately */, true /* animate */)
+ }
+
+ @Test
+ fun testHunIsRemovedWhenAnimationIsCancelled() {
+ flagNotificationAsHun()
+ controller.onLaunchAnimationCancelled()
+
+ assertTrue(HeadsUpUtil.isClickedHeadsUpNotification(notification))
+ assertFalse(notification.entry.isExpandAnimationRunning)
+ verify(headsUpManager).removeNotification(
+ notificationKey, true /* releaseImmediately */, true /* animate */)
+ }
+
+ @Test
+ fun testHunIsRemovedWhenAnimationEnds() {
+ flagNotificationAsHun()
+ controller.onLaunchAnimationEnd(isExpandingFullyAbove = true)
+
+ assertFalse(HeadsUpUtil.isClickedHeadsUpNotification(notification))
+ assertFalse(notification.entry.isExpandAnimationRunning)
+ verify(headsUpManager).removeNotification(
+ notificationKey, true /* releaseImmediately */, false /* animate */)
+ }
+
+ @Test
+ fun testNotificationIsExpandingDuringAnimation() {
+ controller.onIntentStarted(willAnimate = true)
+
+ assertTrue(notification.entry.isExpandAnimationRunning)
+ }
+}
\ No newline at end of file
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 8758e16..43f7284 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
@@ -65,6 +65,7 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.KeyguardBypassEnabledProvider;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import org.junit.Assert;
import org.junit.Before;
@@ -105,6 +106,7 @@
@Mock private NotificationSwipeHelper mNotificationSwipeHelper;
@Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
@Mock private FeatureFlags mFeatureFlags;
+ @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@Before
@UiThreadTest
@@ -143,7 +145,8 @@
mGroupMembershipManger,
mGroupExpansionManager,
mAmbientState,
- mFeatureFlags);
+ mFeatureFlags,
+ mUnlockedScreenOffAnimationController);
mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider,
mNotificationSwipeHelper);
mStackScroller = spy(mStackScrollerInternal);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 152ba90..226c466 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -33,7 +33,6 @@
public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
private static final int SCREEN_HEIGHT = 2000;
- private static final int PREFERRED_CLOCK_Y = SCREEN_HEIGHT / 2;
private static final int EMPTY_MARGIN = 0;
private static final int EMPTY_HEIGHT = 0;
private static final float ZERO_DRAG = 0.f;
@@ -48,7 +47,6 @@
private float mPanelExpansion;
private int mKeyguardStatusHeight;
private float mDark;
- private int mPreferredClockY;
private boolean mHasCustomClock;
private boolean mHasVisibleNotifs;
private float mQsExpansion;
@@ -60,21 +58,36 @@
mClockPositionAlgorithm = new KeyguardClockPositionAlgorithm();
mClockPosition = new KeyguardClockPositionAlgorithm.Result();
- mPreferredClockY = PREFERRED_CLOCK_Y;
mHasCustomClock = HAS_CUSTOM_CLOCK;
mHasVisibleNotifs = HAS_VISIBLE_NOTIFS;
}
@Test
- public void clockPositionMiddleOfScreenOnAOD() {
+ public void clockPositionTopOfScreenOnAOD() {
// GIVEN on AOD and both stack scroll and clock have 0 height
givenAOD();
mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
// WHEN the clock position algorithm is run
positionClock();
- // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
- assertThat(mClockPosition.clockY).isEqualTo(1000);
+ // THEN the clock Y position is the top of the screen
+ assertThat(mClockPosition.clockY).isEqualTo(0);
+ // AND the clock is opaque and positioned on the left.
+ assertThat(mClockPosition.clockX).isEqualTo(0);
+ assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+ }
+
+ @Test
+ public void clockPositionBelowCutout() {
+ // GIVEN on AOD and both stack scroll and clock have 0 height
+ givenAOD();
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = EMPTY_HEIGHT;
+ mCutoutTopInset = 300;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position is below the cutout
+ assertThat(mClockPosition.clockY).isEqualTo(300);
// AND the clock is opaque and positioned on the left.
assertThat(mClockPosition.clockX).isEqualTo(0);
assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
@@ -88,8 +101,8 @@
mKeyguardStatusHeight = 100;
// WHEN the clock position algorithm is run
positionClock();
- // THEN the clock Y position adjusts for the clock height (SCREEN_HEIGHT / 2 - 100).
- assertThat(mClockPosition.clockY).isEqualTo(900);
+ // THEN the clock Y position is at the top
+ assertThat(mClockPosition.clockY).isEqualTo(0);
// AND the clock is opaque and positioned on the left.
assertThat(mClockPosition.clockX).isEqualTo(0);
assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
@@ -111,18 +124,17 @@
}
@Test
- public void clockPositionMiddleOfScreenOnLockScreen() {
+ public void clockPositionTopOfScreenOnLockScreen() {
// GIVEN on lock screen with stack scroll and clock of 0 height
givenLockScreen();
mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
// WHEN the clock position algorithm is run
positionClock();
- // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
- assertThat(mClockPosition.clockY).isEqualTo(1000);
- // AND the clock is opaque and positioned on the left.
+ // THEN the clock Y position is the top of the screen
+ assertThat(mClockPosition.clockY).isEqualTo(0);
+ // AND the clock is positioned on the left.
assertThat(mClockPosition.clockX).isEqualTo(0);
- assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
}
@Test
@@ -133,11 +145,10 @@
mKeyguardStatusHeight = EMPTY_HEIGHT;
// WHEN the clock position algorithm is run
positionClock();
- // THEN the clock Y position adjusts for stack scroll height ( (SCREEN_HEIGHT - 500 ) / 2).
- assertThat(mClockPosition.clockY).isEqualTo(750);
- // AND the clock is opaque and positioned on the left.
+ // THEN the clock Y position stays to the top
+ assertThat(mClockPosition.clockY).isEqualTo(0);
+ // AND the clock is positioned on the left.
assertThat(mClockPosition.clockX).isEqualTo(0);
- assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
}
@Test
@@ -182,15 +193,15 @@
}
@Test
- public void notifPositionMiddleOfScreenOnAOD() {
+ public void notifPositionTopOfScreenOnAOD() {
// GIVEN on AOD and both stack scroll and clock have 0 height
givenAOD();
mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
// WHEN the position algorithm is run
positionClock();
- // THEN the notif padding is half of the screen (SCREEN_HEIGHT / 2).
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(1000);
+ // THEN the notif padding is 0 (top of screen)
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
}
@Test
@@ -201,8 +212,8 @@
mKeyguardStatusHeight = 100;
// WHEN the position algorithm is run
positionClock();
- // THEN the notif padding is half of the screen (SCREEN_HEIGHT / 2).
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(1000);
+ // THEN the notif padding adjusts for keyguard status height
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(100);
}
@Test
@@ -225,8 +236,8 @@
mKeyguardStatusHeight = EMPTY_HEIGHT;
// WHEN the position algorithm is run
positionClock();
- // THEN the notif padding is half of the screen (SCREEN_HEIGHT / 2).
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(1000);
+ // THEN the notif are placed to the top of the screen
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
}
@Test
@@ -237,8 +248,8 @@
mKeyguardStatusHeight = EMPTY_HEIGHT;
// WHEN the position algorithm is run
positionClock();
- // THEN the notif padding adjusts for the expanded notif stack.
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(750);
+ // THEN the notif padding adjusts for keyguard status height
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
}
@Test
@@ -250,7 +261,7 @@
// WHEN the position algorithm is run
positionClock();
// THEN the notif padding adjusts for both clock and notif stack.
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(1000);
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(200);
}
@Test
@@ -261,8 +272,8 @@
mKeyguardStatusHeight = 200;
// WHEN the position algorithm is run
positionClock();
- // THEN the notif padding adjusts for both clock and notif stack.
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(810);
+ // THEN the notifs are placed below the statusview
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(200);
}
@Test
@@ -270,12 +281,11 @@
// GIVEN on lock screen and split shade mode
givenLockScreen();
mIsSplitShade = true;
- mPreferredClockY = 100;
mHasCustomClock = true;
// WHEN the position algorithm is run
positionClock();
// THEN the notif padding DOESN'T adjust for keyguard status height.
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(mPreferredClockY);
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
}
@Test
@@ -286,8 +296,8 @@
mKeyguardStatusHeight = SCREEN_HEIGHT;
// WHEN the position algorithm is run
positionClock();
- // THEN the notif padding is half of the screen (SCREEN_HEIGHT / 2).
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(1000);
+ // THEN the notif padding is below keyguard status area
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(SCREEN_HEIGHT);
}
@Test
@@ -317,58 +327,6 @@
}
@Test
- public void preferredCustomClockPositionNoNotifications() {
- // GIVEN on the lock screen with a custom clock and no visible notifications
- givenLockScreen();
- mPreferredClockY = 100;
- mHasCustomClock = true;
- mHasVisibleNotifs = false;
- // AND given empty height for clock and stack scroller
- mNotificationStackHeight = EMPTY_HEIGHT;
- mKeyguardStatusHeight = EMPTY_HEIGHT;
- // WHEN the clock position algorithm is run
- positionClock();
- // THEN the clock Y position is the preferred Y position.
- assertThat(mClockPosition.clockY).isEqualTo(100);
- assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
- }
-
- @Test
- public void preferredDefaultClockPositionNoNotifications() {
- // GIVEN on the lock screen with a custom clock and no visible notifications
- givenLockScreen();
- mPreferredClockY = 100;
- mHasCustomClock = false;
- mHasVisibleNotifs = false;
- // AND given empty height for clock and stack scroller
- mNotificationStackHeight = EMPTY_HEIGHT;
- mKeyguardStatusHeight = EMPTY_HEIGHT;
- // WHEN the clock position algorithm is run
- positionClock();
- // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2) and not
- // preferred.
- assertThat(mClockPosition.clockY).isEqualTo(1000);
- assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
- }
-
- @Test
- public void preferredCustomClockPositionWithVisibleNotifications() {
- // GIVEN on the lock screen with a custom clock and visible notifications
- givenLockScreen();
- mPreferredClockY = 100;
- mHasCustomClock = true;
- mHasVisibleNotifs = true;
- // AND given empty height for clock and stack scroller
- mNotificationStackHeight = EMPTY_HEIGHT;
- mKeyguardStatusHeight = EMPTY_HEIGHT;
- // WHEN the clock position algorithm is run
- positionClock();
- // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
- assertThat(mClockPosition.clockY).isEqualTo(1000);
- assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
- }
-
- @Test
public void clockHiddenWhenQsIsExpanded() {
// GIVEN on the lock screen with a custom clock and visible notifications
givenLockScreen();
@@ -379,22 +337,6 @@
assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
}
- @Test
- public void preferredCustomClockPositionWithVisibleNotificationsOnAod() {
- // GIVEN on the lock screen with a custom clock and visible notifications
- givenAOD();
- mPreferredClockY = 100;
- mHasCustomClock = true;
- mHasVisibleNotifs = true;
- // AND given empty height for clock and stack scroller
- mNotificationStackHeight = EMPTY_HEIGHT;
- mKeyguardStatusHeight = EMPTY_HEIGHT;
- // WHEN the clock position algorithm is run
- positionClock();
- // THEN the clock Y position is the preferred Y position.
- assertThat(mClockPosition.clockY).isEqualTo(100);
- }
-
private void givenAOD() {
mPanelExpansion = 1.f;
mDark = 1.f;
@@ -408,7 +350,7 @@
private void positionClock() {
mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight,
- 0 /* userSwitchHeight */, mPreferredClockY, 0 /* userSwitchPreferredY */,
+ 0 /* userSwitchHeight */, 0 /* userSwitchPreferredY */,
mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
0 /* unlockedStackScrollerPadding */, mQsExpansion,
mCutoutTopInset, mIsSplitShade);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index ffb53a8..c6e5697 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -83,6 +83,7 @@
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSDetailDisplayer;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
@@ -129,6 +130,8 @@
@TestableLooper.RunWithLooper
public class NotificationPanelViewTest extends SysuiTestCase {
+ private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
+
@Mock
private StatusBar mStatusBar;
@Mock
@@ -290,6 +293,8 @@
when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
mDisplayMetrics.density = 100;
when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
+ when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
+ .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
when(mResources.getDimensionPixelSize(R.dimen.qs_panel_width)).thenReturn(400);
when(mResources.getDimensionPixelSize(R.dimen.notification_panel_width)).thenReturn(400);
when(mView.getContext()).thenReturn(getContext());
@@ -638,8 +643,6 @@
public void testCancelSwipeWhileLocked_notifiesKeyguardState() {
mStatusBarStateController.setState(KEYGUARD);
- mNotificationPanelViewController.setOverExpansion(100f, true);
-
// Fling expanded (cancelling the keyguard exit swipe). We should notify keyguard state that
// the fling occurred and did not dismiss the keyguard.
mNotificationPanelViewController.flingToHeight(
@@ -668,6 +671,21 @@
verify(mTapAgainViewController).show();
}
+ @Test
+ public void testNotificationClipping_isAlignedWithNotificationScrimInSplitShade() {
+ mStatusBarStateController.setState(SHADE);
+ QS qs = mock(QS.class);
+ when(qs.getHeader()).thenReturn(mock(View.class));
+ mNotificationPanelViewController.mQs = qs;
+ enableSplitShade();
+
+ // hacky way to refresh notification scrim top with non-zero qsPanelBottom value
+ mNotificationPanelViewController.setTransitionToFullShadeAmount(200, false, 0);
+
+ verify(mAmbientState)
+ .setNotificationScrimTop(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
+ }
+
private FalsingManager.FalsingTapListener getFalsingTapListener() {
for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
listener.onViewAttachedToWindow(mView);
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 deff204..b2efd68 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
@@ -755,7 +755,7 @@
when(mCommandQueue.panelsEnabled()).thenReturn(false);
mStatusBar.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NONE,
StatusBarManager.DISABLE2_NOTIFICATION_SHADE, false);
- verify(mNotificationPanelViewController).setQsExpansionEnabled(false);
+ verify(mNotificationPanelViewController).setQsExpansionEnabledPolicy(false);
mStatusBar.animateExpandNotificationsPanel();
verify(mNotificationPanelViewController, never()).expand(anyBoolean());
mStatusBar.animateExpandSettingsPanel(null);
@@ -764,7 +764,7 @@
when(mCommandQueue.panelsEnabled()).thenReturn(true);
mStatusBar.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NONE,
StatusBarManager.DISABLE2_NONE, false);
- verify(mNotificationPanelViewController).setQsExpansionEnabled(true);
+ verify(mNotificationPanelViewController).setQsExpansionEnabledPolicy(true);
mStatusBar.animateExpandNotificationsPanel();
verify(mNotificationPanelViewController).expandWithoutQs();
mStatusBar.animateExpandSettingsPanel(null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index 3d2a0f1..208790b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -232,9 +232,9 @@
verify(mSecureSettings).putString(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), updatedSetting.capture());
- assertThat(updatedSetting.getValue().contains("android.theme.customization.system_palette"))
+ assertThat(updatedSetting.getValue().contains("android.theme.customization.accent_color"))
.isFalse();
- assertThat(updatedSetting.getValue().contains("android.theme.customization.color_source"))
+ assertThat(updatedSetting.getValue().contains("android.theme.customization.system_palette"))
.isFalse();
assertThat(updatedSetting.getValue().contains("android.theme.customization.color_index"))
.isFalse();
@@ -289,7 +289,8 @@
.thenReturn(jsonString);
when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK)).thenReturn(-1);
- mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+ mColorsListener.getValue().onColorsChanged(mainColors,
+ WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
ArgumentCaptor<String> updatedSetting = ArgumentCaptor.forClass(String.class);
verify(mSecureSettings).putString(
@@ -303,6 +304,60 @@
}
@Test
+ public void onWallpaperColorsChanged_changeLockWallpaper() {
+ // Should ask for a new theme when wallpaper colors change
+ WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
+ Color.valueOf(Color.BLUE), null);
+ String jsonString =
+ "{\"android.theme.customization.system_palette\":\"override.package.name\","
+ + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+ + "\"android.theme.customization.color_index\":\"2\"}";
+ when(mSecureSettings.getStringForUser(
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
+ .thenReturn(jsonString);
+ when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK)).thenReturn(1);
+
+ mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_LOCK);
+
+ ArgumentCaptor<String> updatedSetting = ArgumentCaptor.forClass(String.class);
+ verify(mSecureSettings).putString(
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), updatedSetting.capture());
+ assertThat(updatedSetting.getValue().contains(
+ "android.theme.customization.color_source\":\"lock_wallpaper")).isTrue();
+ assertThat(updatedSetting.getValue().contains("android.theme.customization.color_index"))
+ .isFalse();
+ verify(mThemeOverlayApplier)
+ .applyCurrentUserOverlays(any(), any(), anyInt(), any());
+ }
+
+ @Test
+ public void onWallpaperColorsChanged_changeHomeWallpaper() {
+ // Should ask for a new theme when wallpaper colors change
+ WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
+ Color.valueOf(Color.BLUE), null);
+ String jsonString =
+ "{\"android.theme.customization.system_palette\":\"override.package.name\","
+ + "\"android.theme.customization.color_source\":\"lock_wallpaper\","
+ + "\"android.theme.customization.color_index\":\"2\"}";
+ when(mSecureSettings.getStringForUser(
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
+ .thenReturn(jsonString);
+ when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK)).thenReturn(-1);
+
+ mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+
+ ArgumentCaptor<String> updatedSetting = ArgumentCaptor.forClass(String.class);
+ verify(mSecureSettings).putString(
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), updatedSetting.capture());
+ assertThat(updatedSetting.getValue().contains(
+ "android.theme.customization.color_source\":\"home_wallpaper")).isTrue();
+ assertThat(updatedSetting.getValue().contains("android.theme.customization.color_index"))
+ .isFalse();
+ verify(mThemeOverlayApplier)
+ .applyCurrentUserOverlays(any(), any(), anyInt(), any());
+ }
+
+ @Test
public void onWallpaperColorsChanged_ResetThemeWhenFromLatestWallpaper() {
// Should ask for a new theme when the colors of the last applied wallpaper change
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
@@ -374,8 +429,19 @@
}
@Test
+ public void onUserAdded_appliesTheme_ifNotManagedProfile() {
+ reset(mDeviceProvisionedController);
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(false);
+ mBroadcastReceiver.getValue().onReceive(null,
+ new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED));
+ verify(mThemeOverlayApplier)
+ .applyCurrentUserOverlays(any(), any(), anyInt(), any());
+ }
+
+ @Test
public void onProfileAdded_ignoresUntilSetupComplete() {
reset(mDeviceProvisionedController);
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
mBroadcastReceiver.getValue().onReceive(null,
new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED));
verify(mThemeOverlayApplier, never())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java b/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java
index 9b177e1..5efe05f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java
@@ -84,6 +84,7 @@
private static final String PACKAGE_NAME_1 = "com.example1.test";
private static final Binder TOKEN_1 = new Binder();
private static final Binder WINDOW_TOKEN_1 = new Binder();
+ private static final int USER_ID = 1;
private static final int UID_2 = 10256;
private static final String PACKAGE_NAME_2 = "com.example2.test";
@@ -227,6 +228,14 @@
}
@Test
+ public void testShowToast_accessibilityManagerClientIsRemoved() throws Exception {
+ when(mContextSpy.getUserId()).thenReturn(USER_ID);
+ mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+ null);
+ verify(mAccessibilityManager).removeClient(any(), eq(USER_ID));
+ }
+
+ @Test
public void testHideToast_removesView() throws Exception {
mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
mCallback);
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 01623d6..e6c740b 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
@@ -34,7 +34,6 @@
import android.graphics.drawable.Icon;
import android.os.Handler;
import android.service.quickaccesswallet.GetWalletCardsError;
-import android.service.quickaccesswallet.GetWalletCardsRequest;
import android.service.quickaccesswallet.GetWalletCardsResponse;
import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.service.quickaccesswallet.QuickAccessWalletService;
@@ -44,6 +43,7 @@
import androidx.test.filters.SmallTest;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
@@ -89,15 +89,13 @@
@Mock
FalsingManager mFalsingManager;
@Mock
+ KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
KeyguardStateController mKeyguardStateController;
@Captor
ArgumentCaptor<Intent> mIntentCaptor;
@Captor
- ArgumentCaptor<GetWalletCardsRequest> mRequestCaptor;
- @Captor
ArgumentCaptor<QuickAccessWalletClient.OnWalletCardsRetrievedCallback> mCallbackCaptor;
- @Captor
- ArgumentCaptor<QuickAccessWalletClient.WalletServiceEventListener> mListenerCaptor;
private WalletScreenController mController;
private TestableLooper mTestableLooper;
@@ -114,6 +112,8 @@
when(mWalletClient.getServiceLabel()).thenReturn(SERVICE_LABEL);
when(mWalletClient.createWalletIntent()).thenReturn(mWalletIntent);
when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+ when(mKeyguardUpdateMonitor.isUdfpsEnrolled()).thenReturn(false);
+ when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(false);
mController = new WalletScreenController(
mContext,
mWalletView,
@@ -123,10 +123,61 @@
new Handler(mTestableLooper.getLooper()),
mUserTracker,
mFalsingManager,
+ mKeyguardUpdateMonitor,
mKeyguardStateController);
}
@Test
+ public void queryCards_deviceLocked_udfpsEnabled_hideUnlockButton() {
+ when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true);
+ when(mKeyguardUpdateMonitor.isUdfpsEnrolled()).thenReturn(true);
+ when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+ GetWalletCardsResponse response =
+ new GetWalletCardsResponse(
+ Collections.singletonList(createWalletCard(mContext)), 0);
+
+ mController.queryWalletCards();
+ mTestableLooper.processAllMessages();
+
+ verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
+
+ QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
+ mCallbackCaptor.getValue();
+
+ assertEquals(mController, callback);
+
+ callback.onWalletCardsRetrieved(response);
+ mTestableLooper.processAllMessages();
+
+ assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
+ assertEquals(GONE, mWalletView.getActionButton().getVisibility());
+ }
+
+ @Test
+ public void queryCards_deviceLocked_udfpsNotEnabled_showUnlockButton() {
+ when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+ GetWalletCardsResponse response =
+ new GetWalletCardsResponse(
+ Collections.singletonList(createWalletCard(mContext)), 0);
+
+ mController.queryWalletCards();
+ mTestableLooper.processAllMessages();
+
+ verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
+
+ QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
+ mCallbackCaptor.getValue();
+
+ assertEquals(mController, callback);
+
+ callback.onWalletCardsRetrieved(response);
+ mTestableLooper.processAllMessages();
+
+ assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
+ assertEquals(VISIBLE, mWalletView.getActionButton().getVisibility());
+ }
+
+ @Test
public void queryCards_hasCards_showCarousel_activeCard() {
GetWalletCardsResponse response =
new GetWalletCardsResponse(
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml
index 8c47bcc..adc3086 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Versteek (vermy programme in uitsnede-area)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Lewer programme onder uitsnede-area"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-am/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-am/strings.xml
index 0f1edf6..648e1d4 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-am/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-am/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ደብቅ (በተቆራረጠ ክልል ውስጥ መተግበሪያዎችን ያስወግዱ)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ከተቆረጠው አከባቢ በታች የመተግበሪያዎች ምስልን ስራ"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ar/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ar/strings.xml
index 71f4f7c..2d3b506 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ar/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ar/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"إخفاء (تجنّب التطبيقات في المناطق المقطوعة)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"عرض التطبيقات أسفل منطقة الصورة المقطوعة للشاشة"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-as/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-as/strings.xml
index e462ec6..db2b15a 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-as/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-as/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"লুকুৱাওক (কাটআউট অংশৰ এপ্ বাদ দিয়ক)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"এপ্সমূহ কাটআউট অঞ্চলৰ তলত দেখুৱাওক"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-az/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-az/strings.xml
index fc7e546..a6b7c43 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-az/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-az/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Gizlədin (displey kəsiyində tətbiqlər görünməsin)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Tətbiqləri kəsilmə sahəsinin aşağısında göstərin"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-b+sr+Latn/strings.xml
index c21fcda..f80fa8d 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-b+sr+Latn/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-b+sr+Latn/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Sakrij (izbegavaj aplikacije u izrezanoj oblasti)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Prikazuj aplikacije ispod oblasti izreza"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-be/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-be/strings.xml
index 8ef67a2..0e5c8bc 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-be/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-be/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Схаваць (не паказваць праграмы ў месце выраза)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Візуалізацыя праграм ніжэй месца выраза"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bg/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bg/strings.xml
index 8b81d6a..e97bb57 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bg/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bg/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Скриване (избягване на приложенията в областта на прореза на екрана)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Изобразяване на приложенията под областта на прореза"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bn/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bn/strings.xml
index 15b1fdc..d13c777 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bn/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bn/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"লুকান (কাটআউট অঞ্চলে অ্যাপটি দেখাবেন না)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"কাটআউট এরিয়ার নিচে অ্যাপ রেন্ডার করুন"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bs/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bs/strings.xml
index eb2b8d2..9c9f437 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bs/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bs/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Sakrij (izbjegavaj aplikacije u izrezanoj oblasti)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderovanje aplikacija ispod izrezanog područja"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ca/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ca/strings.xml
index be3e093..e0a577e 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ca/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ca/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Amaga (evita les aplicacions de la regió de retall)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderitza les aplicacions per sota de l\'àrea de retallada"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-cs/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-cs/strings.xml
index 67ed6aff..0f64473 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-cs/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-cs/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Skrýt (nezobrazovat aplikace v oblasti výřezu)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Vykreslovat aplikace pod oblastí výseče"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-da/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-da/strings.xml
index dcf70bf..d0cc43e 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-da/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-da/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Skjul (undgå apps i cutout-område)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Gengiv apps under skærmhakkets område"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-de/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-de/strings.xml
index 86e3732..a7759ea 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-de/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-de/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ausblenden (Apps im Bereich der Display-Aussparung vermeiden)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Apps unterhalb des Aussparungs-Bereichs darstellen"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-el/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-el/strings.xml
index 9806966..b71679a 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-el/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-el/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Απόκρυψη (αποφυγή εφαρμογών στην περιοχή εγκοπής)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Απόδοση εφαρμογών κάτω από την περιοχή εγκοπής"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rAU/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rAU/strings.xml
index a7700b9..8c85cbd 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rAU/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rAU/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Hide (avoid apps in cutout region)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render apps below cutout area"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rCA/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rCA/strings.xml
index a7700b9..8c85cbd 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rCA/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rCA/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Hide (avoid apps in cutout region)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render apps below cutout area"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rGB/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rGB/strings.xml
index a7700b9..8c85cbd 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rGB/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rGB/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Hide (avoid apps in cutout region)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render apps below cutout area"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rIN/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rIN/strings.xml
index a7700b9..8c85cbd 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rIN/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rIN/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Hide (avoid apps in cutout region)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render apps below cutout area"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rXC/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rXC/strings.xml
index e9b76fb..8b72d9f 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rXC/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rXC/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Hide (avoid apps in cutout region)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render apps below cutout area"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es-rUS/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es-rUS/strings.xml
index ee5f8ea..359cdd0 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es-rUS/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es-rUS/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (evitar apps en la región excluida)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar apps debajo del área de recorte"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es/strings.xml
index c244e49..47f525e 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (evitar aplicaciones en la zona recortada)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar aplicaciones por debajo de la zona de recorte"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-et/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-et/strings.xml
index cf84a24..0cc5a25 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-et/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-et/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Peida (rakendusi ei kuvata ekraani väljalõikealal)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Väljalõikeala all olevate rakenduste renderdamine"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-eu/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-eu/strings.xml
index f1a6fda..15d7d60 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-eu/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-eu/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ezkutatu (saihestu aplikazioak agertzea pantailaren mozketa-eremuan)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Errendatu mozketa-eremutik kanpo geratzen diren aplikazioak"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fa/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fa/strings.xml
index f31fad1..0865f75 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fa/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fa/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"پنهان کردن (از برنامههای موجود در منطقه بریدهشده اجتناب میشود)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"پرداز زدن برنامهها در زیر ناحیه بریدهشده"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fi/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fi/strings.xml
index 5e626ee..1a6bf7a 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fi/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fi/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Piilota (vältä lovialueella olevia sovelluksia)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderöi sovellukset lovialueen alle"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr-rCA/strings.xml
index 5c9194e..ea0a27b 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr-rCA/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr-rCA/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Masquer (éviter les applications dans la forme découpée)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Rendre les applications sous la zone de découpe"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr/strings.xml
index 321ee66..6d91a9d 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Masquer (éviter les applis dans la zone de l\'encoche)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Afficher les applis sous la zone d\'encoche"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gl/strings.xml
index a05a5fd..382497b 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gl/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gl/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (non mostrar as aplicacións que aparezan na zona recortada)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar aplicacións que aparezan na zona recortada"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gu/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gu/strings.xml
index 557c791..d578d92 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gu/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gu/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"છુપાવો (કટ આઉટ પ્રદેશમાં ઍપ બાકાત રાખો)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ઍપને કટઆઉટ ક્ષેત્રની નીચે રેન્ડર કરો"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hi/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hi/strings.xml
index c4ab1fe..e1f09f2 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hi/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hi/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"छिपाएं (कटआउट वाले हिस्से में ऐप्लिकेशन न दिखाएं)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ऐप्लिकेशन को कटआउट एरिया के नीचे दिखाएं"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hr/strings.xml
index a2c1feb..db734e8 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hr/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hr/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Sakrij (izbjegavaj aplikacije u području ureza)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderiraj aplikacije ispod područja ureza"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hu/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hu/strings.xml
index e8db0d1..264095b 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hu/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hu/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Elrejtés (a képernyőkivágás területén szereplő alkalmazások elkerülése)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Alkalmazások megjelenítése a kivágási terület alatt"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hy/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hy/strings.xml
index 5b1838d..72e67ec 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hy/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hy/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Թաքցնել (չցուցադրել հավելվածները էկրանի կտրված հատվածում)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Արտապատկերել հավելվածները էկրանի կտրված հատվածի ներքևում"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-in/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-in/strings.xml
index d40d73b..c49bf0c 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-in/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-in/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Sembunyikan (hindari aplikasi di wilayah cutout)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render aplikasi di bawah area potongan"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-is/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-is/strings.xml
index 1a24665..0b90991 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-is/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-is/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Fela (forðast forrit á útklipptu svæði)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Birta forrit fyrir neðan útklippta svæðið"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-it/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-it/strings.xml
index 90b9810..2a0f026b 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-it/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-it/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Nascondi (evita le app nell\'area di ritaglio)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Visualizza le app sotto l\'area di ritaglio"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-iw/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-iw/strings.xml
index 0c4af2d..cc7a0a4 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-iw/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-iw/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"הסתרה (ללא אפליקציות באזור חיתוך התצוגה)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"עיבוד האפליקציות שמתחת לאזור המגרעת"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ja/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ja/strings.xml
index 69b9f24..9e99482 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ja/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ja/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"非表示(カットアウト領域にアプリを表示しない)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"カットアウト領域の下でアプリをレンダリング"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ka/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ka/strings.xml
index 1ee2fae..5464a56 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ka/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ka/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"დამალვა (აპების არდაშვება ჭრილის უბანში)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"აპების ასახვა ჭრილის ქვემოთ"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kk/strings.xml
index 92215247..6a2623f 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kk/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kk/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Жасыру (қолданбалар экран қиығында көрсетілмесін)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Экран ойығының астындағы қолданбаларды көрсету"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-km/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-km/strings.xml
index ea0a9d0..4b4d169 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-km/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-km/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"លាក់ (ជៀសវាងបង្ហាញកម្មវិធីនៅផ្នែកឆក)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"បំប្លែងកម្មវិធីខាងក្រោមផ្នែកឆក"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kn/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kn/strings.xml
index 10176a8..7a929d1 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kn/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kn/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ಮರೆಮಾಡಿ (ಕಟ್ಔಟ್ ಪ್ರದೇಶದಲ್ಲಿ ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸದಂತೆ ತಡೆಯಿರಿ)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ಕಟೌಟ್ ಪ್ರದೇಶದ ಕೆಳಗಿನ ಆ್ಯಪ್ಗಳನ್ನು ರೆಂಡರ್ ಮಾಡಿ"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ko/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ko/strings.xml
index 97856d3..4b9e640 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ko/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ko/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"숨기기(컷아웃 영역에 앱을 표시하지 않음)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"컷아웃 영역 아래에 앱 렌더링"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ky/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ky/strings.xml
index 039bdf0..1ac6a8b 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ky/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ky/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Жашыруу (кесилген аймакта колдонмолор көрсөтүлбөсүн)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Колдонмолорду кесилген аймактын ылдый жагында көрсөтүү"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lo/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lo/strings.xml
index 29ec224..4c38580 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lo/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lo/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ເຊື່ອງ (ຫຼີກເວັ້ນແອັບໃນພື້ນທີ່ຕັດອອກ)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ສະແດງພາບແອັບຢູ່ທາງລຸ່ມພື້ນທີ່ຮອຍເສັ້ນ"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lt/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lt/strings.xml
index 09d8641..c43736d 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lt/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lt/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Slėpti (nerodyti programų ekrano išpjovos srityje)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Pateikti programas po išpjovos sritimi"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lv/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lv/strings.xml
index f2367c6..f95abb6 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lv/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lv/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Paslēpt (nerādīt lietotnes ekrāna izgriezumā)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Atveidot lietotnes zem izgriezuma apgabala"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mk/strings.xml
index 67b45d3..ff236be 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mk/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mk/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Сокриј (избегнувај апликации во отсечен регион)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Прикажувај апликации под отсечената област"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ml/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ml/strings.xml
index 6e88f29..ef728ab 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ml/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ml/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"മറയ്ക്കുക (കട്ടൗട്ട് ഭാഗത്ത് ആപ്പുകൾ കാണിക്കരുത്)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"കട്ടൗട്ട് ഭാഗത്തിന് താഴെ ആപ്പുകൾ റെൻഡർ ചെയ്യുക"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mn/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mn/strings.xml
index 9bda419..23dbe0c 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mn/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mn/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Нуух (тусгаарласан бүс дэх аппуудаас зайлсхийнэ)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Аппуудыг тасалж авсан хэсгийн доор буулгах"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mr/strings.xml
index ecd0c0b..42f09cb 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mr/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mr/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"लपवा (कटआउट भागामध्ये ॲप्स दाखवू नका)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"कटआउट क्षेत्राच्या खाली असलेली ॲप्स रेंडर करा"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ms/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ms/strings.xml
index 5864ff8..e348630 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ms/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ms/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Sembunyikan (elakkan apl dalam kawasan potongan)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Serahkan apl di bawah kawasan potongan"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-my/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-my/strings.xml
index 0f3c0aa..90cb0a5 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-my/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-my/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ဝှက်ရန် (ဖြတ်ထုတ်ထားသောအပိုင်းရှိ အက်ပ်များကို မပြပါနှင့်)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ဖြတ်ထုတ်ထားသော နေရာအောက်ရှိ အက်ပ်များ ပြသရန်"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nb/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nb/strings.xml
index 8a1da68..b8b4e75 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nb/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nb/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Skjul (unngå apper i utklippsregionen)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Gjengi apper under utklippsområdet"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ne/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ne/strings.xml
index 98d7512..bd213bb 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ne/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ne/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"लुकाइयोस् (कटआउट क्षेत्रमा एपहरू नदेखाइयोस्)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"कटआउट गरिएको क्षेत्रभन्दा तल पर्ने एपहरू रेन्डर गर्नुहोस्"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nl/strings.xml
index 0e51514..68f5c07 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nl/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nl/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Verbergen (apps in cutout-regio vermijden)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Apps renderen onder display-cutout"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-or/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-or/strings.xml
index b0552b8..162a29e 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-or/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-or/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ଲୁଚାନ୍ତୁ (କଟଆଉଟ୍ ରିଜନରେ ଆପଗୁଡ଼ିକୁ ଏଡ଼ାନ୍ତୁ)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ଆପଗୁଡ଼ିକୁ କଟଆଉଟ୍ ଏରିଆ ନିମ୍ନରେ ରେଣ୍ଡର୍ କରନ୍ତୁ"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pa/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pa/strings.xml
index 803a69d..908393b 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pa/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pa/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ਲੁਕਾਓ (ਕੱਟਆਊਟ ਖੇਤਰ ਵਿਚਲੀਆਂ ਐਪਾਂ ਨੂੰ ਨਾ ਛੇੜੋ)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ਕੱਟਆਊਟ ਖੇਤਰ ਹੇਠ ਐਪਾਂ ਨੂੰ ਰੈਂਡਰ ਕਰੋ"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pl/strings.xml
index e8d7fb7..c027d52 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pl/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pl/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ukryj (unikaj wyświetlania aplikacji w obszarze wycięcia)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderuj aplikacje pod obszarem wycięcia"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rBR/strings.xml
index b5364e9..d09ed97 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rBR/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rBR/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (evitar apps na região recortada)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar apps abaixo da área de corte"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rPT/strings.xml
index e9467a2..d38ce43 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rPT/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rPT/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (evitar apps na área de recorte)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar apps abaixo da área de recorte"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt/strings.xml
index b5364e9..d09ed97 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (evitar apps na região recortada)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar apps abaixo da área de corte"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ro/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ro/strings.xml
index 9aefb31..6e5947c 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ro/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ro/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ascundeți (se evită aplicațiile în regiunea decupată)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Redați aplicațiile sub zona de decupaj"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ru/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ru/strings.xml
index 8335c77..c7f54bb 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ru/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ru/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Скрыть (не показывать приложения в вырезе на экране)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Отображать приложения под вырезом"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-si/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-si/strings.xml
index d21b02c..4a14a36 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-si/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-si/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"සඟවන්න (කටවුට් කලාපයෙහි යෙදුම් වළක්වන්න)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"කටවුට් ප්රදේශයට පහළින් යෙදුම් විදහන්න"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sk/strings.xml
index dfd01af..98b82e6 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sk/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sk/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Skryť (nezobrazovať aplikácie v oblasti výrezu)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Vykresľovať aplikácie pod oblasťou výrezu"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sl/strings.xml
index 704dfbb..dcf0c84 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sl/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sl/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Skrij (izogibaj se aplikacijam na območju zareze)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Upodobitev aplikacij pod predelom zareze zaslona"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sq/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sq/strings.xml
index 8035d7f..d7b0676 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sq/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sq/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Fshih (shmang aplikacionet në zonën e prerë)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Paraqiti aplikacionet poshtë zonës së prerjes"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sr/strings.xml
index c835b35..c2b611e 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sr/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sr/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Сакриј (избегавај апликације у изрезаној области)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Приказуј апликације испод области изреза"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sv/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sv/strings.xml
index a8fd157..3007ffb 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sv/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sv/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Dölj (visa inte appar i skärmutskärningen)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Visa appar under skärmutskärningens område"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sw/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sw/strings.xml
index 57ef684..b605554 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sw/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sw/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ficha (epuka programu katika eneo lenye pengo)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Usionyeshe programu chini ya eneo lenye pengo"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ta/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ta/strings.xml
index c0506cf..c4d06fb 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ta/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ta/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"மறை (திரை மறையும் பகுதியில் ஆப்ஸைக் காட்ட வேண்டாம்)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"கட் அவுட் பகுதிக்குள்ளாக ஆப்ஸை ரெண்டர் செய்"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-te/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-te/strings.xml
index db2a797..08fa4ae 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-te/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-te/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"దాచండి (కట్అవుట్ ప్రాంతంలో యాప్లను నివారించండి)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"కట్అవుట్ ఏరియా కింద యాప్లను రెండర్ చేయండి"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-th/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-th/strings.xml
index 09d597d..9a30250 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-th/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-th/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ซ่อน (หลีกเลี่ยงการแสดงแอปในภูมิภาคที่ถูกตัดออก)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"แสดงผลแอปใต้บริเวณรอยบาก"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tl/strings.xml
index 6b1c372..a3d4a3a 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tl/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tl/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Itago (iwasan ang mga app sa rehiyon ng cutout)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"I-render ang mga app sa ibaba ng lugar ng cutout"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tr/strings.xml
index 991a840..12e0f30 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tr/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tr/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Gizle (kesim bölgesindeki uygulamalardan kaçının)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Uygulamaları kesme alanının altında oluşturun"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uk/strings.xml
index 7d6c068..08b1521 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uk/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uk/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Сховати (не показувати додатки з вирізаних регіонів)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Відображати додатки під областю вирізу екрана"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ur/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ur/strings.xml
index 48c5d14..711b538 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ur/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ur/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"چھپائیں (کٹ آؤٹ والے علاقے میں ایپس سے اجتناب کریں)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"کٹ آؤٹ ایریا کے نیچے رینڈر ایپس"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uz/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uz/strings.xml
index 13a56ac..7f6f2b4 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uz/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uz/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Berkitish (qirqilgan hudud ilovalariga diqqat qiling)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Ekran kesimi quyidagi ilovalarni renderlash"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-vi/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-vi/strings.xml
index 2217862..a7d54fb 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-vi/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-vi/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ẩn (không hiện các ứng dụng ở vùng cắt)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Hiển thị các ứng dụng bên dưới khu vực có vết cắt"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rCN/strings.xml
index 3d672b4..f596520 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rCN/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rCN/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"隐藏(避免应用显示在凹口区域)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"在刘海区域下方呈现应用"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rHK/strings.xml
index 7f37f3b..ddb1df7 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rHK/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rHK/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"隱藏 (避免將應用程式置於凹口區域)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"在凹口區域下方輸出應用程式"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rTW/strings.xml
index ff50ddb..7aad79c 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rTW/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rTW/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"隱藏 (避免在螢幕凹口顯示應用程式的內容)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"在螢幕凹口底下顯示應用程式畫面"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zu/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zu/strings.xml
index d6d7727..d861c5e 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zu/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zu/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Fihla (gwema ama-app kwisifunda esikhishiwe)"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Nikezela ngama-app angaphansi kwendawo yokukhipha"</string>
</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values/strings.xml
index a65fd43..49010da 100644
--- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values/strings.xml
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- [CHAR_LIMIT=NONE] Developer Settings: Label for the option that masks the display cutout, i.e. avoid apps in cutout region.-->
- <string name="display_cutout_emulation_overlay">Hide (avoid apps in cutout region)</string>
+ <string name="display_cutout_emulation_overlay">Render apps below cutout area</string>
</resources>
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java
index d44a417..7b9ca2d 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java
@@ -119,20 +119,32 @@
private static final String CAMERA_EXTENSION_VERSION_NAME =
"androidx.camera.extensions.impl.ExtensionVersionImpl";
private static final String LATEST_VERSION = "1.2.0";
- private static final String LEGACY_VERSION_PREFIX = "1.1";
+ private static final String NON_INIT_VERSION_PREFIX = "1.0";
private static final String ADVANCED_VERSION_PREFIX = "1.2";
private static final String[] SUPPORTED_VERSION_PREFIXES = {ADVANCED_VERSION_PREFIX,
- LEGACY_VERSION_PREFIX, "1.0."};
+ "1.1", NON_INIT_VERSION_PREFIX};
private static final boolean EXTENSIONS_PRESENT = checkForExtensions();
private static final String EXTENSIONS_VERSION = EXTENSIONS_PRESENT ?
(new ExtensionVersionImpl()).checkApiVersion(LATEST_VERSION) : null;
- private static final boolean LEGACY_VERSION_SUPPORTED =
- EXTENSIONS_PRESENT && EXTENSIONS_VERSION.startsWith(LEGACY_VERSION_PREFIX);
- private static final boolean ADVANCED_VERSION_SUPPORTED =
- EXTENSIONS_PRESENT && EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX);
+ private static final boolean ADVANCED_API_SUPPORTED = checkForAdvancedAPI();
+ private static final boolean INIT_API_SUPPORTED = EXTENSIONS_PRESENT &&
+ (!EXTENSIONS_VERSION.startsWith(NON_INIT_VERSION_PREFIX));
private HashMap<String, CameraCharacteristics> mCharacteristicsHashMap = new HashMap<>();
+ private static boolean checkForAdvancedAPI() {
+ if (EXTENSIONS_PRESENT && EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) {
+ try {
+ return (new ExtensionVersionImpl()).isAdvancedExtenderImplemented();
+ } catch (NoSuchMethodError e) {
+ // This could happen in case device specific extension implementations are using an
+ // older extension API but incorrectly set the extension version.
+ }
+ }
+
+ return false;
+ }
+
private static boolean checkForExtensions() {
try {
Class.forName(CAMERA_EXTENSION_VERSION_NAME);
@@ -265,7 +277,7 @@
public long registerClient(Context ctx) {
synchronized (mLock) {
- if (LEGACY_VERSION_SUPPORTED) {
+ if (INIT_API_SUPPORTED) {
if (mActiveClients.isEmpty()) {
InitializerFuture status = new InitializerFuture();
InitializerImpl.init(EXTENSIONS_VERSION, ctx, new InitializeHandler(status),
@@ -299,7 +311,7 @@
public void unregisterClient(long clientId) {
synchronized (mLock) {
if (mActiveClients.remove(clientId) && mActiveClients.isEmpty() &&
- LEGACY_VERSION_SUPPORTED) {
+ INIT_API_SUPPORTED) {
InitializerFuture status = new InitializerFuture();
InitializerImpl.deinit(new ReleaseHandler(status),
new HandlerExecutor(mHandler));
@@ -528,7 +540,7 @@
@Override
public boolean advancedExtensionsSupported() {
- return ADVANCED_VERSION_SUPPORTED;
+ return ADVANCED_API_SUPPORTED;
}
@Override
@@ -819,10 +831,11 @@
}
@Override
- public void onNextImageAvailable(OutputConfigId outputConfigId, ParcelImage img) {
+ public void onNextImageAvailable(OutputConfigId outputConfigId, ParcelImage img,
+ String physicalCameraId) {
if (mImageProcessor != null) {
mImageProcessor.onNextImageAvailable(outputConfigId.id, img.timestamp,
- new ImageReferenceImpl(img));
+ new ImageReferenceImpl(img), physicalCameraId);
}
}
}
@@ -1072,9 +1085,7 @@
@Override
public void init(String cameraId, CameraMetadataNative chars) {
- if (LEGACY_VERSION_SUPPORTED) {
- mPreviewExtender.init(cameraId, new CameraCharacteristics(chars));
- }
+ mPreviewExtender.init(cameraId, new CameraCharacteristics(chars));
}
@Override
@@ -1136,7 +1147,7 @@
@Override
public List<SizeList> getSupportedResolutions() {
- if (LEGACY_VERSION_SUPPORTED) {
+ if (INIT_API_SUPPORTED) {
List<Pair<Integer, android.util.Size[]>> sizes =
mPreviewExtender.getSupportedResolutions();
if ((sizes != null) && !sizes.isEmpty()) {
@@ -1182,9 +1193,7 @@
@Override
public void init(String cameraId, CameraMetadataNative chars) {
- if (LEGACY_VERSION_SUPPORTED) {
- mImageExtender.init(cameraId, new CameraCharacteristics(chars));
- }
+ mImageExtender.init(cameraId, new CameraCharacteristics(chars));
}
@Override
@@ -1228,7 +1237,7 @@
@Override
public List<SizeList> getSupportedResolutions() {
- if (LEGACY_VERSION_SUPPORTED) {
+ if (INIT_API_SUPPORTED) {
List<Pair<Integer, android.util.Size[]>> sizes =
mImageExtender.getSupportedResolutions();
if ((sizes != null) && !sizes.isEmpty()) {
@@ -1238,6 +1247,23 @@
return null;
}
+
+ @Override
+ public LatencyRange getEstimatedCaptureLatencyRange(
+ android.hardware.camera2.extension.Size outputSize) {
+ if (EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) {
+ Size sz = new Size(outputSize.width, outputSize.height);
+ Range<Long> latencyRange = mImageExtender.getEstimatedCaptureLatencyRange(sz);
+ if (latencyRange != null) {
+ LatencyRange ret = new LatencyRange();
+ ret.min = latencyRange.getLower();
+ ret.max = latencyRange.getUpper();
+ return ret;
+ }
+ }
+
+ return null;
+ }
}
private class CaptureProcessorImplStub extends ICaptureProcessorImpl.Stub {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 4e14411..acbf487 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -2186,10 +2186,6 @@
return false;
}
- if (!ri.activityInfo.isEnabled()) {
- return false;
- }
-
ComponentName componentName = new ComponentName(ri.activityInfo.packageName,
ri.activityInfo.name);
ProviderId providerId = new ProviderId(ri.activityInfo.applicationInfo.uid, componentName);
diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
index e248b21..b2f5396 100644
--- a/services/core/java/com/android/server/MasterClearReceiver.java
+++ b/services/core/java/com/android/server/MasterClearReceiver.java
@@ -16,19 +16,29 @@
package com.android.server;
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
+import android.os.Binder;
import android.os.RecoverySystem;
+import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Slog;
import android.view.WindowManager;
import com.android.internal.R;
+import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.internal.notification.SystemNotificationChannels;
+import com.android.server.utils.Slogf;
import java.io.IOException;
@@ -71,6 +81,19 @@
final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, false)
|| intent.getBooleanExtra(Intent.EXTRA_FORCE_FACTORY_RESET, false);
+ // TODO(b/189938391): properly handle factory reset on headless system user mode.
+ final int sendingUserId = getSendingUserId();
+ if (sendingUserId != UserHandle.USER_SYSTEM && !UserManager.isHeadlessSystemUserMode()) {
+ Slogf.w(
+ TAG,
+ "ACTION_FACTORY_RESET received on a non-system user %d, WIPING THE USER!!",
+ sendingUserId);
+ if (!Binder.withCleanCallingIdentity(() -> wipeUser(context, sendingUserId, reason))) {
+ Slogf.e(TAG, "Failed to wipe user %d", sendingUserId);
+ }
+ return;
+ }
+
Slog.w(TAG, "!!! FACTORY RESET !!!");
// The reboot call is blocking, so we need to do it on another thread.
Thread thr = new Thread("Reboot") {
@@ -101,6 +124,55 @@
}
}
+ private boolean wipeUser(Context context, @UserIdInt int userId, String wipeReason) {
+ final UserManager userManager = context.getSystemService(UserManager.class);
+ final int result = userManager.removeUserOrSetEphemeral(
+ userId, /* evenWhenDisallowed= */ false);
+ if (result == UserManager.REMOVE_RESULT_ERROR) {
+ Slogf.e(TAG, "Can't remove user %d", userId);
+ return false;
+ }
+ if (getCurrentForegroundUserId() == userId) {
+ try {
+ if (!ActivityManager.getService().switchUser(UserHandle.USER_SYSTEM)) {
+ Slogf.w(TAG, "Can't switch from current user %d, user will get removed when "
+ + "it is stopped.", userId);
+
+ }
+ } catch (RemoteException e) {
+ Slogf.w(TAG, "Can't switch from current user %d, user will get removed when "
+ + "it is stopped.", userId);
+ }
+ }
+ if (userManager.isManagedProfile(userId)) {
+ sendWipeProfileNotification(context, wipeReason);
+ }
+ return true;
+ }
+
+ // This method is copied from DevicePolicyManagedService.
+ private void sendWipeProfileNotification(Context context, String wipeReason) {
+ final Notification notification =
+ new Notification.Builder(context, SystemNotificationChannels.DEVICE_ADMIN)
+ .setSmallIcon(android.R.drawable.stat_sys_warning)
+ .setContentTitle(context.getString(R.string.work_profile_deleted))
+ .setContentText(wipeReason)
+ .setColor(context.getColor(R.color.system_notification_accent_color))
+ .setStyle(new Notification.BigTextStyle().bigText(wipeReason))
+ .build();
+ context.getSystemService(NotificationManager.class).notify(
+ SystemMessageProto.SystemMessage.NOTE_PROFILE_WIPED, notification);
+ }
+
+ private @UserIdInt int getCurrentForegroundUserId() {
+ try {
+ return ActivityManager.getCurrentUser();
+ } catch (Exception e) {
+ Slogf.e(TAG, "Can't get current user", e);
+ }
+ return UserHandle.USER_NULL;
+ }
+
private class WipeDataTask extends AsyncTask<Void, Void, Void> {
private final Thread mChainedTask;
private final Context mContext;
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 84f40cb..a481a6a 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -61,6 +61,7 @@
private static final String MDNS_TAG = "mDnsConnector";
private static final boolean DBG = true;
+ private static final long CLEANUP_DELAY_MS = 3000;
private final Context mContext;
private final NsdSettings mNsdSettings;
@@ -77,6 +78,7 @@
private final SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<>();
private final AsyncChannel mReplyChannel = new AsyncChannel();
+ private final long mCleanupDelayMs;
private static final int INVALID_ID = 0;
private int mUniqueId = 1;
@@ -92,6 +94,22 @@
return NsdManager.nameOf(what);
}
+ void maybeStartDaemon() {
+ mDaemon.maybeStart();
+ maybeScheduleStop();
+ }
+
+ void maybeScheduleStop() {
+ if (!isAnyRequestActive()) {
+ cancelStop();
+ sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs);
+ }
+ }
+
+ void cancelStop() {
+ this.removeMessages(NsdManager.DAEMON_CLEANUP);
+ }
+
/**
* Observes the NSD on/off setting, and takes action when changed.
*/
@@ -151,10 +169,6 @@
cInfo.expungeAllRequests();
mClients.remove(msg.replyTo);
}
- //Last client
- if (mClients.size() == 0) {
- mDaemon.stop();
- }
break;
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
AsyncChannel ac = new AsyncChannel();
@@ -180,6 +194,9 @@
replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
NsdManager.FAILURE_INTERNAL_ERROR);
break;
+ case NsdManager.DAEMON_CLEANUP:
+ mDaemon.maybeStop();
+ break;
case NsdManager.NATIVE_DAEMON_EVENT:
default:
Slog.e(TAG, "Unhandled " + msg);
@@ -212,16 +229,13 @@
@Override
public void enter() {
sendNsdStateChangeBroadcast(true);
- if (mClients.size() > 0) {
- mDaemon.start();
- }
}
@Override
public void exit() {
- if (mClients.size() > 0) {
- mDaemon.stop();
- }
+ // TODO: it is incorrect to stop the daemon without expunging all requests
+ // and sending error callbacks to clients.
+ maybeScheduleStop();
}
private boolean requestLimitReached(ClientInfo clientInfo) {
@@ -236,12 +250,15 @@
clientInfo.mClientIds.put(clientId, globalId);
clientInfo.mClientRequests.put(clientId, what);
mIdToClientInfoMap.put(globalId, clientInfo);
+ // Remove the cleanup event because here comes a new request.
+ cancelStop();
}
private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
clientInfo.mClientIds.delete(clientId);
clientInfo.mClientRequests.delete(clientId);
mIdToClientInfoMap.remove(globalId);
+ maybeScheduleStop();
}
@Override
@@ -251,14 +268,12 @@
int id;
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
- //First client
- if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL &&
- mClients.size() == 0) {
- mDaemon.start();
- }
return NOT_HANDLED;
case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
return NOT_HANDLED;
+ }
+
+ switch (msg.what) {
case NsdManager.DISABLE:
//TODO: cleanup clients
transitionTo(mDisabledState);
@@ -274,6 +289,7 @@
break;
}
+ maybeStartDaemon();
id = getUniqueId();
if (discoverServices(id, servInfo.getServiceType())) {
if (DBG) {
@@ -316,6 +332,7 @@
break;
}
+ maybeStartDaemon();
id = getUniqueId();
if (registerService(id, (NsdServiceInfo) msg.obj)) {
if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id);
@@ -357,6 +374,7 @@
break;
}
+ maybeStartDaemon();
id = getUniqueId();
if (resolveService(id, servInfo)) {
clientInfo.mResolvedService = new NsdServiceInfo();
@@ -513,6 +531,10 @@
}
}
+ private boolean isAnyRequestActive() {
+ return mIdToClientInfoMap.size() != 0;
+ }
+
private String unescape(String s) {
StringBuilder sb = new StringBuilder(s.length());
for (int i = 0; i < s.length(); ++i) {
@@ -538,7 +560,9 @@
}
@VisibleForTesting
- NsdService(Context ctx, NsdSettings settings, Handler handler, DaemonConnectionSupplier fn) {
+ NsdService(Context ctx, NsdSettings settings, Handler handler,
+ DaemonConnectionSupplier fn, long cleanupDelayMs) {
+ mCleanupDelayMs = cleanupDelayMs;
mContext = ctx;
mNsdSettings = settings;
mNsdStateMachine = new NsdStateMachine(TAG, handler);
@@ -552,7 +576,8 @@
HandlerThread thread = new HandlerThread(TAG);
thread.start();
Handler handler = new Handler(thread.getLooper());
- NsdService service = new NsdService(context, settings, handler, DaemonConnection::new);
+ NsdService service = new NsdService(context, settings, handler,
+ DaemonConnection::new, CLEANUP_DELAY_MS);
service.mDaemonCallback.awaitConnection();
return service;
}
@@ -681,12 +706,16 @@
@VisibleForTesting
public static class DaemonConnection {
final NativeDaemonConnector mNativeConnector;
+ boolean mIsStarted = false;
DaemonConnection(NativeCallbackReceiver callback) {
mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null);
new Thread(mNativeConnector, MDNS_TAG).start();
}
+ /**
+ * Executes the specified cmd on the daemon.
+ */
public boolean execute(Object... args) {
if (DBG) {
Slog.d(TAG, "mdnssd " + Arrays.toString(args));
@@ -700,12 +729,26 @@
return true;
}
- public void start() {
+ /**
+ * Starts the daemon if it is not already started.
+ */
+ public void maybeStart() {
+ if (mIsStarted) {
+ return;
+ }
execute("start-service");
+ mIsStarted = true;
}
- public void stop() {
+ /**
+ * Stops the daemon if it is started.
+ */
+ public void maybeStop() {
+ if (!mIsStarted) {
+ return;
+ }
execute("stop-service");
+ mIsStarted = false;
}
}
@@ -864,6 +907,7 @@
}
mClientIds.clear();
mClientRequests.clear();
+ mNsdStateMachine.maybeScheduleStop();
}
// mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id,
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 7e2274b..f9fd108 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.DUMP;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
@@ -36,6 +37,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
@@ -73,6 +75,7 @@
import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.internal.util.IndentingPrintWriter;
import com.android.net.module.util.LocationPermissionChecker;
+import com.android.net.module.util.PermissionUtils;
import com.android.server.vcn.TelephonySubscriptionTracker;
import com.android.server.vcn.Vcn;
import com.android.server.vcn.VcnContext;
@@ -739,9 +742,10 @@
@NonNull IVcnUnderlyingNetworkPolicyListener listener) {
requireNonNull(listener, "listener was null");
- mContext.enforceCallingOrSelfPermission(
+ PermissionUtils.enforceAnyPermissionOf(
+ mContext,
android.Manifest.permission.NETWORK_FACTORY,
- "Must have permission NETWORK_FACTORY to register a policy listener");
+ android.Manifest.permission.MANAGE_TEST_NETWORKS);
Binder.withCleanCallingIdentity(() -> {
PolicyListenerBinderDeath listenerBinderDeath = new PolicyListenerBinderDeath(listener);
@@ -766,9 +770,10 @@
@NonNull IVcnUnderlyingNetworkPolicyListener listener) {
requireNonNull(listener, "listener was null");
- mContext.enforceCallingOrSelfPermission(
+ PermissionUtils.enforceAnyPermissionOf(
+ mContext,
android.Manifest.permission.NETWORK_FACTORY,
- "Must have permission NETWORK_FACTORY to unregister a policy listener");
+ android.Manifest.permission.MANAGE_TEST_NETWORKS);
Binder.withCleanCallingIdentity(() -> {
synchronized (mLock) {
@@ -819,10 +824,20 @@
requireNonNull(networkCapabilities, "networkCapabilities was null");
requireNonNull(linkProperties, "linkProperties was null");
- mContext.enforceCallingOrSelfPermission(
+ PermissionUtils.enforceAnyPermissionOf(
+ mContext,
android.Manifest.permission.NETWORK_FACTORY,
- "Must have permission NETWORK_FACTORY or be the SystemServer to get underlying"
- + " Network policies");
+ android.Manifest.permission.MANAGE_TEST_NETWORKS);
+
+ final boolean isUsingManageTestNetworks =
+ mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_FACTORY)
+ != PackageManager.PERMISSION_GRANTED;
+
+ if (isUsingManageTestNetworks && !networkCapabilities.hasTransport(TRANSPORT_TEST)) {
+ throw new IllegalStateException(
+ "NetworkCapabilities must be for Test Network if using permission"
+ + " MANAGE_TEST_NETWORKS");
+ }
return Binder.withCleanCallingIdentity(() -> {
// Defensive copy in case this call is in-process and the given NetworkCapabilities
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index afaddd9..8aea4a9 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -250,6 +250,14 @@
final ArrayList<ServiceRecord> mPendingFgsNotifications = new ArrayList<>();
/**
+ * Whether there is a rate limit that suppresses immediate re-deferral of new FGS
+ * notifications from each app. On by default, disabled only by shell command for
+ * test-suite purposes. To disable the behavior more generally, use the usual
+ * DeviceConfig mechanism to set the rate limit interval to zero.
+ */
+ private boolean mFgsDeferralRateLimited = true;
+
+ /**
* Uptime at which a given uid becomes eliglible again for FGS notification deferral
*/
final SparseLongArray mFgsDeferralEligible = new SparseLongArray();
@@ -2142,8 +2150,10 @@
}
}
- final long nextEligible = when + mAm.mConstants.mFgsNotificationDeferralExclusionTime;
- mFgsDeferralEligible.put(uid, nextEligible);
+ if (mFgsDeferralRateLimited) {
+ final long nextEligible = when + mAm.mConstants.mFgsNotificationDeferralExclusionTime;
+ mFgsDeferralEligible.put(uid, nextEligible);
+ }
r.fgDisplayTime = when;
r.mFgsNotificationDeferred = true;
r.mFgsNotificationShown = false;
@@ -2204,6 +2214,38 @@
}
};
+ /**
+ * Suppress or reenable the rate limit on foreground service notification deferral.
+ * Invoked from the activity manager shell command.
+ *
+ * @param enable false to suppress rate-limit policy; true to reenable it.
+ */
+ boolean enableFgsNotificationRateLimitLocked(final boolean enable) {
+ if (enable != mFgsDeferralRateLimited) {
+ mFgsDeferralRateLimited = enable;
+ if (!enable) {
+ // make sure to reset any active rate limiting
+ mFgsDeferralEligible.clear();
+ }
+ }
+ return enable;
+ }
+
+ private void removeServiceNotificationDeferralsLocked(String packageName,
+ final @UserIdInt int userId) {
+ for (int i = mPendingFgsNotifications.size() - 1; i >= 0; i--) {
+ final ServiceRecord r = mPendingFgsNotifications.get(i);
+ if (userId == r.userId
+ && r.appInfo.packageName.equals(packageName)) {
+ mPendingFgsNotifications.remove(i);
+ if (DEBUG_FOREGROUND_SERVICE) {
+ Slog.d(TAG_SERVICE, "Removing notification deferral for "
+ + r);
+ }
+ }
+ }
+ }
+
private void maybeLogFGSStateEnteredLocked(ServiceRecord r) {
if (r.mLogEntering) {
logFGSStateChangeLocked(r,
@@ -4689,6 +4731,7 @@
}
}
removeServiceRestartBackoffEnabledLocked(packageName);
+ removeServiceNotificationDeferralsLocked(packageName, userId);
}
void cleanUpServices(int userId, ComponentName component, Intent baseIntent) {
@@ -4865,7 +4908,8 @@
Slog.w(TAG, "Service crashed " + sr.crashCount
+ " times, stopping: " + sr);
EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
- sr.userId, sr.crashCount, sr.shortInstanceName, sr.app.getPid());
+ sr.userId, sr.crashCount, sr.shortInstanceName,
+ sr.app != null ? sr.app.getPid() : -1);
bringDownServiceLocked(sr, true);
} else if (!allowRestart
|| !mAm.mUserController.isUserRunning(sr.userId, 0)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6b0e2db..2de091b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5996,13 +5996,23 @@
public final ContentProviderHolder getContentProvider(
IApplicationThread caller, String callingPackage, String name, int userId,
boolean stable) {
- return mCpHelper.getContentProvider(caller, callingPackage, name, userId, stable);
+ traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "getContentProvider: ", name);
+ try {
+ return mCpHelper.getContentProvider(caller, callingPackage, name, userId, stable);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
@Override
public ContentProviderHolder getContentProviderExternal(
String name, int userId, IBinder token, String tag) {
- return mCpHelper.getContentProviderExternal(name, userId, token, tag);
+ traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "getContentProviderExternal: ", name);
+ try {
+ return mCpHelper.getContentProviderExternal(name, userId, token, tag);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
/**
@@ -6017,18 +6027,57 @@
@Deprecated
@Override
public void removeContentProviderExternal(String name, IBinder token) {
- removeContentProviderExternalAsUser(name, token, UserHandle.getCallingUserId());
+ traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "removeContentProviderExternal: ", name);
+ try {
+ removeContentProviderExternalAsUser(name, token, UserHandle.getCallingUserId());
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
@Override
public void removeContentProviderExternalAsUser(String name, IBinder token, int userId) {
- mCpHelper.removeContentProviderExternalAsUser(name, token, userId);
+ traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "removeContentProviderExternalAsUser: ", name);
+ try {
+ mCpHelper.removeContentProviderExternalAsUser(name, token, userId);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
@Override
public final void publishContentProviders(IApplicationThread caller,
List<ContentProviderHolder> providers) {
- mCpHelper.publishContentProviders(caller, providers);
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+ final int maxLength = 256;
+ final StringBuilder sb = new StringBuilder(maxLength);
+ sb.append("publishContentProviders: ");
+ if (providers != null) {
+ boolean first = true;
+ for (int i = 0, size = providers.size(); i < size; i++) {
+ final ContentProviderHolder holder = providers.get(i);
+ if (holder != null && holder.info != null && holder.info.authority != null) {
+ final int len = holder.info.authority.length();
+ if (sb.length() + len > maxLength) {
+ sb.append("[[TRUNCATED]]");
+ break;
+ }
+ if (!first) {
+ sb.append(';');
+ } else {
+ first = false;
+ }
+ sb.append(holder.info.authority);
+ }
+ }
+ }
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, sb.toString());
+ }
+ try {
+ mCpHelper.publishContentProviders(caller, providers);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
@Override
@@ -7075,53 +7124,60 @@
if (Binder.getCallingUid() != SYSTEM_UID) {
throw new SecurityException("killPids only available to the system");
}
- String reason = (pReason == null) ? "Unknown" : pReason;
+ final String reason = (pReason == null) ? "Unknown" : pReason;
// XXX Note: don't acquire main activity lock here, because the window
// manager calls in with its locks held.
boolean killed = false;
- synchronized (this) {
- synchronized (mProcLock) {
- synchronized (mPidsSelfLocked) {
- int worstType = 0;
- for (int i = 0; i < pids.length; i++) {
- ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
- if (proc != null) {
- int type = proc.mState.getSetAdj();
- if (type > worstType) {
- worstType = type;
- }
- }
- }
-
- // If the worst oom_adj is somewhere in the cached proc LRU range,
- // then constrain it so we will kill all cached procs.
- if (worstType < ProcessList.CACHED_APP_MAX_ADJ
- && worstType > ProcessList.CACHED_APP_MIN_ADJ) {
- worstType = ProcessList.CACHED_APP_MIN_ADJ;
- }
-
- // If this is not a secure call, don't let it kill processes that
- // are important.
- if (!secure && worstType < ProcessList.SERVICE_ADJ) {
- worstType = ProcessList.SERVICE_ADJ;
- }
-
- Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
- for (int i = 0; i < pids.length; i++) {
- ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
- if (proc == null) {
- continue;
- }
- int adj = proc.mState.getSetAdj();
- if (adj >= worstType && !proc.isKilledByAm()) {
- proc.killLocked(reason, ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_KILL_PID, true);
- killed = true;
- }
+ final ArrayList<ProcessRecord> killCandidates = new ArrayList<>();
+ synchronized (mPidsSelfLocked) {
+ int worstType = 0;
+ for (int i = 0; i < pids.length; i++) {
+ ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
+ if (proc != null) {
+ int type = proc.mState.getSetAdj();
+ if (type > worstType) {
+ worstType = type;
}
}
}
+
+ // If the worst oom_adj is somewhere in the cached proc LRU range,
+ // then constrain it so we will kill all cached procs.
+ if (worstType < ProcessList.CACHED_APP_MAX_ADJ
+ && worstType > ProcessList.CACHED_APP_MIN_ADJ) {
+ worstType = ProcessList.CACHED_APP_MIN_ADJ;
+ }
+
+ // If this is not a secure call, don't let it kill processes that
+ // are important.
+ if (!secure && worstType < ProcessList.SERVICE_ADJ) {
+ worstType = ProcessList.SERVICE_ADJ;
+ }
+
+ Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
+ for (int i = 0; i < pids.length; i++) {
+ ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
+ if (proc == null) {
+ continue;
+ }
+ int adj = proc.mState.getSetAdj();
+ if (adj >= worstType && !proc.isKilledByAm()) {
+ killCandidates.add(proc);
+ killed = true;
+ }
+ }
+ }
+ if (!killCandidates.isEmpty()) {
+ mHandler.post(() -> {
+ synchronized (ActivityManagerService.this) {
+ for (int i = 0, size = killCandidates.size(); i < size; i++) {
+ killCandidates.get(i).killLocked(reason,
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_KILL_PID, true);
+ }
+ }
+ });
}
return killed;
}
@@ -7842,7 +7898,9 @@
incrementalMetrics != null ? incrementalMetrics.getMillisSinceLastReadError()
: -1,
incrementalMetrics != null ? incrementalMetrics.getLastReadErrorNumber()
- : 0
+ : 0,
+ incrementalMetrics != null ? incrementalMetrics.getTotalDelayedReadsDurationMillis()
+ : -1
);
final int relaunchReason = r == null ? RELAUNCH_REASON_NONE
@@ -14258,7 +14316,7 @@
private boolean checkExcessivePowerUsageLPr(final long uptimeSince, boolean doCpuKills,
final long cputimeUsed, final String processName, final String description,
final int cpuLimit, final ProcessRecord app) {
- if (DEBUG_POWER) {
+ if (DEBUG_POWER && (uptimeSince > 0)) {
StringBuilder sb = new StringBuilder(128);
sb.append("CPU for ");
sb.append(description);
@@ -15298,6 +15356,11 @@
}
@Override
+ public int[] getStartedUserIds() {
+ return mUserController.getStartedUserArray();
+ }
+
+ @Override
public void setPendingIntentAllowBgActivityStarts(IIntentSender target,
IBinder allowlistToken, int flags) {
if (!(target instanceof PendingIntentRecord)) {
@@ -16176,6 +16239,14 @@
public PendingIntent getPendingIntentActivityAsApp(
int requestCode, @NonNull Intent intent, int flags, Bundle options,
String ownerPkg, int ownerUid) {
+ return getPendingIntentActivityAsApp(requestCode, new Intent[] { intent }, flags,
+ options, ownerPkg, ownerUid);
+ }
+
+ @Override
+ public PendingIntent getPendingIntentActivityAsApp(
+ int requestCode, @NonNull Intent[] intents, int flags, Bundle options,
+ String ownerPkg, int ownerUid) {
// system callers must explicitly set mutability state
final boolean flagImmutableSet = (flags & PendingIntent.FLAG_IMMUTABLE) != 0;
final boolean flagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0;
@@ -16185,15 +16256,21 @@
}
final Context context = ActivityManagerService.this.mContext;
- String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver());
- intent.migrateExtraStreamToClipData(context);
- intent.prepareToLeaveProcess(context);
+ final ContentResolver resolver = context.getContentResolver();
+ final int len = intents.length;
+ final String[] resolvedTypes = new String[len];
+ for (int i = 0; i < len; i++) {
+ final Intent intent = intents[i];
+ resolvedTypes[i] = intent.resolveTypeIfNeeded(resolver);
+ intent.migrateExtraStreamToClipData(context);
+ intent.prepareToLeaveProcess(context);
+ }
IIntentSender target =
ActivityManagerService.this.getIntentSenderWithFeatureAsApp(
INTENT_SENDER_ACTIVITY, ownerPkg,
context.getAttributionTag(), null, null, requestCode,
- new Intent[] { intent },
- resolvedType != null ? new String[] { resolvedType } : null,
+ intents,
+ resolvedTypes,
flags, options, UserHandle.getUserId(ownerUid), ownerUid);
return target != null ? new PendingIntent(target) : null;
}
@@ -17066,6 +17143,19 @@
}
/**
+ * Suppress or reenable the rate limit on foreground service notification deferral.
+ * @param enable false to suppress rate-limit policy; true to reenable it.
+ */
+ @Override
+ public boolean enableFgsNotificationRateLimit(boolean enable) {
+ enforceCallingPermission(permission.WRITE_DEVICE_CONFIG,
+ "enableFgsNotificationRateLimit");
+ synchronized (this) {
+ return mServices.enableFgsNotificationRateLimitLocked(enable);
+ }
+ }
+
+ /**
* Holds the AM lock for the specified amount of milliseconds.
* Intended for use by the tests that need to imitate lock contention.
* The token should be obtained by
@@ -17079,4 +17169,10 @@
SystemClock.sleep(durationMs);
}
}
+
+ static void traceBegin(long traceTag, String methodName, String subInfo) {
+ if (Trace.isTagEnabled(traceTag)) {
+ Trace.traceBegin(traceTag, methodName + subInfo);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index f2762fc..0757e7b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -230,6 +230,8 @@
return runBugReport(pw);
case "force-stop":
return runForceStop(pw);
+ case "fgs-notification-rate-limit":
+ return runFgsNotificationRateLimit(pw);
case "crash":
return runCrash(pw);
case "kill":
@@ -1103,6 +1105,24 @@
return 0;
}
+ int runFgsNotificationRateLimit(PrintWriter pw) throws RemoteException {
+ final String toggleValue = getNextArgRequired();
+ final boolean enable;
+ switch (toggleValue) {
+ case "enable":
+ enable = true;
+ break;
+ case "disable":
+ enable = false;
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Argument must be either 'enable' or 'disable'");
+ }
+ mInterface.enableFgsNotificationRateLimit(enable);
+ return 0;
+ }
+
int runCrash(PrintWriter pw) throws RemoteException {
int userId = UserHandle.USER_ALL;
@@ -3303,6 +3323,8 @@
pw.println(" when done to select where it should be delivered. Options are:");
pw.println(" --progress: will launch a notification right away to show its progress.");
pw.println(" --telephony: will dump only telephony sections.");
+ pw.println(" fgs-notification-rate-limit {enable | disable}");
+ pw.println(" Enable/disable rate limit on FGS notification deferral policy.");
pw.println(" force-stop [--user <USER_ID> | all | current] <PACKAGE>");
pw.println(" Completely stop the given application package.");
pw.println(" crash [--user <USER_ID>] <PACKAGE|PID>");
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index ab1da80..1611395 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -58,6 +58,7 @@
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -707,20 +708,28 @@
mService.enforceNotIsolatedCaller("removeContentProvider");
final long ident = Binder.clearCallingIdentity();
try {
- synchronized (mService) {
- ContentProviderConnection conn;
- try {
- conn = (ContentProviderConnection) connection;
- } catch (ClassCastException e) {
- String msg = "removeContentProvider: " + connection
- + " not a ContentProviderConnection";
- Slog.w(TAG, msg);
- throw new IllegalArgumentException(msg);
+ ContentProviderConnection conn;
+ try {
+ conn = (ContentProviderConnection) connection;
+ } catch (ClassCastException e) {
+ String msg = "removeContentProvider: " + connection
+ + " not a ContentProviderConnection";
+ Slog.w(TAG, msg);
+ throw new IllegalArgumentException(msg);
+ }
+ if (conn == null) {
+ throw new NullPointerException("connection is null");
+ }
+ ActivityManagerService.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "removeContentProvider: ",
+ (conn.provider != null && conn.provider.info != null
+ ? conn.provider.info.authority : ""));
+ try {
+ synchronized (mService) {
+ decProviderCountLocked(conn, null, null, stable, true, true);
}
- if (conn == null) {
- throw new NullPointerException("connection is null");
- }
- decProviderCountLocked(conn, null, null, stable, true, true);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -781,8 +790,15 @@
throw new NullPointerException("connection is null");
}
- conn.adjustCounts(stable, unstable);
- return !conn.dead;
+ ActivityManagerService.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "refContentProvider: ",
+ (conn.provider != null && conn.provider.info != null
+ ? conn.provider.info.authority : ""));
+ try {
+ conn.adjustCounts(stable, unstable);
+ return !conn.dead;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
void unstableProviderDied(IBinder connection) {
@@ -798,50 +814,60 @@
throw new NullPointerException("connection is null");
}
- // Safely retrieve the content provider associated with the connection.
- IContentProvider provider;
- synchronized (mService) {
- provider = conn.provider.provider;
- }
+ ActivityManagerService.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "unstableProviderDied: ",
+ (conn.provider != null && conn.provider.info != null
+ ? conn.provider.info.authority : ""));
- if (provider == null) {
- // Um, yeah, we're way ahead of you.
- return;
- }
-
- // Make sure the caller is being honest with us.
- if (provider.asBinder().pingBinder()) {
- // Er, no, still looks good to us.
+ try {
+ // Safely retrieve the content provider associated with the connection.
+ IContentProvider provider;
synchronized (mService) {
- Slog.w(TAG, "unstableProviderDied: caller " + Binder.getCallingUid()
- + " says " + conn + " died, but we don't agree");
- return;
+ provider = conn.provider.provider;
}
- }
- // Well look at that! It's dead!
- synchronized (mService) {
- if (conn.provider.provider != provider) {
- // But something changed... good enough.
+ if (provider == null) {
+ // Um, yeah, we're way ahead of you.
return;
}
- ProcessRecord proc = conn.provider.proc;
- if (proc == null || proc.getThread() == null) {
- // Seems like the process is already cleaned up.
- return;
+ // Make sure the caller is being honest with us.
+ if (provider.asBinder().pingBinder()) {
+ // Er, no, still looks good to us.
+ synchronized (mService) {
+ Slog.w(TAG, "unstableProviderDied: caller " + Binder.getCallingUid()
+ + " says " + conn + " died, but we don't agree");
+ return;
+ }
}
- // As far as we're concerned, this is just like receiving a
- // death notification... just a bit prematurely.
- mService.reportUidInfoMessageLocked(TAG, "Process " + proc.processName
- + " (pid " + proc.getPid() + ") early provider death", proc.info.uid);
- final long token = Binder.clearCallingIdentity();
- try {
- mService.appDiedLocked(proc, "unstable content provider");
- } finally {
- Binder.restoreCallingIdentity(token);
+ // Well look at that! It's dead!
+ synchronized (mService) {
+ if (conn.provider.provider != provider) {
+ // But something changed... good enough.
+ return;
+ }
+
+ ProcessRecord proc = conn.provider.proc;
+ if (proc == null || proc.getThread() == null) {
+ // Seems like the process is already cleaned up.
+ return;
+ }
+
+ // As far as we're concerned, this is just like receiving a
+ // death notification... just a bit prematurely.
+ mService.reportUidInfoMessageLocked(TAG, "Process " + proc.processName
+ + " (pid " + proc.getPid() + ") early provider death",
+ proc.info.uid);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mService.appDiedLocked(proc, "unstable content provider");
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
@@ -855,13 +881,21 @@
return;
}
- final ProcessRecord host = conn.provider.proc;
- if (host == null) {
- Slog.w(TAG, "Failed to find hosting ProcessRecord");
- return;
- }
+ ActivityManagerService.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "appNotRespondingViaProvider: ",
+ (conn.provider != null && conn.provider.info != null
+ ? conn.provider.info.authority : ""));
+ try {
+ final ProcessRecord host = conn.provider.proc;
+ if (host == null) {
+ Slog.w(TAG, "Failed to find hosting ProcessRecord");
+ return;
+ }
- mService.mAnrHelper.appNotResponding(host, "ContentProvider not responding");
+ mService.mAnrHelper.appNotResponding(host, "ContentProvider not responding");
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
/**
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 508bd06..b2266f6 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -470,7 +470,9 @@
incrementalMetrics != null ? incrementalMetrics.getMillisSinceLastReadError()
: -1,
incrementalMetrics != null ? incrementalMetrics.getLastReadErrorNumber()
- : 0);
+ : 0,
+ incrementalMetrics != null ? incrementalMetrics.getTotalDelayedReadsDurationMillis()
+ : -1);
final ProcessRecord parentPr = parentProcess != null
? (ProcessRecord) parentProcess.mOwner : null;
mService.addErrorToDropBox("anr", mApp, mApp.processName, activityShortComponentName,
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3bfd62b..8ebc987 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -4289,8 +4289,8 @@
if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_SERVICE) {
long lastCpuTime = r.mProfile.mLastCpuTime.get();
- if (lastCpuTime != 0) {
- long uptimeSince = curUptime - service.mLastPowerCheckUptime;
+ long uptimeSince = curUptime - service.mLastPowerCheckUptime;
+ if (lastCpuTime != 0 && uptimeSince > 0) {
long timeUsed = r.mProfile.mCurCpuTime.get() - lastCpuTime;
long cpuTimeToken = proto.start(ProcessOomProto.Detail.SERVICE_RUN_TIME);
proto.write(ProcessOomProto.Detail.CpuRunTime.OVER_MS, uptimeSince);
@@ -4427,7 +4427,7 @@
if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_SERVICE) {
long lastCpuTime = r.mProfile.mLastCpuTime.get();
- if (lastCpuTime != 0) {
+ if (lastCpuTime != 0 && uptimeSince > 0) {
long timeUsed = r.mProfile.mCurCpuTime.get() - lastCpuTime;
pw.print(prefix);
pw.print(" ");
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 96db1ad..697f6fa 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -469,9 +469,10 @@
}
}
- private boolean isValidPackageName(String packageName) {
+ private boolean isValidPackageName(String packageName, int userId) {
try {
- return mPackageManager.getPackageUid(packageName, 0) == Binder.getCallingUid();
+ return mPackageManager.getPackageUidAsUser(packageName, userId)
+ == Binder.getCallingUid();
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
@@ -547,7 +548,7 @@
// The least privileged case is a normal app performing a query, so check that first and
// return a value if the package name is valid. Next, check if the caller has the necessary
// permission and return a value. Do this check last, since it can throw an exception.
- if (isValidPackageName(packageName)) {
+ if (isValidPackageName(packageName, userId)) {
return getGameModeFromSettings(packageName, userId);
}
@@ -647,9 +648,9 @@
final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
overrides);
try {
- mPlatformCompat.setOverridesOnReleaseBuilds(changeConfig, packageName);
+ mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to call IPlatformCompat#setOverridesOnReleaseBuilds", e);
+ Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
}
} finally {
Binder.restoreCallingIdentity(uid);
@@ -671,9 +672,9 @@
final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
overrides);
try {
- mPlatformCompat.setOverridesOnReleaseBuilds(changeConfig, packageName);
+ mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to call IPlatformCompat#setOverridesOnReleaseBuilds", e);
+ Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
}
} finally {
Binder.restoreCallingIdentity(uid);
diff --git a/services/core/java/com/android/server/app/GameManagerShellCommand.java b/services/core/java/com/android/server/app/GameManagerShellCommand.java
index c5f1a0b..2074ffa 100644
--- a/services/core/java/com/android/server/app/GameManagerShellCommand.java
+++ b/services/core/java/com/android/server/app/GameManagerShellCommand.java
@@ -16,6 +16,7 @@
package com.android.server.app;
+import android.app.ActivityManager;
import android.app.GameManager;
import android.app.IGameManagerService;
import android.compat.Compatibility;
@@ -127,9 +128,14 @@
* <PACKAGE_NAME> <CONFIG_STRING>`
* see: {@link GameManagerServiceTests#mockDeviceConfigAll()}
*/
+ final String option = getNextOption();
+ String userIdStr = null;
+ if (option != null && option.equals("--user")) {
+ userIdStr = getNextArgRequired();
+ }
+
final String gameMode = getNextArgRequired();
final String packageName = getNextArgRequired();
- final String userIdStr = getNextArgRequired();
final IGameManagerService service = IGameManagerService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.GAME_SERVICE));
boolean batteryModeSupported = false;
@@ -142,7 +148,8 @@
batteryModeSupported = true;
}
}
- int userId = Integer.parseInt(userIdStr);
+ int userId = userIdStr != null ? Integer.parseInt(userIdStr)
+ : ActivityManager.getCurrentUser();
switch (gameMode.toLowerCase()) {
case "1":
case "standard":
@@ -199,7 +206,8 @@
pw.println(" Print this help text.");
pw.println(" downscale [0.5|0.6|0.7|0.8|0.9|disable] <PACKAGE_NAME>");
pw.println(" Force app to run at the specified scaling ratio.");
- pw.println(" mode [1|2|3|standard|performance|battery] <PACKAGE_NAME> <USER_ID>");
+ pw.println(" mode [--user <USER_ID>] [1|2|3|standard|performance|battery] <PACKAGE_NAME>");
pw.println(" Force app to run in the specified game mode, if supported.");
+ pw.println(" --user <USER_ID>: apply for the given user, the current user is used when unspecified.");
}
}
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index 535fb67..4cb2e9b 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -97,7 +97,9 @@
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_UNINSTALLED_PACKAGES
- | PackageManager.MATCH_DISABLED_COMPONENTS;
+ | PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS;
/**
* Lock for accessing any in-memory hibernation state
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index a68364e..ce8cbaf 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -84,8 +84,8 @@
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
import android.app.AppOpsManager;
-import android.app.AppOpsManager.AttributionFlags;
import android.app.AppOpsManager.AttributedOpEntry;
+import android.app.AppOpsManager.AttributionFlags;
import android.app.AppOpsManager.HistoricalOps;
import android.app.AppOpsManager.Mode;
import android.app.AppOpsManager.OpEntry;
@@ -667,12 +667,30 @@
/** Lazily populated cache of attributionTags of this package */
final @NonNull ArraySet<String> knownAttributionTags = new ArraySet<>();
+ /**
+ * Lazily populated cache of <b>valid</b> attributionTags of this package, a set smaller
+ * than or equal to {@link #knownAttributionTags}.
+ */
+ final @NonNull ArraySet<String> validAttributionTags = new ArraySet<>();
+
Ops(String _packageName, UidState _uidState) {
packageName = _packageName;
uidState = _uidState;
}
}
+ /** Returned from {@link #verifyAndGetBypass(int, String, String, String, boolean)}. */
+ private static final class PackageVerificationResult {
+
+ final RestrictionBypass bypass;
+ final boolean isAttributionTagValid;
+
+ PackageVerificationResult(RestrictionBypass bypass, boolean isAttributionTagValid) {
+ this.bypass = bypass;
+ this.isAttributionTagValid = isAttributionTagValid;
+ }
+ }
+
/** A in progress startOp->finishOp event */
private static final class InProgressStartOpEvent implements IBinder.DeathRecipient {
/** Wall clock time of startOp event (not monotonic) */
@@ -2225,7 +2243,8 @@
return Collections.emptyList();
}
synchronized (this) {
- Ops pkgOps = getOpsLocked(uid, resolvedPackageName, null, null, false /* edit */);
+ Ops pkgOps = getOpsLocked(uid, resolvedPackageName, null, false, null,
+ /* edit */ false);
if (pkgOps == null) {
return null;
}
@@ -2387,7 +2406,7 @@
op.removeAttributionsWithNoTime();
if (op.mAttributions.isEmpty()) {
- Ops ops = getOpsLocked(uid, packageName, null, null, false /* edit */);
+ Ops ops = getOpsLocked(uid, packageName, null, false, null, /* edit */ false);
if (ops != null) {
ops.remove(op.op);
if (ops.size() <= 0) {
@@ -2697,9 +2716,9 @@
ArraySet<ModeCallback> repCbs = null;
code = AppOpsManager.opToSwitch(code);
- RestrictionBypass bypass;
+ PackageVerificationResult pvr;
try {
- bypass = verifyAndGetBypass(uid, packageName, null);
+ pvr = verifyAndGetBypass(uid, packageName, null);
} catch (SecurityException e) {
Slog.e(TAG, "Cannot setMode", e);
return;
@@ -2708,7 +2727,7 @@
int previousMode = MODE_DEFAULT;
synchronized (this) {
UidState uidState = getUidStateLocked(uid, false);
- Op op = getOpLocked(code, uid, packageName, null, bypass, true);
+ Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ true);
if (op != null) {
if (op.mode != mode) {
previousMode = op.mode;
@@ -3148,9 +3167,9 @@
*/
private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
@Nullable String attributionTag, boolean raw) {
- RestrictionBypass bypass;
+ PackageVerificationResult pvr;
try {
- bypass = verifyAndGetBypass(uid, packageName, null);
+ pvr = verifyAndGetBypass(uid, packageName, null);
} catch (SecurityException e) {
Slog.e(TAG, "checkOperation", e);
return AppOpsManager.opToDefaultMode(code);
@@ -3160,7 +3179,7 @@
return AppOpsManager.MODE_IGNORED;
}
synchronized (this) {
- if (isOpRestrictedLocked(uid, code, packageName, attributionTag, bypass)) {
+ if (isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass)) {
return AppOpsManager.MODE_IGNORED;
}
code = AppOpsManager.opToSwitch(code);
@@ -3170,7 +3189,7 @@
final int rawMode = uidState.opModes.get(code);
return raw ? rawMode : uidState.evalMode(code, rawMode);
}
- Op op = getOpLocked(code, uid, packageName, null, bypass, false);
+ Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
@@ -3255,13 +3274,6 @@
shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation);
}
- // TODO b/184963112: remove once full blaming is implemented
- private boolean isRecognitionServiceTemp(int code, String packageName) {
- return code == OP_RECORD_AUDIO
- && (packageName.equals("com.google.android.googlequicksearchbox")
- || packageName.equals("com.google.android.tts"));
- }
-
private SyncNotedAppOp noteProxyOperationImpl(int code, AttributionSource attributionSource,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
boolean skipProxyOperation) {
@@ -3289,8 +3301,7 @@
final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid;
final boolean isProxyTrusted = mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
- == PackageManager.PERMISSION_GRANTED || isSelfBlame
- || isRecognitionServiceTemp(code, proxyPackageName);
+ == PackageManager.PERMISSION_GRANTED || isSelfBlame;
if (!skipProxyOperation) {
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
@@ -3349,16 +3360,16 @@
@Nullable String proxyAttributionTag, @OpFlags int flags,
boolean shouldCollectAsyncNotedOp, @Nullable String message,
boolean shouldCollectMessage) {
- RestrictionBypass bypass;
+ PackageVerificationResult pvr;
try {
boolean isLocOrActivity = code == AppOpsManager.OP_FINE_LOCATION
|| code == AppOpsManager.OP_FINE_LOCATION_SOURCE
|| code == AppOpsManager.OP_ACTIVITY_RECOGNITION
|| code == AppOpsManager.OP_ACTIVITY_RECOGNITION_SOURCE;
- bypass = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName,
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName,
isLocOrActivity);
boolean wasNull = attributionTag == null;
- if (bypass != null && bypass.getIsAttributionTagNotFound()) {
+ if (!pvr.isAttributionTagValid) {
attributionTag = null;
}
if (attributionTag == null && isLocOrActivity
@@ -3373,8 +3384,8 @@
}
synchronized (this) {
- final Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass,
- true /* edit */);
+ final Ops ops = getOpsLocked(uid, packageName, attributionTag,
+ pvr.isAttributionTagValid, pvr.bypass, /* edit */ true);
if (ops == null) {
scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
AppOpsManager.MODE_IGNORED);
@@ -3394,7 +3405,7 @@
final int switchCode = AppOpsManager.opToSwitch(code);
final UidState uidState = ops.uidState;
- if (isOpRestrictedLocked(uid, code, packageName, attributionTag, bypass)) {
+ if (isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass)) {
attributedOp.rejected(uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
AppOpsManager.MODE_IGNORED);
@@ -3870,15 +3881,15 @@
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @Nullable String message,
boolean shouldCollectMessage, @AttributionFlags int attributionFlags,
int attributionChainId, boolean dryRun) {
- RestrictionBypass bypass;
+ PackageVerificationResult pvr;
try {
boolean isLocOrActivity = code == AppOpsManager.OP_FINE_LOCATION
|| code == AppOpsManager.OP_FINE_LOCATION_SOURCE
|| code == AppOpsManager.OP_ACTIVITY_RECOGNITION
|| code == AppOpsManager.OP_ACTIVITY_RECOGNITION_SOURCE;
- bypass = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName,
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName,
isLocOrActivity);
- if (bypass != null && bypass.getIsAttributionTagNotFound()) {
+ if (!pvr.isAttributionTagValid) {
attributionTag = null;
}
if (attributionTag == null && isLocOrActivity
@@ -3894,7 +3905,8 @@
boolean isRestricted = false;
synchronized (this) {
- final Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass, true /* edit */);
+ final Ops ops = getOpsLocked(uid, packageName, attributionTag,
+ pvr.isAttributionTagValid, pvr.bypass, /* edit */ true);
if (ops == null) {
if (!dryRun) {
scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
@@ -3909,7 +3921,7 @@
final Op op = getOpLocked(ops, code, uid, true);
final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag);
final UidState uidState = ops.uidState;
- isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag, bypass);
+ isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass);
final int switchCode = AppOpsManager.opToSwitch(code);
// If there is a non-default per UID policy (we set UID op mode only if
// non-default) it takes over, otherwise use the per package policy.
@@ -4041,10 +4053,10 @@
private void finishOperationUnchecked(IBinder clientId, int code, int uid, String packageName,
String attributionTag) {
- RestrictionBypass bypass;
+ PackageVerificationResult pvr;
try {
- bypass = verifyAndGetBypass(uid, packageName, attributionTag);
- if (bypass != null && bypass.getIsAttributionTagNotFound()) {
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag);
+ if (!pvr.isAttributionTagValid) {
attributionTag = null;
}
} catch (SecurityException e) {
@@ -4053,7 +4065,8 @@
}
synchronized (this) {
- Op op = getOpLocked(code, uid, packageName, attributionTag, bypass, true);
+ Op op = getOpLocked(code, uid, packageName, attributionTag, pvr.isAttributionTagValid,
+ pvr.bypass, /* edit */ true);
if (op == null) {
Slog.e(TAG, "Operation not found: uid=" + uid + " pkg=" + packageName + "("
+ attributionTag + ") op=" + AppOpsManager.opToName(code));
@@ -4435,32 +4448,35 @@
}
/**
- * @see verifyAndGetBypass(int, String, String, String)
+ * @see #verifyAndGetBypass(int, String, String, String, boolean)
*/
- private @Nullable RestrictionBypass verifyAndGetBypass(int uid, String packageName,
+ private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
@Nullable String attributionTag) {
return verifyAndGetBypass(uid, packageName, attributionTag, null, false);
}
/**
* Verify that package belongs to uid and return the {@link RestrictionBypass bypass
- * description} for the package.
+ * description} for the package, along with a boolean indicating whether the attribution tag is
+ * valid.
*
* @param uid The uid the package belongs to
* @param packageName The package the might belong to the uid
* @param attributionTag attribution tag or {@code null} if no need to verify
* @param proxyPackageName The proxy package, from which the attribution tag is to be pulled
*
- * @return {@code true} iff the package is privileged
+ * @return PackageVerificationResult containing {@link RestrictionBypass} and whether the
+ * attribution tag is valid
*/
- private @Nullable RestrictionBypass verifyAndGetBypass(int uid, String packageName,
+ private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
@Nullable String attributionTag, @Nullable String proxyPackageName, boolean extraLog) {
if (uid == Process.ROOT_UID) {
// For backwards compatibility, don't check package name for root UID.
- return null;
+ return new PackageVerificationResult(null,
+ /* isAttributionTagValid */ true);
}
- // Do not check if uid/packageName/attributionTag is already known
+ // Do not check if uid/packageName/attributionTag is already known.
synchronized (this) {
UidState uidState = mUidStates.get(uid);
if (uidState != null && uidState.pkgOps != null) {
@@ -4468,14 +4484,13 @@
if (ops != null && (attributionTag == null || ops.knownAttributionTags.contains(
attributionTag)) && ops.bypass != null) {
- return ops.bypass;
+ return new PackageVerificationResult(ops.bypass,
+ ops.validAttributionTags.contains(attributionTag));
}
}
}
int callingUid = Binder.getCallingUid();
- int userId = UserHandle.getUserId(uid);
- RestrictionBypass bypass = null;
// Allow any attribution tag for resolvable uids
int pkgUid = resolveUid(packageName);
@@ -4483,15 +4498,20 @@
// Special case for the shell which is a package but should be able
// to bypass app attribution tag restrictions.
if (pkgUid != UserHandle.getAppId(uid)) {
+ String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not";
throw new SecurityException("Specified package " + packageName + " under uid "
- + UserHandle.getAppId(uid) + " but it is really " + pkgUid);
+ + UserHandle.getAppId(uid) + otherUidMessage);
}
- return RestrictionBypass.UNRESTRICTED;
+ return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED,
+ /* isAttributionTagValid */ true);
}
+ int userId = UserHandle.getUserId(uid);
+ RestrictionBypass bypass = null;
+ boolean isAttributionTagValid = false;
+
final long ident = Binder.clearCallingIdentity();
try {
- boolean isAttributionTagValid = false;
PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
AndroidPackage pkg = pmInt.getPackage(packageName);
if (pkg != null) {
@@ -4501,8 +4521,12 @@
Slog.i("AppOpsDebug", "tag " + attributionTag + " found in "
+ packageName);
} else {
+ ArrayList<String> tagList = new ArrayList<>();
+ for (int i = 0; i < pkg.getAttributions().size(); i++) {
+ tagList.add(pkg.getAttributions().get(i).tag);
+ }
Slog.i("AppOpsDebug", "tag " + attributionTag + " missing from "
- + packageName);
+ + packageName + ", tags: " + tagList);
}
}
@@ -4512,15 +4536,15 @@
if (!isAttributionTagValid) {
AndroidPackage proxyPkg = proxyPackageName != null
? pmInt.getPackage(proxyPackageName) : null;
- boolean foundInProxy = isAttributionInPackage(proxyPkg, attributionTag);
+ // Re-check in proxy.
+ isAttributionTagValid = isAttributionInPackage(proxyPkg, attributionTag);
String msg;
- if (pkg != null && foundInProxy) {
+ if (pkg != null && isAttributionTagValid) {
msg = "attributionTag " + attributionTag + " declared in manifest of the proxy"
+ " package " + proxyPackageName + ", this is not advised";
} else if (pkg != null) {
msg = "attributionTag " + attributionTag + " not declared in manifest of "
+ packageName;
- bypass.setIsAttributionTagNotFound(true);
} else {
msg = "package " + packageName + " not found, can't check for "
+ "attributionTag " + attributionTag;
@@ -4531,7 +4555,7 @@
SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, packageName,
userId) && mPlatformCompat.isChangeEnabledByUid(
SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE,
- callingUid) && !foundInProxy) {
+ callingUid) && !isAttributionTagValid) {
Slog.e(TAG, msg);
} else {
Slog.e(TAG, msg);
@@ -4544,11 +4568,12 @@
}
if (pkgUid != uid) {
+ String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not";
throw new SecurityException("Specified package " + packageName + " under uid " + uid
- + " but it is really " + pkgUid);
+ + otherUidMessage);
}
- return bypass;
+ return new PackageVerificationResult(bypass, isAttributionTagValid);
}
private boolean isAttributionInPackage(@Nullable AndroidPackage pkg,
@@ -4576,13 +4601,14 @@
* @param uid The uid the package belongs to
* @param packageName The name of the package
* @param attributionTag attribution tag
+ * @param isAttributionTagValid whether the given attribution tag is valid
* @param bypass When to bypass certain op restrictions (can be null if edit == false)
* @param edit If an ops does not exist, create the ops?
* @return The ops
*/
private Ops getOpsLocked(int uid, String packageName, @Nullable String attributionTag,
- @Nullable RestrictionBypass bypass, boolean edit) {
+ boolean isAttributionTagValid, @Nullable RestrictionBypass bypass, boolean edit) {
UidState uidState = getUidStateLocked(uid, edit);
if (uidState == null) {
return null;
@@ -4611,6 +4637,11 @@
if (attributionTag != null) {
ops.knownAttributionTags.add(attributionTag);
+ if (isAttributionTagValid) {
+ ops.validAttributionTags.add(attributionTag);
+ } else {
+ ops.validAttributionTags.remove(attributionTag);
+ }
}
}
@@ -4640,14 +4671,17 @@
* @param uid The uid the of the package
* @param packageName The package name for which to get the state for
* @param attributionTag The attribution tag
+ * @param isAttributionTagValid Whether the given attribution tag is valid
* @param bypass When to bypass certain op restrictions (can be null if edit == false)
* @param edit Iff {@code true} create the {@link Op} object if not yet created
*
* @return The {@link Op state} of the op
*/
private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName,
- @Nullable String attributionTag, @Nullable RestrictionBypass bypass, boolean edit) {
- Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass, edit);
+ @Nullable String attributionTag, boolean isAttributionTagValid,
+ @Nullable RestrictionBypass bypass, boolean edit) {
+ Ops ops = getOpsLocked(uid, packageName, attributionTag, isAttributionTagValid, bypass,
+ edit);
if (ops == null) {
return null;
}
@@ -6512,7 +6546,7 @@
}
// TODO moltmann: Allow to check for attribution op activeness
synchronized (AppOpsService.this) {
- Ops pkgOps = getOpsLocked(uid, resolvedPackageName, null, null, false);
+ Ops pkgOps = getOpsLocked(uid, resolvedPackageName, null, false, null, false);
if (pkgOps == null) {
return false;
}
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 6f73985..5cd330a 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -27,6 +27,8 @@
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
import static android.hardware.biometrics.BiometricManager.Authenticators;
import android.annotation.NonNull;
@@ -76,7 +78,6 @@
*/
public class AuthService extends SystemService {
private static final String TAG = "AuthService";
- private static final boolean DEBUG = false;
private static final String SETTING_HIDL_DISABLED =
"com.android.server.biometrics.AuthService.hidlDisabled";
private static final int DEFAULT_HIDL_DISABLED = 0;
@@ -208,7 +209,6 @@
public void authenticate(IBinder token, long sessionId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo)
throws RemoteException {
-
// Only allow internal clients to authenticate with a different userId.
final int callingUserId = UserHandle.getCallingUserId();
final int callingUid = Binder.getCallingUid();
@@ -222,17 +222,18 @@
}
if (!checkAppOps(callingUid, opPackageName, "authenticate()")) {
- Slog.e(TAG, "Denied by app ops: " + opPackageName);
- return;
- }
-
- if (!Utils.isForeground(callingUid, callingPid)) {
- Slog.e(TAG, "Caller is not foreground: " + opPackageName);
+ authenticateFastFail("Denied by app ops: " + opPackageName, receiver);
return;
}
if (token == null || receiver == null || opPackageName == null || promptInfo == null) {
- Slog.e(TAG, "Unable to authenticate, one or more null arguments");
+ authenticateFastFail(
+ "Unable to authenticate, one or more null arguments", receiver);
+ return;
+ }
+
+ if (!Utils.isForeground(callingUid, callingPid)) {
+ authenticateFastFail("Caller is not foreground: " + opPackageName, receiver);
return;
}
@@ -257,6 +258,17 @@
}
}
+ private void authenticateFastFail(String message, IBiometricServiceReceiver receiver) {
+ // notify caller in cases where authentication is aborted before calling into
+ // IBiometricService without raising an exception
+ Slog.e(TAG, message);
+ try {
+ receiver.onError(TYPE_NONE, BIOMETRIC_ERROR_CANCELED, 0 /*vendorCode */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "authenticateFastFail failed to notify caller", e);
+ }
+ }
+
@Override
public void cancelAuthentication(IBinder token, String opPackageName)
throws RemoteException {
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index 36dc5cd..8f36489 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -355,10 +355,6 @@
}
}
- private void cancelAllFingerprintSensors() {
- cancelAllSensors(sensor -> sensor.modality == TYPE_FINGERPRINT);
- }
-
private void cancelAllSensors() {
cancelAllSensors(sensor -> true);
}
@@ -387,6 +383,9 @@
*/
boolean onErrorReceived(int sensorId, int cookie, @BiometricConstants.Errors int error,
int vendorCode) throws RemoteException {
+ if (DEBUG) {
+ Slog.v(TAG, "onErrorReceived sensor: " + sensorId + " error: " + error);
+ }
if (!containsCookie(cookie)) {
Slog.e(TAG, "Unknown/expired cookie: " + cookie);
@@ -454,12 +453,14 @@
// a round trip to SystemUI.
mClientReceiver.onError(modality, error, vendorCode);
return true;
- } else if (shouldErrorTriggerMultiSensorTransition()) {
- // wait for the UI to signal when modality should switch
- mMultiSensorState = MULTI_SENSOR_STATE_SWITCHING;
- Slog.d(TAG, "onErrorReceived: waiting for modality switch callback");
} else {
mState = STATE_ERROR_PENDING_SYSUI;
+ if (mMultiSensorMode == BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT
+ && mMultiSensorState == MULTI_SENSOR_STATE_FACE_SCANNING) {
+ // wait for the UI to signal when modality should switch
+ Slog.d(TAG, "onErrorReceived: waiting for modality switch callback");
+ mMultiSensorState = MULTI_SENSOR_STATE_SWITCHING;
+ }
mStatusBarService.onBiometricError(modality, error, vendorCode);
}
break;
@@ -627,7 +628,7 @@
void onDeviceCredentialPressed() {
// Cancel authentication. Skip the token/package check since we are cancelling
// from system server. The interface is permission protected so this is fine.
- cancelBiometricOnly();
+ cancelAllSensors();
mState = STATE_SHOWING_DEVICE_CREDENTIAL;
}
@@ -678,7 +679,8 @@
FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
latency,
mDebugEnabled,
- -1 /* sensorId */);
+ -1 /* sensorId */,
+ -1f /* ambientLightLux */);
} else {
final long latency = System.currentTimeMillis() - mStartTimeMs;
@@ -733,12 +735,10 @@
}
mClientReceiver.onAuthenticationSucceeded(
Utils.getAuthenticationTypeForResult(reason));
- cancelBiometricOnly();
break;
case BiometricPrompt.DISMISSED_REASON_NEGATIVE:
mClientReceiver.onDialogDismissed(reason);
- cancelBiometricOnly();
break;
case BiometricPrompt.DISMISSED_REASON_USER_CANCEL:
@@ -747,7 +747,6 @@
BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
0 /* vendorCode */
);
- cancelBiometricOnly();
break;
case BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED:
@@ -765,6 +764,9 @@
}
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception", e);
+ } finally {
+ // ensure everything is cleaned up when dismissed
+ cancelAllSensors();
}
}
@@ -780,8 +782,8 @@
|| mState == STATE_AUTH_STARTED
|| mState == STATE_AUTH_STARTED_UI_SHOWING;
+ cancelAllSensors();
if (authStarted && !force) {
- cancelAllSensors();
// Wait for ERROR_CANCELED to be returned from the sensors
return false;
} else {
@@ -804,22 +806,6 @@
return false;
}
- /**
- * Cancels biometric authentication only. AuthSession may either be going into
- * {@link #STATE_SHOWING_DEVICE_CREDENTIAL} or dismissed.
- */
- private void cancelBiometricOnly() {
- if (mState == STATE_AUTH_STARTED || mState == STATE_AUTH_STARTED_UI_SHOWING) {
- cancelAllSensors();
- } else if (mMultiSensorMode == BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT) {
- cancelAllFingerprintSensors();
- } else {
- if (DEBUG) {
- Slog.v(TAG, "nothing to cancel - wrong state: " + mState);
- }
- }
- }
-
boolean isCrypto() {
return mOperationId != 0;
}
@@ -896,13 +882,6 @@
}
}
- private boolean shouldErrorTriggerMultiSensorTransition() {
- if (mMultiSensorMode == BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT) {
- return mMultiSensorState == MULTI_SENSOR_STATE_FACE_SCANNING;
- }
- return false;
- }
-
@BiometricMultiSensorMode
private static int getMultiSensorModeForNewSession(Collection<BiometricSensor> sensors) {
boolean hasFace = false;
diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index 99f4e2c..f51b1c2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -69,6 +69,31 @@
}
}
+ /** Holder for wrapping multiple handlers into a single Callback. */
+ protected static class CompositeCallback implements Callback {
+ @NonNull
+ private final Callback[] mCallbacks;
+
+ public CompositeCallback(@NonNull Callback... callbacks) {
+ mCallbacks = callbacks;
+ }
+
+ @Override
+ public final void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].onClientStarted(clientMonitor);
+ }
+ }
+
+ @Override
+ public final void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
+ boolean success) {
+ for (int i = mCallbacks.length - 1; i >= 0; i--) {
+ mCallbacks[i].onClientFinished(clientMonitor, success);
+ }
+ }
+ }
+
private final int mSequentialId;
@NonNull private final Context mContext;
private final int mTargetUserId;
@@ -125,7 +150,7 @@
@Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int cookie, int sensorId, int statsModality, int statsAction,
int statsClient) {
- super(statsModality, statsAction, statsClient);
+ super(context, statsModality, statsAction, statsClient);
mSequentialId = sCount++;
mContext = context;
mToken = token;
@@ -153,10 +178,19 @@
* @param callback invoked when the operation is complete (succeeds, fails, etc)
*/
public void start(@NonNull Callback callback) {
- mCallback = callback;
+ mCallback = wrapCallbackForStart(callback);
mCallback.onClientStarted(this);
}
+ /**
+ * Called during start to provide subclasses a hook for decorating the callback.
+ *
+ * Returns the original callback unless overridden.
+ */
+ @NonNull
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return callback;
+ }
public boolean isAlreadyDone() {
return mAlreadyDone;
diff --git a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
index 4da644d..c8867ea 100644
--- a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
@@ -16,7 +16,13 @@
package com.android.server.biometrics.sensors;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.face.FaceManager;
@@ -37,9 +43,41 @@
final int mStatsModality;
private final int mStatsAction;
private final int mStatsClient;
+ @NonNull private final SensorManager mSensorManager;
private long mFirstAcquireTimeMs;
+ private boolean mLightSensorEnabled = false;
private boolean mShouldLogMetrics = true;
+ // report only the most recent value
+ // consider com.android.server.display.utils.AmbientFilter or similar if need arises
+ private volatile float mLastAmbientLux = 0;
+
+ private final SensorEventListener mLightSensorListener = new SensorEventListener() {
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ mLastAmbientLux = event.values[0];
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ // Not used.
+ }
+ };
+
+ /**
+ * @param context system_server context
+ * @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants.
+ * @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants.
+ * @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants.
+ */
+ public LoggableMonitor(@NonNull Context context, int statsModality, int statsAction,
+ int statsClient) {
+ mStatsModality = statsModality;
+ mStatsAction = statsAction;
+ mStatsClient = statsClient;
+ mSensorManager = context.getSystemService(SensorManager.class);
+ }
+
/**
* Only valid for AuthenticationClient.
* @return true if the client is authenticating for a crypto operation.
@@ -48,17 +86,6 @@
return false;
}
- /**
- * @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants.
- * @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants.
- * @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants.
- */
- public LoggableMonitor(int statsModality, int statsAction, int statsClient) {
- mStatsModality = statsModality;
- mStatsAction = statsAction;
- mStatsClient = statsClient;
- }
-
protected void setShouldLog(boolean shouldLog) {
mShouldLogMetrics = shouldLog;
}
@@ -131,7 +158,6 @@
}
protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) {
-
if (!mShouldLogMetrics) {
return;
}
@@ -199,7 +225,8 @@
+ ", Client: " + mStatsClient
+ ", RequireConfirmation: " + requireConfirmation
+ ", State: " + authState
- + ", Latency: " + latency);
+ + ", Latency: " + latency
+ + ", Lux: " + mLastAmbientLux);
} else {
Slog.v(TAG, "Authentication latency: " + latency);
}
@@ -217,7 +244,8 @@
authState,
sanitizeLatency(latency),
Utils.isDebugEnabled(context, targetUserId),
- -1 /* sensorId */);
+ -1 /* sensorId */,
+ mLastAmbientLux /* ambientLightLux */);
}
protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
@@ -230,6 +258,7 @@
+ ", User: " + targetUserId
+ ", Client: " + mStatsClient
+ ", Latency: " + latency
+ + ", Lux: " + mLastAmbientLux
+ ", Success: " + enrollSuccessful);
} else {
Slog.v(TAG, "Enroll latency: " + latency);
@@ -244,7 +273,8 @@
targetUserId,
sanitizeLatency(latency),
enrollSuccessful,
- -1 /* sensorId */);
+ -1, /* sensorId */
+ mLastAmbientLux /* ambientLightLux */);
}
private long sanitizeLatency(long latency) {
@@ -255,4 +285,46 @@
return latency;
}
+ /** Get a callback to start/stop ALS capture when client runs. */
+ @NonNull
+ protected BaseClientMonitor.Callback createALSCallback() {
+ return new BaseClientMonitor.Callback() {
+ @Override
+ public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
+ setLightSensorLoggingEnabled(getAmbientLightSensor(mSensorManager));
+ }
+
+ @Override
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
+ boolean success) {
+ setLightSensorLoggingEnabled(null);
+ }
+ };
+ }
+
+ /** The sensor to use for ALS logging. */
+ @Nullable
+ protected Sensor getAmbientLightSensor(@NonNull SensorManager sensorManager) {
+ return mShouldLogMetrics ? sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) : null;
+ }
+
+ private void setLightSensorLoggingEnabled(@Nullable Sensor lightSensor) {
+ if (DEBUG) {
+ Slog.v(TAG, "capturing ambient light using: "
+ + (lightSensor != null ? lightSensor : "[disabled]"));
+ }
+
+ if (lightSensor != null) {
+ if (!mLightSensorEnabled) {
+ mLightSensorEnabled = true;
+ mLastAmbientLux = 0;
+ mSensorManager.registerListener(mLightSensorListener, lightSensor,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ }
+ } else {
+ mLightSensorEnabled = false;
+ mLastAmbientLux = 0;
+ mSensorManager.unregisterListener(mLightSensorListener);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 2ab1285..2adf5f9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -99,6 +99,12 @@
"face_custom_success_error", 0) == 1;
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
protected void startHalOperation() {
try {
@@ -229,7 +235,8 @@
}
}
- @Override public void onLockoutTimed(long durationMillis) {
+ @Override
+ public void onLockoutTimed(long durationMillis) {
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED);
// Lockout metrics are logged as an error code.
final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT;
@@ -242,7 +249,8 @@
}
}
- @Override public void onLockoutPermanent() {
+ @Override
+ public void onLockoutPermanent() {
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT);
// Lockout metrics are logged as an error code.
final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index f974147..ff68aa8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -95,6 +95,12 @@
ReEnrollNotificationUtils.cancelNotification(getContext());
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
public void destroy() {
try {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index c4bdb32..01dd18f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -88,6 +88,12 @@
"face_custom_success_error", 0) == 1;
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
protected void startHalOperation() {
try {
@@ -186,7 +192,6 @@
@Override
public void onAcquired(int acquireInfo, int vendorCode) {
-
mLastAcquire = acquireInfo;
if (acquireInfo == FaceManager.FACE_ACQUIRED_RECALIBRATE) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
index fc1200a..d3bd18b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
@@ -68,6 +68,12 @@
.getIntArray(R.array.config_face_acquire_vendor_enroll_ignorelist);
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
protected boolean hasReachedEnrollmentLimit() {
final int limit = getContext().getResources().getInteger(
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index a5326b3..3c9d802 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -70,6 +70,12 @@
mUdfpsOverlayController = udfpsOverlayController;
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 125cfd2..1184966 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -27,6 +27,7 @@
import android.hardware.biometrics.fingerprint.ISession;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
@@ -46,6 +47,7 @@
private static final String TAG = "FingerprintEnrollClient";
+ @NonNull private final FingerprintSensorPropertiesInternal mSensorProps;
@Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
@Nullable private final ISidefpsController mSidefpsController;
@@ -58,12 +60,15 @@
@NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String owner,
@NonNull BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull FingerprintSensorPropertiesInternal sensorProps,
@Nullable IUdfpsOverlayController udfpsOvelayController,
@Nullable ISidefpsController sidefpsController,
int maxTemplatesPerUser, @FingerprintManager.EnrollReason int enrollReason) {
+ // UDFPS enroll vibrations are handled in SystemUI
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
0 /* timeoutSec */, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
- true /* shouldVibrate */);
+ !sensorProps.isAnyUdfpsType() /* shouldVibrate */);
+ mSensorProps = sensorProps;
mUdfpsOverlayController = udfpsOvelayController;
mSidefpsController = sidefpsController;
mMaxTemplatesPerUser = maxTemplatesPerUser;
@@ -74,6 +79,12 @@
}
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) {
super.onEnrollResult(identifier, remaining);
@@ -90,7 +101,8 @@
public void onAcquired(@FingerprintAcquired int acquiredInfo, int vendorCode) {
// For UDFPS, notify SysUI that the illumination can be turned off.
// See AcquiredInfo#GOOD and AcquiredInfo#RETRYING_CAPTURE
- if (acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD) {
+ if (acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD
+ && mSensorProps.isAnyUdfpsType()) {
UdfpsHelper.onAcquiredGood(getSensorId(), mUdfpsOverlayController);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 293b9e4..096c311 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -340,6 +340,7 @@
mSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
+ mSensors.get(sensorId).getSensorProperties(),
mUdfpsOverlayController, mSidefpsController, maxTemplatesPerUser, enrollReason);
scheduleForSensor(sensorId, client, new BaseClientMonitor.Callback() {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 24ed85c..45e35e3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -69,6 +69,12 @@
mUdfpsOverlayController = udfpsOverlayController;
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index 4f3e930..a28a3f6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -72,6 +72,12 @@
}
}
+ @NonNull
+ @Override
+ protected Callback wrapCallbackForStart(@NonNull Callback callback) {
+ return new CompositeCallback(createALSCallback(), callback);
+ }
+
@Override
protected boolean hasReachedEnrollmentLimit() {
final int limit = getContext().getResources().getInteger(
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 909ed11..6dca001 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -235,13 +235,11 @@
* @param packageName app for which the overrides will be applied.
*/
void addOverrides(CompatibilityOverrideConfig overrides, String packageName) {
- synchronized (mChanges) {
- for (Long changeId : overrides.overrides.keySet()) {
- addOverrideUnsafe(changeId, packageName, overrides.overrides.get(changeId));
- }
- saveOverrides();
- invalidateCache();
+ for (Long changeId : overrides.overrides.keySet()) {
+ addOverrideUnsafe(changeId, packageName, overrides.overrides.get(changeId));
}
+ saveOverrides();
+ invalidateCache();
}
private boolean addOverrideUnsafe(long changeId, String packageName,
@@ -335,27 +333,38 @@
/**
* Unsafe version of {@link #removeOverride(long, String)}.
- * It does not invalidate the cache nor save the overrides.
+ * It does not save the overrides.
*/
private boolean removeOverrideUnsafe(long changeId, String packageName) {
Long versionCode = getVersionCodeOrNull(packageName);
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
if (c != null) {
- OverrideAllowedState allowedState =
- mOverrideValidator.getOverrideAllowedState(changeId, packageName);
- if (c.hasPackageOverride(packageName)) {
- allowedState.enforce(changeId, packageName);
- c.removePackageOverride(packageName, allowedState, versionCode);
- invalidateCache();
- return true;
- }
+ return removeOverrideUnsafe(c, packageName, versionCode);
}
}
return false;
}
/**
+ * Similar to {@link #removeOverrideUnsafe(long, String)} except this method receives a {@link
+ * CompatChange} directly as well as the package's version code.
+ */
+ private boolean removeOverrideUnsafe(CompatChange change, String packageName,
+ @Nullable Long versionCode) {
+ long changeId = change.getId();
+ OverrideAllowedState allowedState =
+ mOverrideValidator.getOverrideAllowedState(changeId, packageName);
+ if (change.hasPackageOverride(packageName)) {
+ allowedState.enforce(changeId, packageName);
+ change.removePackageOverride(packageName, allowedState, versionCode);
+ invalidateCache();
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or
* {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package.
*
@@ -364,10 +373,11 @@
* @param packageName the package for which the overrides should be purged
*/
void removePackageOverrides(String packageName) {
+ Long versionCode = getVersionCodeOrNull(packageName);
synchronized (mChanges) {
for (int i = 0; i < mChanges.size(); ++i) {
CompatChange change = mChanges.valueAt(i);
- removeOverrideUnsafe(change.getId(), packageName);
+ removeOverrideUnsafe(change, packageName, versionCode);
}
saveOverrides();
invalidateCache();
@@ -386,13 +396,11 @@
*/
void removePackageOverrides(CompatibilityOverridesToRemoveConfig overridesToRemove,
String packageName) {
- synchronized (mChanges) {
- for (Long changeId : overridesToRemove.changeIds) {
- removeOverrideUnsafe(changeId, packageName);
- }
- saveOverrides();
- invalidateCache();
+ for (Long changeId : overridesToRemove.changeIds) {
+ removeOverrideUnsafe(changeId, packageName);
}
+ saveOverrides();
+ invalidateCache();
}
private long[] getAllowedChangesSinceTargetSdkForPackage(String packageName,
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index eba53fb..19e858c 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -91,15 +91,17 @@
@Override
public void reportChange(long changeId, ApplicationInfo appInfo) {
- reportChangeByUid(changeId, appInfo.uid);
+ checkCompatChangeLogPermission();
+ reportChangeInternal(changeId, appInfo.uid, ChangeReporter.STATE_LOGGED);
}
@Override
public void reportChangeByPackageName(long changeId, String packageName,
@UserIdInt int userId) {
+ checkCompatChangeLogPermission();
ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
if (appInfo != null) {
- reportChangeByUid(changeId, appInfo.uid);
+ reportChangeInternal(changeId, appInfo.uid, ChangeReporter.STATE_LOGGED);
}
}
@@ -207,15 +209,6 @@
}
@Override
- public void setOverridesOnReleaseBuilds(CompatibilityOverrideConfig overrides,
- String packageName) {
- // TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
- checkCompatChangeOverrideOverridablePermission();
- checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
- mCompatConfig.addOverrides(overrides, packageName);
- }
-
- @Override
public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) {
checkCompatChangeOverridePermission();
Map<Long, PackageOverride> overridesMap = new HashMap<>();
@@ -230,6 +223,15 @@
}
@Override
+ public void putOverridesOnReleaseBuilds(CompatibilityOverrideConfig overrides,
+ String packageName) {
+ // TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
+ checkCompatChangeOverrideOverridablePermission();
+ checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
+ mCompatConfig.addOverrides(overrides, packageName);
+ }
+
+ @Override
public int enableTargetSdkChanges(String packageName, int targetSdkVersion) {
checkCompatChangeOverridePermission();
int numChanges =
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index d4920f5..13b7ebc 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -3250,6 +3250,11 @@
mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
.ignoreProximitySensorUntilChanged();
}
+
+ @Override
+ public int getRefreshRateSwitchingType() {
+ return getRefreshRateSwitchingTypeInternal();
+ }
}
class DesiredDisplayModeSpecsObserver
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 52b05f2..c14acd7 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -941,6 +941,7 @@
final boolean mustNotify;
final int previousPolicy;
boolean mustInitialize = false;
+ boolean shouldSaveBrightnessInfo = true;
int brightnessAdjustmentFlags = 0;
mBrightnessReasonTemp.set(null);
synchronized (mLock) {
@@ -1071,6 +1072,7 @@
if (state == Display.STATE_OFF) {
brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
+ shouldSaveBrightnessInfo = false;
}
// Always use the VR brightness when in the VR state.
@@ -1197,6 +1199,7 @@
&& Display.isDozeState(state)) {
brightnessState = mScreenBrightnessDozeConfig;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
+ shouldSaveBrightnessInfo = false;
}
// Apply manual brightness.
@@ -1213,7 +1216,10 @@
// Save out the brightness info now that the brightness state for this iteration has been
// finalized and before we send out notifications about the brightness changing.
- saveBrightnessInfo(brightnessState);
+ if (shouldSaveBrightnessInfo) {
+ saveBrightnessInfo(brightnessState);
+
+ }
if (updateScreenBrightnessSetting) {
// Tell the rest of the system about the new brightness in case we had to change it
diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java
index a7e1a28..6db75eb 100644
--- a/services/core/java/com/android/server/display/WifiDisplayController.java
+++ b/services/core/java/com/android/server/display/WifiDisplayController.java
@@ -550,6 +550,11 @@
private void disconnect() {
mDesiredDevice = null;
+ mWifiP2pManager = null;
+ if (null != mWifiP2pChannel) {
+ mWifiP2pChannel.close();
+ mWifiP2pChannel = null;
+ }
updateConnection();
}
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubShellCommand.java b/services/core/java/com/android/server/location/contexthub/ContextHubShellCommand.java
index 5ec85e6..6931baa 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubShellCommand.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubShellCommand.java
@@ -32,16 +32,18 @@
// Internal service impl -- must perform security checks before touching.
private final ContextHubService mInternal;
+ private final Context mContext;
public ContextHubShellCommand(Context context, ContextHubService service) {
mInternal = service;
-
- context.enforceCallingOrSelfPermission(
- android.Manifest.permission.ACCESS_CONTEXT_HUB, "ContextHubShellCommand");
+ mContext = context;
}
@Override
public int onCommand(String cmd) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_CONTEXT_HUB, "ContextHubShellCommand");
+
if ("deny".equals(cmd)) {
return runDisableAuth();
}
diff --git a/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java b/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java
index ba7f44f..1da45bd 100644
--- a/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java
@@ -305,6 +305,10 @@
setState(state -> state.withIdentity(identity));
}
+ public final Set<String> getExtraAttributionTags() {
+ return mInternalState.get().state.extraAttributionTags;
+ }
+
/**
* Call this method to report a change in the provider's extra attribution tags.
*/
diff --git a/services/core/java/com/android/server/location/provider/MockableLocationProvider.java b/services/core/java/com/android/server/location/provider/MockableLocationProvider.java
index 8193644..021e8db 100644
--- a/services/core/java/com/android/server/location/provider/MockableLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/MockableLocationProvider.java
@@ -32,6 +32,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
+import java.util.Set;
/**
* Represents a location provider that may switch between a mock implementation and a real
@@ -296,6 +297,10 @@
if (identity != null) {
pw.println("identity=" + identity);
}
+ Set<String> extraAttributionTags = getExtraAttributionTags();
+ if (!extraAttributionTags.isEmpty()) {
+ pw.println("extra attribution tags=" + extraAttributionTags);
+ }
ProviderProperties properties = getProperties();
if (properties != null) {
pw.println("properties=" + properties);
diff --git a/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java b/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java
index 5df7870..a9641f0 100644
--- a/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java
@@ -17,6 +17,7 @@
package com.android.server.location.provider.proxy;
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+import static com.android.server.location.LocationManagerService.TAG;
import android.annotation.Nullable;
import android.content.Context;
@@ -32,6 +33,7 @@
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.server.FgThread;
@@ -44,6 +46,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -78,6 +81,7 @@
final Context mContext;
final ServiceWatcher mServiceWatcher;
+ final String mName;
@GuardedBy("mLock")
final ArrayList<Runnable> mFlushListeners = new ArrayList<>(0);
@@ -101,6 +105,7 @@
mServiceWatcher = ServiceWatcher.create(context, provider,
new CurrentUserServiceSupplier(context, action, enableOverlayResId,
nonOverlayPackageResId), this);
+ mName = provider;
mProxy = null;
mRequest = ProviderRequest.EMPTY_REQUEST;
@@ -249,6 +254,8 @@
String tagsStr = mBoundServiceInfo.getMetadata().getString(EXTRA_LOCATION_TAGS);
if (!TextUtils.isEmpty(tagsStr)) {
attributionTags = tagsStr.split(LOCATION_TAGS_SEPARATOR);
+ Log.i(TAG, mName + " provider loaded extra attribution tags: "
+ + Arrays.toString(attributionTags));
}
}
ArraySet<String> extraAttributionTags = new ArraySet<>(attributionTags);
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index edc9d7c..204ebfc 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -47,7 +47,7 @@
mUniqueId = componentName.flattenToShortString();
}
- public void setCallback(MediaRoute2ProviderServiceProxy.Callback callback) {
+ public void setCallback(Callback callback) {
mCallback = callback;
}
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index ab38dca..21f61ca 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -16,6 +16,10 @@
package com.android.server.media;
+import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
@@ -43,6 +47,7 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -64,6 +69,7 @@
private Connection mActiveConnection;
private boolean mConnectionReady;
+ private boolean mIsManagerScanning;
private RouteDiscoveryPreference mLastDiscoveryPreference = null;
@GuardedBy("mLock")
@@ -86,6 +92,13 @@
pw.println(prefix + " mConnectionReady=" + mConnectionReady);
}
+ public void setManagerScanning(boolean managerScanning) {
+ if (mIsManagerScanning != managerScanning) {
+ mIsManagerScanning = managerScanning;
+ updateBinding();
+ }
+ }
+
@Override
public void requestCreateSession(long requestId, String packageName, String routeId,
Bundle sessionHints) {
@@ -209,7 +222,8 @@
// Bind when there is a discovery preference or an active route session.
return (mLastDiscoveryPreference != null
&& !mLastDiscoveryPreference.getPreferredFeatures().isEmpty())
- || !getSessionInfos().isEmpty();
+ || !getSessionInfos().isEmpty()
+ || mIsManagerScanning;
}
return false;
}
@@ -311,13 +325,12 @@
}
}
- private void onProviderStateUpdated(Connection connection,
- MediaRoute2ProviderInfo providerInfo) {
+ private void onProviderUpdated(Connection connection, MediaRoute2ProviderInfo providerInfo) {
if (mActiveConnection != connection) {
return;
}
if (DEBUG) {
- Slog.d(TAG, this + ": State changed ");
+ Slog.d(TAG, this + ": updated");
}
setAndNotifyProviderState(providerInfo);
}
@@ -350,40 +363,44 @@
mCallback.onSessionCreated(this, requestId, newSession);
}
- private void onSessionUpdated(Connection connection, RoutingSessionInfo updatedSession) {
+ private int findSessionByIdLocked(RoutingSessionInfo session) {
+ for (int i = 0; i < mSessionInfos.size(); i++) {
+ if (TextUtils.equals(mSessionInfos.get(i).getId(), session.getId())) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+
+ private void onSessionsUpdated(Connection connection, List<RoutingSessionInfo> sessions) {
if (mActiveConnection != connection) {
return;
}
- if (updatedSession == null) {
- Slog.w(TAG, "onSessionUpdated: Ignoring null session sent from "
- + mComponentName);
- return;
- }
- updatedSession = assignProviderIdForSession(updatedSession);
-
- boolean found = false;
+ int targetIndex = 0;
synchronized (mLock) {
- for (int i = 0; i < mSessionInfos.size(); i++) {
- if (mSessionInfos.get(i).getId().equals(updatedSession.getId())) {
- mSessionInfos.set(i, updatedSession);
- found = true;
- break;
+ for (RoutingSessionInfo session : sessions) {
+ if (session == null) continue;
+ session = assignProviderIdForSession(session);
+
+ int sourceIndex = findSessionByIdLocked(session);
+ if (sourceIndex < 0) {
+ mSessionInfos.add(targetIndex++, session);
+ dispatchSessionCreated(REQUEST_ID_NONE, session);
+ } else if (sourceIndex < targetIndex) {
+ Slog.w(TAG, "Ignoring duplicate session ID: " + session.getId());
+ } else {
+ mSessionInfos.set(sourceIndex, session);
+ Collections.swap(mSessionInfos, sourceIndex, targetIndex++);
+ dispatchSessionUpdated(session);
}
}
-
- if (!found) {
- for (RoutingSessionInfo releasingSession : mReleasingSessions) {
- if (TextUtils.equals(releasingSession.getId(), updatedSession.getId())) {
- return;
- }
- }
- Slog.w(TAG, "onSessionUpdated: Matching session info not found");
- return;
+ for (int i = mSessionInfos.size() - 1; i >= targetIndex; i--) {
+ RoutingSessionInfo releasedSession = mSessionInfos.remove(i);
+ dispatchSessionReleased(releasedSession);
}
}
-
- mCallback.onSessionUpdated(this, updatedSession);
}
private void onSessionReleased(Connection connection, RoutingSessionInfo releaedSession) {
@@ -424,6 +441,21 @@
mCallback.onSessionReleased(this, releaedSession);
}
+ private void dispatchSessionCreated(long requestId, RoutingSessionInfo session) {
+ mHandler.sendMessage(
+ obtainMessage(mCallback::onSessionCreated, this, requestId, session));
+ }
+
+ private void dispatchSessionUpdated(RoutingSessionInfo session) {
+ mHandler.sendMessage(
+ obtainMessage(mCallback::onSessionUpdated, this, session));
+ }
+
+ private void dispatchSessionReleased(RoutingSessionInfo session) {
+ mHandler.sendMessage(
+ obtainMessage(mCallback::onSessionReleased, this, session));
+ }
+
private RoutingSessionInfo assignProviderIdForSession(RoutingSessionInfo sessionInfo) {
return new RoutingSessionInfo.Builder(sessionInfo)
.setOwnerPackageName(mComponentName.getPackageName())
@@ -436,7 +468,7 @@
return;
}
- if (requestId == MediaRoute2ProviderService.REQUEST_ID_NONE) {
+ if (requestId == REQUEST_ID_NONE) {
Slog.w(TAG, "onRequestFailed: Ignoring requestId REQUEST_ID_NONE");
return;
}
@@ -561,16 +593,16 @@
mHandler.post(() -> onConnectionDied(Connection.this));
}
- void postProviderStateUpdated(MediaRoute2ProviderInfo providerInfo) {
- mHandler.post(() -> onProviderStateUpdated(Connection.this, providerInfo));
+ void postProviderUpdated(MediaRoute2ProviderInfo providerInfo) {
+ mHandler.post(() -> onProviderUpdated(Connection.this, providerInfo));
}
void postSessionCreated(long requestId, RoutingSessionInfo sessionInfo) {
mHandler.post(() -> onSessionCreated(Connection.this, requestId, sessionInfo));
}
- void postSessionUpdated(RoutingSessionInfo sessionInfo) {
- mHandler.post(() -> onSessionUpdated(Connection.this, sessionInfo));
+ void postSessionsUpdated(List<RoutingSessionInfo> sessionInfo) {
+ mHandler.post(() -> onSessionsUpdated(Connection.this, sessionInfo));
}
void postSessionReleased(RoutingSessionInfo sessionInfo) {
@@ -595,10 +627,10 @@
}
@Override
- public void updateState(MediaRoute2ProviderInfo providerInfo) {
+ public void notifyProviderUpdated(MediaRoute2ProviderInfo providerInfo) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postProviderStateUpdated(providerInfo);
+ connection.postProviderUpdated(providerInfo);
}
}
@@ -611,10 +643,10 @@
}
@Override
- public void notifySessionUpdated(RoutingSessionInfo sessionInfo) {
+ public void notifySessionsUpdated(List<RoutingSessionInfo> sessionInfo) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postSessionUpdated(sessionInfo);
+ connection.postSessionsUpdated(sessionInfo);
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 1dbc8a9..168ca55 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -2156,6 +2156,8 @@
List<RouterRecord> routerRecords = getRouterRecords();
List<ManagerRecord> managerRecords = getManagerRecords();
+ boolean shouldBindProviders = false;
+
if (service.mPowerManager.isInteractive()) {
boolean isManagerScanning = managerRecords.stream().anyMatch(manager ->
manager.mIsScanning && service.mActivityManager
@@ -2166,6 +2168,7 @@
discoveryPreferences = routerRecords.stream()
.map(record -> record.mDiscoveryPreference)
.collect(Collectors.toList());
+ shouldBindProviders = true;
} else {
discoveryPreferences = routerRecords.stream().filter(record ->
service.mActivityManager.getPackageImportance(record.mPackageName)
@@ -2175,6 +2178,13 @@
}
}
+ for (MediaRoute2Provider provider : mRouteProviders) {
+ if (provider instanceof MediaRoute2ProviderServiceProxy) {
+ ((MediaRoute2ProviderServiceProxy) provider)
+ .setManagerScanning(shouldBindProviders);
+ }
+ }
+
synchronized (service.mLock) {
RouteDiscoveryPreference newPreference =
new RouteDiscoveryPreference.Builder(discoveryPreferences).build();
diff --git a/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java b/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
index 1e0142c..2cc2ebf 100644
--- a/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
+++ b/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
@@ -98,7 +98,8 @@
private String getSessionIdInternal(int userId) {
byte[] byteId = new byte[16]; // 128 bits
mSecureRandom.nextBytes(byteId);
- String id = Base64.encodeToString(byteId, Base64.DEFAULT);
+ String id = Base64.encodeToString(
+ byteId, Base64.NO_PADDING | Base64.NO_WRAP | Base64.URL_SAFE);
return id;
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 4b41466..654b17f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -26,6 +26,7 @@
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
+import static android.os.PowerExemptionManager.reasonCodeToString;
import static android.os.Process.INVALID_UID;
import android.app.ActivityManager;
@@ -192,13 +193,12 @@
}
}
- void tempPowerSaveWlChanged(int appId, boolean added) {
+ void tempPowerSaveWlChanged(int appId, boolean added, int reasonCode, String reason) {
synchronized (mLock) {
if (LOGV || appId == UserHandle.getAppId(mDebugUid)) {
- Slog.v(TAG,
- getTempPowerSaveWlChangedLog(appId, added));
+ Slog.v(TAG, getTempPowerSaveWlChangedLog(appId, added, reasonCode, reason));
}
- mEventsBuffer.tempPowerSaveWlChanged(appId, added);
+ mEventsBuffer.tempPowerSaveWlChanged(appId, added, reasonCode, reason);
}
}
@@ -326,8 +326,10 @@
return "Parole state: " + paroleOn;
}
- private static String getTempPowerSaveWlChangedLog(int appId, boolean added) {
- return "temp-power-save whitelist for " + appId + " changed to: " + added;
+ private static String getTempPowerSaveWlChangedLog(int appId, boolean added,
+ int reasonCode, String reason) {
+ return "temp-power-save whitelist for " + appId + " changed to: " + added
+ + "; reason=" + reasonCodeToString(reasonCode) + " <" + reason + ">";
}
private static String getUidFirewallRuleChangedLog(int chain, int uid, int rule) {
@@ -497,14 +499,17 @@
data.timeStamp = System.currentTimeMillis();
}
- public void tempPowerSaveWlChanged(int appId, boolean added) {
+ public void tempPowerSaveWlChanged(int appId, boolean added,
+ int reasonCode, String reason) {
final Data data = getNextSlot();
if (data == null) return;
data.reset();
data.type = EVENT_TEMP_POWER_SAVE_WL_CHANGED;
data.ifield1 = appId;
+ data.ifield2 = reasonCode;
data.bfield1 = added;
+ data.sfield1 = reason;
data.timeStamp = System.currentTimeMillis();
}
@@ -571,7 +576,8 @@
case EVENT_PAROLE_STATE_CHANGED:
return getParoleStateChanged(data.bfield1);
case EVENT_TEMP_POWER_SAVE_WL_CHANGED:
- return getTempPowerSaveWlChangedLog(data.ifield1, data.bfield1);
+ return getTempPowerSaveWlChangedLog(data.ifield1, data.bfield1,
+ data.ifield2, data.sfield1);
case EVENT_UID_FIREWALL_RULE_CHANGED:
return getUidFirewallRuleChangedLog(data.ifield1, data.ifield2, data.ifield3);
case EVENT_FIREWALL_CHAIN_ENABLED:
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 2e4d41c..03a63b9 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -17,9 +17,11 @@
package com.android.server.net;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.net.Network;
import android.net.NetworkTemplate;
import android.net.netstats.provider.NetworkStatsProvider;
+import android.os.PowerExemptionManager.ReasonCode;
import android.telephony.SubscriptionPlan;
import java.util.Set;
@@ -41,9 +43,13 @@
* that network rules for that appId can be updated.
*
* @param appId The appId which has been updated in the allowlist.
- * @param added Denotes whether the {@param appId} has been added or removed from the allowlist.
+ * @param added Denotes whether the {@code appId} has been added or removed from the allowlist.
+ * @param reasonCode one of {@link ReasonCode} indicating the reason for the change.
+ * Only valid when {@code added} is {@code true}.
+ * @param reason an optional human-readable reason explaining why the app is temp allow-listed.
*/
- public abstract void onTempPowerSaveWhitelistChange(int appId, boolean added);
+ public abstract void onTempPowerSaveWhitelistChange(int appId, boolean added,
+ @ReasonCode int reasonCode, @Nullable String reason);
/**
* Return the active {@link SubscriptionPlan} for the given network.
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index cfd5750..21f68ae 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -211,6 +211,7 @@
import android.os.MessageQueue.IdleHandler;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
+import android.os.PowerExemptionManager.ReasonCode;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
@@ -5743,12 +5744,13 @@
}
@Override
- public void onTempPowerSaveWhitelistChange(int appId, boolean added) {
+ public void onTempPowerSaveWhitelistChange(int appId, boolean added,
+ @ReasonCode int reasonCode, @Nullable String reason) {
synchronized (mUidRulesFirstLock) {
if (!mSystemReady) {
return;
}
- mLogger.tempPowerSaveWlChanged(appId, added);
+ mLogger.tempPowerSaveWlChanged(appId, added, reasonCode, reason);
if (added) {
mPowerSaveTempWhitelistAppIds.put(appId, true);
} else {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5b5d5d4..b26485b 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2661,8 +2661,10 @@
mRoleObserver = roleObserver;
LauncherApps launcherApps =
(LauncherApps) getContext().getSystemService(Context.LAUNCHER_APPS_SERVICE);
+ UserManager userManager = (UserManager) getContext().getSystemService(
+ Context.USER_SERVICE);
mShortcutHelper = new ShortcutHelper(launcherApps, mShortcutListener, getLocalService(
- ShortcutServiceInternal.class));
+ ShortcutServiceInternal.class), userManager);
BubbleExtractor bubbsExtractor = mRankingHelper.findExtractor(BubbleExtractor.class);
if (bubbsExtractor != null) {
bubbsExtractor.setShortcutHelper(mShortcutHelper);
diff --git a/services/core/java/com/android/server/notification/ShortcutHelper.java b/services/core/java/com/android/server/notification/ShortcutHelper.java
index b0be206..fc106b8 100644
--- a/services/core/java/com/android/server/notification/ShortcutHelper.java
+++ b/services/core/java/com/android/server/notification/ShortcutHelper.java
@@ -29,6 +29,7 @@
import android.os.Binder;
import android.os.Handler;
import android.os.UserHandle;
+import android.os.UserManager;
import android.text.TextUtils;
import android.util.Slog;
@@ -67,6 +68,7 @@
private LauncherApps mLauncherAppsService;
private ShortcutListener mShortcutListener;
private ShortcutServiceInternal mShortcutServiceInternal;
+ private UserManager mUserManager;
// Key: packageName Value: <shortcutId, notifId>
private HashMap<String, HashMap<String, String>> mActiveShortcutBubbles = new HashMap<>();
@@ -144,10 +146,11 @@
};
ShortcutHelper(LauncherApps launcherApps, ShortcutListener listener,
- ShortcutServiceInternal shortcutServiceInternal) {
+ ShortcutServiceInternal shortcutServiceInternal, UserManager userManager) {
mLauncherAppsService = launcherApps;
mShortcutListener = listener;
mShortcutServiceInternal = shortcutServiceInternal;
+ mUserManager = userManager;
}
@VisibleForTesting
@@ -160,6 +163,11 @@
mShortcutServiceInternal = shortcutServiceInternal;
}
+ @VisibleForTesting
+ void setUserManager(UserManager userManager) {
+ mUserManager = userManager;
+ }
+
/**
* Returns whether the given shortcut info is a conversation shortcut.
*/
@@ -182,7 +190,8 @@
* Only returns shortcut info if it's found and if it's a conversation shortcut.
*/
ShortcutInfo getValidShortcutInfo(String shortcutId, String packageName, UserHandle user) {
- if (mLauncherAppsService == null) {
+ // Shortcuts cannot be accessed when the user is locked.
+ if (mLauncherAppsService == null || !mUserManager.isUserUnlocked(user)) {
return null;
}
final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index c97095d..3369dcd 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -32,6 +32,7 @@
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser.PackageParserException;
+import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
import android.content.pm.parsing.ParsingPackageUtils;
import android.os.Binder;
@@ -45,6 +46,7 @@
import android.util.Singleton;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.apk.ApkSignatureVerifier;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -52,6 +54,7 @@
import com.android.internal.util.Preconditions;
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.utils.TimingsTraceAndSlog;
import com.google.android.collect.Lists;
@@ -390,9 +393,10 @@
throws RemoteException;
/**
- * Performs a non-staged install of an APEX package with given {@code packagePath}.
+ * Performs a non-staged install of the given {@code apexFile}.
*/
- abstract void installPackage(String packagePath) throws PackageManagerException;
+ abstract void installPackage(File apexFile, PackageParser2 packageParser)
+ throws PackageManagerException;
/**
* Dumps various state information to the provided {@link PrintWriter} object.
@@ -979,12 +983,80 @@
waitForApexService().reserveSpaceForCompressedApex(infoList);
}
- @Override
- void installPackage(String packagePath) throws PackageManagerException {
+ private SigningDetails getSigningDetails(PackageInfo pkg) throws PackageManagerException {
+ int minSignatureScheme =
+ ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
+ pkg.applicationInfo.targetSdkVersion);
try {
- // TODO(b/187864524): do pre-install verification.
- waitForApexService().installAndActivatePackage(packagePath);
- // TODO(b/187864524): update mAllPackagesCache.
+ return ApkSignatureVerifier.verify(pkg.applicationInfo.sourceDir,
+ minSignatureScheme);
+ } catch (PackageParserException e) {
+ throw PackageManagerException.from(e);
+ }
+ }
+
+ private void checkApexSignature(PackageInfo existingApexPkg, PackageInfo newApexPkg)
+ throws PackageManagerException {
+ final SigningDetails existingSigningDetails = getSigningDetails(existingApexPkg);
+ final SigningDetails newSigningDetails = getSigningDetails(newApexPkg);
+ if (!newSigningDetails.checkCapability(existingSigningDetails,
+ SigningDetails.CertCapabilities.INSTALLED_DATA)) {
+ throw new PackageManagerException(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
+ "APK container signature of " + newApexPkg.applicationInfo.sourceDir
+ + " is not compatible with currently installed on device");
+ }
+ }
+
+ private void checkDowngrade(PackageInfo existingApexPkg, PackageInfo newApexPkg)
+ throws PackageManagerException {
+ final long currentVersionCode = existingApexPkg.applicationInfo.longVersionCode;
+ final long newVersionCode = newApexPkg.applicationInfo.longVersionCode;
+ if (currentVersionCode > newVersionCode) {
+ throw new PackageManagerException(PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE,
+ "Downgrade of APEX package " + newApexPkg.packageName
+ + " is not allowed");
+ }
+ }
+
+ @Override
+ void installPackage(File apexFile, PackageParser2 packageParser)
+ throws PackageManagerException {
+ try {
+ final int flags = PackageManager.GET_META_DATA
+ | PackageManager.GET_SIGNING_CERTIFICATES
+ | PackageManager.GET_SIGNATURES;
+ final ParsedPackage parsedPackage = packageParser.parsePackage(
+ apexFile, flags, /* useCaches= */ false);
+ final PackageInfo newApexPkg = PackageInfoWithoutStateUtils.generate(parsedPackage,
+ /* apexInfo= */ null, flags);
+ if (newApexPkg == null) {
+ throw new PackageManagerException(PackageManager.INSTALL_FAILED_INVALID_APK,
+ "Failed to generate package info for " + apexFile.getAbsolutePath());
+ }
+ final PackageInfo existingApexPkg = getPackageInfo(newApexPkg.packageName,
+ MATCH_ACTIVE_PACKAGE);
+ if (existingApexPkg == null) {
+ Slog.w(TAG, "Attempting to install new APEX package " + newApexPkg.packageName);
+ throw new PackageManagerException(PackageManager.INSTALL_FAILED_PACKAGE_CHANGED,
+ "It is forbidden to install new APEX packages");
+ }
+ checkApexSignature(existingApexPkg, newApexPkg);
+ checkDowngrade(existingApexPkg, newApexPkg);
+ ApexInfo apexInfo = waitForApexService().installAndActivatePackage(
+ apexFile.getAbsolutePath());
+ final ParsedPackage parsedPackage2 = packageParser.parsePackage(
+ new File(apexInfo.modulePath), flags, /* useCaches= */ false);
+ final PackageInfo finalApexPkg = PackageInfoWithoutStateUtils.generate(
+ parsedPackage, apexInfo, flags);
+ // Installation was successful, time to update mAllPackagesCache
+ synchronized (mLock) {
+ for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) {
+ if (mAllPackagesCache.get(i).equals(existingApexPkg)) {
+ mAllPackagesCache.set(i, finalApexPkg);
+ break;
+ }
+ }
+ }
} catch (RemoteException e) {
throw new PackageManagerException(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
"apexservice not available");
@@ -1262,7 +1334,7 @@
}
@Override
- void installPackage(String packagePath) {
+ void installPackage(File apexFile, PackageParser2 packageParser) {
throw new UnsupportedOperationException("APEX updates are not supported");
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b135e88..9370b14 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -698,14 +698,13 @@
}
final long ident = Binder.clearCallingIdentity();
try {
- return injectCreatePendingIntent(mContext.createPackageContextAsUser(packageName,
- 0, user), 0 /* requestCode */, intents, FLAG_MUTABLE, opts, user);
- } catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "Cannot create pending intent from shortcut " + shortcutId, e);
+ return injectCreatePendingIntent(0 /* requestCode */, intents,
+ FLAG_MUTABLE, opts, packageName, mPackageManagerInternal.getPackageUid(
+ packageName, PackageManager.MATCH_DIRECT_BOOT_AUTO,
+ user.getIdentifier()));
} finally {
Binder.restoreCallingIdentity(ident);
}
- return null;
}
@Override
@@ -812,10 +811,10 @@
}
@VisibleForTesting
- PendingIntent injectCreatePendingIntent(Context context, int requestCode,
- @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) {
- return PendingIntent.getActivitiesAsUser(context, requestCode, intents, flags, options,
- user);
+ PendingIntent injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents,
+ int flags, Bundle options, String ownerPackage, int ownerUserId) {
+ return mActivityManagerInternal.getPendingIntentActivityAsApp(requestCode, intents,
+ flags, options, ownerPackage, ownerUserId);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 1f0a8ca..0b63b7d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -653,13 +653,20 @@
}
if (params.isStaged && !isCalledBySystemOrShell(callingUid)) {
- if (mBypassNextStagedInstallerCheck) {
- mBypassNextStagedInstallerCheck = false;
- } else if (!isStagedInstallerAllowed(requestedInstallerPackageName)) {
+ if (!mBypassNextStagedInstallerCheck
+ && !isStagedInstallerAllowed(requestedInstallerPackageName)) {
throw new SecurityException("Installer not allowed to commit staged install");
}
}
+ if (isApex && !isCalledBySystemOrShell(callingUid)) {
+ if (!mBypassNextStagedInstallerCheck
+ && !isStagedInstallerAllowed(requestedInstallerPackageName)) {
+ throw new SecurityException(
+ "Installer not allowed to commit non-staged APEX install");
+ }
+ }
+ mBypassNextStagedInstallerCheck = false;
if (!params.isMultiPackage) {
// Only system components can circumvent runtime permissions when installing.
if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 8202587..4b0eb65 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -3760,11 +3760,6 @@
return true;
}
- // Retrying commit.
- if (mIncrementalFileStorages != null) {
- return false;
- }
-
final List<InstallationFileParcel> addedFiles = new ArrayList<>();
final List<String> removedFiles = new ArrayList<>();
@@ -3925,18 +3920,24 @@
(pkgInfo != null && pkgInfo.applicationInfo != null) ? new File(
pkgInfo.applicationInfo.getCodePath()).getParentFile() : null;
- mIncrementalFileStorages = IncrementalFileStorages.initialize(mContext, stageDir,
- inheritedDir, params, statusListener, healthCheckParams, healthListener,
- addedFiles, perUidReadTimeouts,
- new IPackageLoadingProgressCallback.Stub() {
- @Override
- public void onPackageLoadingProgressChanged(float progress) {
- synchronized (mProgressLock) {
- mIncrementalProgress = progress;
- computeProgressLocked(true);
+ if (mIncrementalFileStorages == null) {
+ mIncrementalFileStorages = IncrementalFileStorages.initialize(mContext,
+ stageDir, inheritedDir, params, statusListener, healthCheckParams,
+ healthListener, addedFiles, perUidReadTimeouts,
+ new IPackageLoadingProgressCallback.Stub() {
+ @Override
+ public void onPackageLoadingProgressChanged(float progress) {
+ synchronized (mProgressLock) {
+ mIncrementalProgress = progress;
+ computeProgressLocked(true);
+ }
}
- }
- });
+ });
+ } else {
+ // Retrying commit.
+ mIncrementalFileStorages.startLoading(params, statusListener, healthCheckParams,
+ healthListener, perUidReadTimeouts);
+ }
return false;
} catch (IOException e) {
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE, e.getMessage(),
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index be2a63d..a8cc5fd 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2335,11 +2335,11 @@
List<CrossProfileIntentFilter> matchingFilters =
getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
// Check for results that need to skip the current profile.
- ResolveInfo xpResolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent,
- resolvedType, flags, userId);
- if (xpResolveInfo != null) {
+ ResolveInfo skipProfileInfo = querySkipCurrentProfileIntents(matchingFilters,
+ intent, resolvedType, flags, userId);
+ if (skipProfileInfo != null) {
List<ResolveInfo> xpResult = new ArrayList<>(1);
- xpResult.add(xpResolveInfo);
+ xpResult.add(skipProfileInfo);
return new QueryIntentActivitiesResult(
applyPostResolutionFilter(
filterIfNotSystemUser(xpResult, userId), instantAppPkgName,
@@ -2354,54 +2354,55 @@
false /*skipPackageCheck*/, flags);
// Check for cross profile results.
boolean hasNonNegativePriorityResult = hasNonNegativePriority(result);
- xpResolveInfo = queryCrossProfileIntents(
+ CrossProfileDomainInfo specificXpInfo = queryCrossProfileIntents(
matchingFilters, intent, resolvedType, flags, userId,
hasNonNegativePriorityResult);
- if (xpResolveInfo != null && isUserEnabled(xpResolveInfo.targetUserId)) {
- boolean isVisibleToUser = filterIfNotSystemUser(
- Collections.singletonList(xpResolveInfo), userId).size() > 0;
- if (isVisibleToUser) {
- result.add(xpResolveInfo);
- sortResult = true;
- }
- }
if (intent.hasWebURI()) {
- CrossProfileDomainInfo xpDomainInfo = null;
+ CrossProfileDomainInfo generalXpInfo = null;
final UserInfo parent = getProfileParent(userId);
if (parent != null) {
- xpDomainInfo = getCrossProfileDomainPreferredLpr(intent, resolvedType,
+ generalXpInfo = getCrossProfileDomainPreferredLpr(intent, resolvedType,
flags, userId, parent.id);
}
- if (xpDomainInfo != null) {
- if (xpResolveInfo != null) {
- // If we didn't remove it, the cross-profile ResolveInfo would be twice
- // in the result.
- result.remove(xpResolveInfo);
- }
- if (result.size() == 0 && !addInstant) {
+
+ // Generalized cross profile intents take precedence over specific.
+ // Note that this is the opposite of the intuitive order.
+ CrossProfileDomainInfo prioritizedXpInfo =
+ generalXpInfo != null ? generalXpInfo : specificXpInfo;
+
+ if (!addInstant) {
+ if (result.isEmpty() && prioritizedXpInfo != null) {
// No result in current profile, but found candidate in parent user.
// And we are not going to add ephemeral app, so we can return the
// result straight away.
- result.add(xpDomainInfo.resolveInfo);
+ result.add(prioritizedXpInfo.resolveInfo);
+ return new QueryIntentActivitiesResult(
+ applyPostResolutionFilter(result, instantAppPkgName,
+ allowDynamicSplits, filterCallingUid, resolveForStart,
+ userId, intent));
+ } else if (result.size() <= 1 && prioritizedXpInfo == null) {
+ // No result in parent user and <= 1 result in current profile, and we
+ // are not going to add ephemeral app, so we can return the result
+ // without further processing.
return new QueryIntentActivitiesResult(
applyPostResolutionFilter(result, instantAppPkgName,
allowDynamicSplits, filterCallingUid, resolveForStart,
userId, intent));
}
- } else if (result.size() <= 1 && !addInstant) {
- // No result in parent user and <= 1 result in current profile, and we
- // are not going to add ephemeral app, so we can return the result without
- // further processing.
- return new QueryIntentActivitiesResult(
- applyPostResolutionFilter(result, instantAppPkgName,
- allowDynamicSplits, filterCallingUid, resolveForStart, userId,
- intent));
}
+
// We have more than one candidate (combining results from current and parent
// profile), so we need filtering and sorting.
result = filterCandidatesWithDomainPreferredActivitiesLPr(
- intent, flags, result, xpDomainInfo, userId);
+ intent, flags, result, prioritizedXpInfo, userId);
sortResult = true;
+ } else {
+ // If not web Intent, just add result to candidate set and let ResolverActivity
+ // figure it out.
+ if (specificXpInfo != null) {
+ result.add(specificXpInfo.resolveInfo);
+ sortResult = true;
+ }
}
} else {
final PackageSetting setting =
@@ -2833,15 +2834,17 @@
if (ps == null) {
continue;
}
- if (result == null) {
- result = new CrossProfileDomainInfo();
- result.resolveInfo = createForwardingResolveInfoUnchecked(
- new WatchedIntentFilter(), sourceUserId, parentUserId);
- }
- result.highestApprovalLevel = Math.max(mDomainVerificationManager
- .approvalLevelForDomain(ps, intent, resultTargetUser, flags,
- parentUserId), result.highestApprovalLevel);
+ int approvalLevel = mDomainVerificationManager
+ .approvalLevelForDomain(ps, intent, flags, parentUserId);
+
+ if (result == null) {
+ result = new CrossProfileDomainInfo(createForwardingResolveInfoUnchecked(
+ new WatchedIntentFilter(), sourceUserId, parentUserId), approvalLevel);
+ } else {
+ result.highestApprovalLevel =
+ Math.max(approvalLevel, result.highestApprovalLevel);
+ }
}
if (result != null && result.highestApprovalLevel
<= DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE) {
@@ -3088,8 +3091,8 @@
final String packageName = info.activityInfo.packageName;
final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps.getInstantApp(userId)) {
- if (hasAnyDomainApproval(mDomainVerificationManager, ps, intent,
- instantApps, flags, userId)) {
+ if (hasAnyDomainApproval(mDomainVerificationManager, ps, intent, flags,
+ userId)) {
if (DEBUG_INSTANT) {
Slog.v(TAG, "Instant app approved for intent; pkg: "
+ packageName);
@@ -3416,28 +3419,59 @@
}
/**
- * If the filter's target user can handle the intent and is enabled: returns a ResolveInfo
- * that
- * will forward the intent to the filter's target user.
- * Otherwise, returns null.
+ * If the filter's target user can handle the intent and is enabled: a [ResolveInfo] that
+ * will forward the intent to the filter's target user, along with the highest approval of
+ * any handler in the target user. Otherwise, returns null.
*/
- private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter,
- Intent intent,
- String resolvedType, int flags, int sourceUserId) {
+ @Nullable
+ private CrossProfileDomainInfo createForwardingResolveInfo(
+ @NonNull CrossProfileIntentFilter filter, @NonNull Intent intent,
+ @Nullable String resolvedType, int flags, int sourceUserId) {
int targetUserId = filter.getTargetUserId();
+ if (!isUserEnabled(targetUserId)) {
+ return null;
+ }
+
List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
resolvedType, flags, targetUserId);
- if (resultTargetUser != null && isUserEnabled(targetUserId)) {
- // If all the matches in the target profile are suspended, return null.
- for (int i = resultTargetUser.size() - 1; i >= 0; i--) {
- if ((resultTargetUser.get(i).activityInfo.applicationInfo.flags
- & ApplicationInfo.FLAG_SUSPENDED) == 0) {
- return createForwardingResolveInfoUnchecked(filter,
- sourceUserId, targetUserId);
- }
+ if (CollectionUtils.isEmpty(resultTargetUser)) {
+ return null;
+ }
+
+ ResolveInfo forwardingInfo = null;
+ for (int i = resultTargetUser.size() - 1; i >= 0; i--) {
+ ResolveInfo targetUserResolveInfo = resultTargetUser.get(i);
+ if ((targetUserResolveInfo.activityInfo.applicationInfo.flags
+ & ApplicationInfo.FLAG_SUSPENDED) == 0) {
+ forwardingInfo = createForwardingResolveInfoUnchecked(filter, sourceUserId,
+ targetUserId);
+ break;
}
}
- return null;
+
+ if (forwardingInfo == null) {
+ // If all the matches in the target profile are suspended, return null.
+ return null;
+ }
+
+ int highestApprovalLevel = DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE;
+
+ int size = resultTargetUser.size();
+ for (int i = 0; i < size; i++) {
+ ResolveInfo riTargetUser = resultTargetUser.get(i);
+ if (riTargetUser.handleAllWebDataURI) {
+ continue;
+ }
+ String packageName = riTargetUser.activityInfo.packageName;
+ PackageSetting ps = mSettings.getPackageLPr(packageName);
+ if (ps == null) {
+ continue;
+ }
+ highestApprovalLevel = Math.max(highestApprovalLevel, mDomainVerificationManager
+ .approvalLevelForDomain(ps, intent, flags, targetUserId));
+ }
+
+ return new CrossProfileDomainInfo(forwardingInfo, highestApprovalLevel);
}
public ResolveInfo createForwardingResolveInfoUnchecked(WatchedIntentFilter filter,
@@ -3476,34 +3510,59 @@
}
// Return matching ResolveInfo in target user if any.
- private ResolveInfo queryCrossProfileIntents(
+ @Nullable
+ private CrossProfileDomainInfo queryCrossProfileIntents(
List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
int flags, int sourceUserId, boolean matchInCurrentProfile) {
- if (matchingFilters != null) {
- // Two {@link CrossProfileIntentFilter}s can have the same targetUserId and
- // match the same intent. For performance reasons, it is better not to
- // run queryIntent twice for the same userId
- SparseBooleanArray alreadyTriedUserIds = new SparseBooleanArray();
- int size = matchingFilters.size();
- for (int i = 0; i < size; i++) {
- CrossProfileIntentFilter filter = matchingFilters.get(i);
- int targetUserId = filter.getTargetUserId();
- boolean skipCurrentProfile =
- (filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) != 0;
- boolean skipCurrentProfileIfNoMatchFound =
- (filter.getFlags() & PackageManager.ONLY_IF_NO_MATCH_FOUND) != 0;
- if (!skipCurrentProfile && !alreadyTriedUserIds.get(targetUserId)
- && (!skipCurrentProfileIfNoMatchFound || !matchInCurrentProfile)) {
- // Checking if there are activities in the target user that can handle the
- // intent.
- ResolveInfo resolveInfo = createForwardingResolveInfo(filter, intent,
- resolvedType, flags, sourceUserId);
- if (resolveInfo != null) return resolveInfo;
- alreadyTriedUserIds.put(targetUserId, true);
+ if (matchingFilters == null) {
+ return null;
+ }
+ // Two {@link CrossProfileIntentFilter}s can have the same targetUserId and
+ // match the same intent. For performance reasons, it is better not to
+ // run queryIntent twice for the same userId
+ SparseBooleanArray alreadyTriedUserIds = new SparseBooleanArray();
+
+ CrossProfileDomainInfo resultInfo = null;
+
+ int size = matchingFilters.size();
+ for (int i = 0; i < size; i++) {
+ CrossProfileIntentFilter filter = matchingFilters.get(i);
+ int targetUserId = filter.getTargetUserId();
+ boolean skipCurrentProfile =
+ (filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) != 0;
+ boolean skipCurrentProfileIfNoMatchFound =
+ (filter.getFlags() & PackageManager.ONLY_IF_NO_MATCH_FOUND) != 0;
+ if (!skipCurrentProfile && !alreadyTriedUserIds.get(targetUserId)
+ && (!skipCurrentProfileIfNoMatchFound || !matchInCurrentProfile)) {
+ // Checking if there are activities in the target user that can handle the
+ // intent.
+ CrossProfileDomainInfo info = createForwardingResolveInfo(filter, intent,
+ resolvedType, flags, sourceUserId);
+ if (info != null) {
+ resultInfo = info;
+ break;
}
+ alreadyTriedUserIds.put(targetUserId, true);
}
}
- return null;
+
+ if (resultInfo == null) {
+ return null;
+ }
+
+ ResolveInfo forwardingResolveInfo = resultInfo.resolveInfo;
+ if (!isUserEnabled(forwardingResolveInfo.targetUserId)) {
+ return null;
+ }
+
+ List<ResolveInfo> filteredResult =
+ filterIfNotSystemUser(Collections.singletonList(forwardingResolveInfo),
+ sourceUserId);
+ if (filteredResult.isEmpty()) {
+ return null;
+ }
+
+ return resultInfo;
}
private ResolveInfo querySkipCurrentProfileIntents(
@@ -3516,10 +3575,10 @@
if ((filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) != 0) {
// Checking if there are activities in the target user that can handle the
// intent.
- ResolveInfo resolveInfo = createForwardingResolveInfo(filter, intent,
+ CrossProfileDomainInfo info = createForwardingResolveInfo(filter, intent,
resolvedType, flags, sourceUserId);
- if (resolveInfo != null) {
- return resolveInfo;
+ if (info != null) {
+ return info.resolveInfo;
}
}
}
@@ -4029,8 +4088,8 @@
if (ps != null) {
// only check domain verification status if the app is not a browser
if (!info.handleAllWebDataURI) {
- if (hasAnyDomainApproval(mDomainVerificationManager, ps, intent,
- resolvedActivities, flags, userId)) {
+ if (hasAnyDomainApproval(mDomainVerificationManager, ps, intent, flags,
+ userId)) {
if (DEBUG_INSTANT) {
Slog.v(TAG, "DENY instant app;" + " pkg: " + packageName
+ ", approved");
@@ -8167,7 +8226,7 @@
}
if (best == null || cur.priority > best.priority) {
- if (cur.getComponentInfo().enabled) {
+ if (isComponentEffectivelyEnabled(cur.getComponentInfo(), UserHandle.USER_SYSTEM)) {
best = cur;
} else {
Slog.w(TAG, "Domain verification agent found but not enabled");
@@ -9497,21 +9556,19 @@
@Override
public boolean isProtectedBroadcast(String actionName) {
- // allow instant applications
- synchronized (mProtectedBroadcasts) {
- if (mProtectedBroadcasts.contains(actionName)) {
+ if (actionName != null) {
+ // TODO: remove these terrible hacks
+ if (actionName.startsWith("android.net.netmon.lingerExpired")
+ || actionName.startsWith("com.android.server.sip.SipWakeupTimer")
+ || actionName.startsWith("com.android.internal.telephony.data-reconnect")
+ || actionName.startsWith("android.net.netmon.launchCaptivePortalApp")) {
return true;
- } else if (actionName != null) {
- // TODO: remove these terrible hacks
- if (actionName.startsWith("android.net.netmon.lingerExpired")
- || actionName.startsWith("com.android.server.sip.SipWakeupTimer")
- || actionName.startsWith("com.android.internal.telephony.data-reconnect")
- || actionName.startsWith("android.net.netmon.launchCaptivePortalApp")) {
- return true;
- }
}
}
- return false;
+ // allow instant applications
+ synchronized (mProtectedBroadcasts) {
+ return mProtectedBroadcasts.contains(actionName);
+ }
}
@Override
@@ -10131,7 +10188,7 @@
final String packageName = ri.activityInfo.packageName;
final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null && hasAnyDomainApproval(mDomainVerificationManager, ps,
- intent, query, flags, userId)) {
+ intent, flags, userId)) {
return ri;
}
}
@@ -10188,10 +10245,10 @@
*/
private static boolean hasAnyDomainApproval(
@NonNull DomainVerificationManagerInternal manager, @NonNull PackageSetting pkgSetting,
- @NonNull Intent intent, @NonNull List<ResolveInfo> candidates,
- @PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId) {
- return manager.approvalLevelForDomain(pkgSetting, intent, candidates, resolveInfoFlags,
- userId) > DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE;
+ @NonNull Intent intent, @PackageManager.ResolveInfoFlags int resolveInfoFlags,
+ @UserIdInt int userId) {
+ return manager.approvalLevelForDomain(pkgSetting, intent, resolveInfoFlags, userId)
+ > DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE;
}
/**
@@ -10624,7 +10681,20 @@
private static class CrossProfileDomainInfo {
/* ResolveInfo for IntentForwarderActivity to send the intent to the other profile */
ResolveInfo resolveInfo;
- int highestApprovalLevel = DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE;
+ int highestApprovalLevel;
+
+ CrossProfileDomainInfo(ResolveInfo resolveInfo, int highestApprovalLevel) {
+ this.resolveInfo = resolveInfo;
+ this.highestApprovalLevel = highestApprovalLevel;
+ }
+
+ @Override
+ public String toString() {
+ return "CrossProfileDomainInfo{"
+ + "resolveInfo=" + resolveInfo
+ + ", highestApprovalLevel=" + highestApprovalLevel
+ + '}';
+ }
}
private CrossProfileDomainInfo getCrossProfileDomainPreferredLpr(Intent intent,
@@ -15143,9 +15213,10 @@
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
}
- if (!pkg.getProtectedBroadcasts().isEmpty()) {
+ final List<String> protectedBroadcasts = pkg.getProtectedBroadcasts();
+ if (!protectedBroadcasts.isEmpty()) {
synchronized (mProtectedBroadcasts) {
- mProtectedBroadcasts.addAll(pkg.getProtectedBroadcasts());
+ mProtectedBroadcasts.addAll(protectedBroadcasts);
}
}
@@ -16915,6 +16986,7 @@
@Override
public void setInstallerPackageName(String targetPackage, String installerPackageName) {
final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(callingUid);
if (getInstantAppPackageName(callingUid) != null) {
return;
}
@@ -16923,14 +16995,16 @@
PackageSetting targetPackageSetting = mSettings.getPackageLPr(targetPackage);
if (targetPackageSetting == null
|| shouldFilterApplicationLocked(
- targetPackageSetting, callingUid, UserHandle.getUserId(callingUid))) {
+ targetPackageSetting, callingUid, callingUserId)) {
throw new IllegalArgumentException("Unknown target package: " + targetPackage);
}
PackageSetting installerPackageSetting;
if (installerPackageName != null) {
installerPackageSetting = mSettings.getPackageLPr(installerPackageName);
- if (installerPackageSetting == null) {
+ if (installerPackageSetting == null
+ || shouldFilterApplicationLocked(
+ installerPackageSetting, callingUid, callingUserId)) {
throw new IllegalArgumentException("Unknown installer package: "
+ installerPackageName);
}
@@ -17118,7 +17192,7 @@
try {
// Should directory scanning logic be moved to ApexManager for better test coverage?
final File dir = request.args.origin.resolvedFile;
- final String[] apexes = dir.list();
+ final File[] apexes = dir.listFiles();
if (apexes == null) {
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
dir.getAbsolutePath() + " is not a directory");
@@ -17128,7 +17202,9 @@
"Expected exactly one .apex file under " + dir.getAbsolutePath()
+ " got: " + apexes.length);
}
- mApexManager.installPackage(dir.getAbsolutePath() + "/" + apexes[0]);
+ try (PackageParser2 packageParser = mInjector.getScanningPackageParser()) {
+ mApexManager.installPackage(apexes[0], packageParser);
+ }
} catch (PackageManagerException e) {
request.installResult.setError("APEX installation failed", e);
}
@@ -22264,7 +22340,7 @@
UserManagerInternal umInternal = mInjector.getUserManagerInternal();
final int flags;
- if (umInternal.isUserUnlockingOrUnlocked(userId)) {
+ if (StorageManager.isUserKeyUnlocked(userId)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
} else if (umInternal.isUserRunning(userId)) {
flags = StorageManager.FLAG_STORAGE_DE;
@@ -23531,11 +23607,6 @@
throw new IllegalArgumentException("Must specify a component");
}
- boolean componentExists = mComponentResolver.componentExists(componentName);
- if (!componentExists) {
- throw new IllegalArgumentException("Component " + componentName + " not found");
- }
-
int callingUid = Binder.getCallingUid();
String componentPkgName = componentName.getPackageName();
@@ -23567,6 +23638,10 @@
"Changing the label is not allowed for " + componentName);
}
+ if (!mComponentResolver.componentExists(componentName)) {
+ throw new IllegalArgumentException("Component " + componentName + " not found");
+ }
+
if (!pkgSetting.overrideNonLocalizedLabelAndIcon(componentName, nonLocalizedLabel,
icon, userId)) {
// Nothing changed
@@ -24111,6 +24186,42 @@
}
}
+ /**
+ * @return true if the runtime app user enabled state, runtime component user enabled state,
+ * install-time app manifest enabled state, and install-time component manifest enabled state
+ * are all effectively enabled for the given component. Or if the component cannot be found,
+ * returns false.
+ */
+ private boolean isComponentEffectivelyEnabled(@NonNull ComponentInfo componentInfo,
+ @UserIdInt int userId) {
+ synchronized (mLock) {
+ try {
+ String packageName = componentInfo.packageName;
+ int appEnabledSetting =
+ mSettings.getApplicationEnabledSettingLPr(packageName, userId);
+ if (appEnabledSetting == COMPONENT_ENABLED_STATE_DEFAULT) {
+ if (!componentInfo.applicationInfo.enabled) {
+ return false;
+ }
+ } else if (appEnabledSetting != COMPONENT_ENABLED_STATE_ENABLED) {
+ return false;
+ }
+
+ int componentEnabledSetting = mSettings.getComponentEnabledSettingLPr(
+ componentInfo.getComponentName(), userId);
+ if (componentEnabledSetting == COMPONENT_ENABLED_STATE_DEFAULT) {
+ return componentInfo.isEnabled();
+ } else if (componentEnabledSetting != COMPONENT_ENABLED_STATE_ENABLED) {
+ return false;
+ }
+
+ return true;
+ } catch (PackageManager.NameNotFoundException ignored) {
+ return false;
+ }
+ }
+ }
+
@Override
public void enterSafeMode() {
enforceSystemOrRoot("Only the system can request entering safe mode");
@@ -25134,7 +25245,7 @@
UserManagerInternal umInternal = mInjector.getUserManagerInternal();
for (UserInfo user : mUserManager.getUsers(false /* includeDying */)) {
final int flags;
- if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+ if (StorageManager.isUserKeyUnlocked(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
} else if (umInternal.isUserRunning(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE;
@@ -25474,7 +25585,7 @@
StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class);
for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) {
final int flags;
- if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+ if (StorageManager.isUserKeyUnlocked(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
} else if (umInternal.isUserRunning(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE;
@@ -25488,7 +25599,7 @@
// Note: this code block is executed with the Installer lock
// already held, since it's invoked as a side-effect of
// executeBatchLI()
- if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+ if (StorageManager.isUserKeyUnlocked(user.id)) {
// Prepare app data on external storage; currently this is used to
// setup any OBB dirs that were created by the installer correctly.
int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid()));
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 4ebf476..f9c63a9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3772,9 +3772,6 @@
pw.println(" get-oem-permissions TARGET-PACKAGE");
pw.println(" Prints all OEM permissions for a package.");
pw.println("");
- pw.println(" set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
- pw.println(" get-app-link [--user USER_ID] PACKAGE");
- pw.println("");
pw.println(" trim-caches DESIRED_FREE_SPACE [internal|UUID]");
pw.println(" Trim cache files to reach the given free space.");
pw.println("");
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 4bc87a2..7aa1c3a 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3997,15 +3997,18 @@
final int uninstallReason = (shouldMaybeInstall && !shouldReallyInstall) ?
UNINSTALL_REASON_USER_TYPE : UNINSTALL_REASON_UNKNOWN;
ps.setUninstallReason(uninstallReason, userHandle);
- if (!shouldReallyInstall) {
+ if (shouldReallyInstall) {
+ // Need to create a data directory for all apps installed for this user.
+ // Accumulate all required args and call the installer after mPackages lock
+ // has been released
+ final String seInfo = AndroidPackageUtils.getSeInfo(ps.pkg, ps);
+ batch.createAppData(ps.volumeUuid, ps.name, userHandle,
+ StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE,
+ ps.appId, seInfo, ps.pkg.getTargetSdkVersion());
+ } else {
+ // Make sure the app is excluded from storage mapping for this user
writeKernelMappingLPr(ps);
}
- // Need to create a data directory for all apps under this user. Accumulate all
- // required args and call the installer after mPackages lock has been released
- final String seInfo = AndroidPackageUtils.getSeInfo(ps.pkg, ps);
- batch.createAppData(ps.volumeUuid, ps.name, userHandle,
- StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE, ps.appId,
- seInfo, ps.pkg.getTargetSdkVersion());
}
}
t.traceBegin("createAppData");
diff --git a/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java b/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
index f411c98..901f96f 100644
--- a/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
+++ b/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
@@ -61,7 +61,7 @@
* Before saving shortcuts.xml, and returning icons to the launcher, we wait for all pending
* saves to finish. However if it takes more than this long, we just give up and proceed.
*/
- private final long SAVE_WAIT_TIMEOUT_MS = 30 * 1000;
+ private final long SAVE_WAIT_TIMEOUT_MS = 5 * 1000;
private final ShortcutService mService;
@@ -281,7 +281,7 @@
}
final String path = file.getAbsolutePath();
- mService.postValue(shortcut, si -> si.setBitmapPath(path));
+ shortcut.setBitmapPath(path);
} catch (IOException | RuntimeException e) {
Slog.e(ShortcutService.TAG, "Unable to write bitmap to file", e);
@@ -296,14 +296,12 @@
Slog.d(TAG, "Saved bitmap.");
}
if (shortcut != null) {
- mService.postValue(shortcut, si -> {
- if (si.getBitmapPath() == null) {
- removeIcon(si);
- }
+ if (shortcut.getBitmapPath() == null) {
+ removeIcon(shortcut);
+ }
- // Whatever happened, remove this flag.
- si.clearFlags(ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE);
- });
+ // Whatever happened, remove this flag.
+ shortcut.clearFlags(ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE);
}
}
return true;
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 1e9d7e1..5f10277 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1208,16 +1208,6 @@
}
}
- void postValue(@NonNull final ShortcutInfo shortcutInfo,
- @NonNull final Consumer<ShortcutInfo> cb) {
- final String pkg = shortcutInfo.getPackage();
- final int userId = shortcutInfo.getUserId();
- final String id = shortcutInfo.getId();
- synchronized (mLock) {
- getPackageShortcutsLocked(pkg, userId).mutateShortcut(id, shortcutInfo, cb);
- }
- }
-
/** Return the last reset time. */
@GuardedBy("mLock")
long getLastResetTimeLocked() {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index b0f8ee1..a391dbc 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -17,7 +17,9 @@
package com.android.server.pm.permission;
import static android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY;
+import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.Manifest.permission.RECORD_AUDIO;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
@@ -148,6 +150,7 @@
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.permission.PermissionManagerServiceInternal.HotwordDetectionServiceProvider;
import com.android.server.pm.permission.PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.policy.SoftRestrictedPermissionPolicy;
@@ -308,6 +311,9 @@
@NonNull
private final OnPermissionChangeListeners mOnPermissionChangeListeners;
+ @Nullable
+ private HotwordDetectionServiceProvider mHotwordDetectionServiceProvider;
+
// TODO: Take a look at the methods defined in the callback.
// The callback was initially created to support the split between permission
// manager and the package manager. However, it's started to be used for other
@@ -5200,6 +5206,16 @@
public int[] getGidsForUid(int uid) {
return PermissionManagerService.this.getGidsForUid(uid);
}
+
+ @Override
+ public void setHotwordDetectionServiceProvider(HotwordDetectionServiceProvider provider) {
+ mHotwordDetectionServiceProvider = provider;
+ }
+
+ @Override
+ public HotwordDetectionServiceProvider getHotwordDetectionServiceProvider() {
+ return mHotwordDetectionServiceProvider;
+ }
}
/**
@@ -5476,10 +5492,13 @@
private final @NonNull Context mContext;
private final @NonNull AppOpsManager mAppOpsManager;
+ private final @NonNull PermissionManagerServiceInternal mPermissionManagerServiceInternal;
PermissionCheckerService(@NonNull Context context) {
mContext = context;
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
+ mPermissionManagerServiceInternal =
+ LocalServices.getService(PermissionManagerServiceInternal.class);
}
@Override
@@ -5492,10 +5511,12 @@
Objects.requireNonNull(attributionSourceState);
final AttributionSource attributionSource = new AttributionSource(
attributionSourceState);
- final int result = checkPermission(mContext, permission, attributionSource, message,
- forDataDelivery, startDataDelivery, fromDatasource, attributedOp);
+ final int result = checkPermission(mContext, mPermissionManagerServiceInternal,
+ permission, attributionSource, message, forDataDelivery, startDataDelivery,
+ fromDatasource, attributedOp);
// Finish any started op if some step in the attribution chain failed.
- if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED) {
+ if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED
+ && result != PermissionChecker.PERMISSION_SOFT_DENIED) {
if (attributedOp == AppOpsManager.OP_NONE) {
finishDataDelivery(AppOpsManager.permissionToOpCode(permission),
attributionSource.asState(), fromDatasource);
@@ -5581,10 +5602,11 @@
}
@PermissionCheckerManager.PermissionResult
- private static int checkPermission(@NonNull Context context, @NonNull String permission,
- @NonNull AttributionSource attributionSource, @Nullable String message,
- boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource,
- int attributedOp) {
+ private static int checkPermission(@NonNull Context context,
+ @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
+ @NonNull String permission, @NonNull AttributionSource attributionSource,
+ @Nullable String message, boolean forDataDelivery, boolean startDataDelivery,
+ boolean fromDatasource, int attributedOp) {
PermissionInfo permissionInfo = sPlatformPermissions.get(permission);
if (permissionInfo == null) {
@@ -5601,22 +5623,25 @@
}
if (permissionInfo.isAppOp()) {
- return checkAppOpPermission(context, permission, attributionSource, message,
- forDataDelivery, fromDatasource);
+ return checkAppOpPermission(context, permissionManagerServiceInt, permission,
+ attributionSource, message, forDataDelivery, fromDatasource);
}
if (permissionInfo.isRuntime()) {
- return checkRuntimePermission(context, permission, attributionSource, message,
- forDataDelivery, startDataDelivery, fromDatasource, attributedOp);
+ return checkRuntimePermission(context, permissionManagerServiceInt, permission,
+ attributionSource, message, forDataDelivery, startDataDelivery,
+ fromDatasource, attributedOp);
}
- if (!fromDatasource && !checkPermission(context, permission, attributionSource.getUid(),
+ if (!fromDatasource && !checkPermission(context, permissionManagerServiceInt,
+ permission, attributionSource.getUid(),
attributionSource.getRenouncedPermissions())) {
return PermissionChecker.PERMISSION_HARD_DENIED;
}
if (attributionSource.getNext() != null) {
- return checkPermission(context, permission, attributionSource.getNext(), message,
- forDataDelivery, startDataDelivery, /*fromDatasource*/ false, attributedOp);
+ return checkPermission(context, permissionManagerServiceInt, permission,
+ attributionSource.getNext(), message, forDataDelivery, startDataDelivery,
+ /*fromDatasource*/ false, attributedOp);
}
return PermissionChecker.PERMISSION_GRANTED;
@@ -5624,6 +5649,7 @@
@PermissionCheckerManager.PermissionResult
private static int checkAppOpPermission(@NonNull Context context,
+ @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
@NonNull String permission, @NonNull AttributionSource attributionSource,
@Nullable String message, boolean forDataDelivery, boolean fromDatasource) {
final int op = AppOpsManager.permissionToOpCode(permission);
@@ -5667,13 +5693,13 @@
return PermissionChecker.PERMISSION_HARD_DENIED;
}
case AppOpsManager.MODE_DEFAULT: {
- if (!skipCurrentChecks && !checkPermission(context, permission,
- attributionSource.getUid(), attributionSource
- .getRenouncedPermissions())) {
+ if (!skipCurrentChecks && !checkPermission(context,
+ permissionManagerServiceInt, permission, attributionSource.getUid(),
+ attributionSource.getRenouncedPermissions())) {
return PermissionChecker.PERMISSION_HARD_DENIED;
}
- if (next != null && !checkPermission(context, permission,
- next.getUid(), next.getRenouncedPermissions())) {
+ if (next != null && !checkPermission(context, permissionManagerServiceInt,
+ permission, next.getUid(), next.getRenouncedPermissions())) {
return PermissionChecker.PERMISSION_HARD_DENIED;
}
}
@@ -5688,6 +5714,7 @@
}
private static int checkRuntimePermission(@NonNull Context context,
+ @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
@NonNull String permission, @NonNull AttributionSource attributionSource,
@Nullable String message, boolean forDataDelivery, boolean startDataDelivery,
boolean fromDatasource, int attributedOp) {
@@ -5712,13 +5739,13 @@
}
// If we already checked the permission for this one, skip the work
- if (!skipCurrentChecks && !checkPermission(context, permission,
- current.getUid(), current.getRenouncedPermissions())) {
+ if (!skipCurrentChecks && !checkPermission(context, permissionManagerServiceInt,
+ permission, current.getUid(), current.getRenouncedPermissions())) {
return PermissionChecker.PERMISSION_HARD_DENIED;
}
- if (next != null && !checkPermission(context, permission,
- next.getUid(), next.getRenouncedPermissions())) {
+ if (next != null && !checkPermission(context, permissionManagerServiceInt,
+ permission, next.getUid(), next.getRenouncedPermissions())) {
return PermissionChecker.PERMISSION_HARD_DENIED;
}
@@ -5773,10 +5800,26 @@
}
}
- private static boolean checkPermission(@NonNull Context context, @NonNull String permission,
- int uid, @NonNull Set<String> renouncedPermissions) {
- final boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1,
+ private static boolean checkPermission(@NonNull Context context,
+ @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
+ @NonNull String permission, int uid, @NonNull Set<String> renouncedPermissions) {
+ boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1,
uid) == PackageManager.PERMISSION_GRANTED;
+
+ // Override certain permissions checks for the HotwordDetectionService. This service is
+ // an isolated service, which ordinarily cannot hold permissions.
+ // There's probably a cleaner, more generalizable way to do this. For now, this is
+ // the only use case for this, so simply override here.
+ if (!permissionGranted
+ && Process.isIsolated(uid) // simple check which fails-fast for the common case
+ && (permission.equals(RECORD_AUDIO)
+ || permission.equals(CAPTURE_AUDIO_HOTWORD))) {
+ HotwordDetectionServiceProvider hotwordServiceProvider =
+ permissionManagerServiceInt.getHotwordDetectionServiceProvider();
+ permissionGranted = hotwordServiceProvider != null
+ && uid == hotwordServiceProvider.getUid();
+ }
+
if (permissionGranted && renouncedPermissions.contains(permission)
&& context.checkPermission(Manifest.permission.RENOUNCE_PERMISSIONS,
/*pid*/ -1, uid) == PackageManager.PERMISSION_GRANTED) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 895cabc..f4fb810 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -428,4 +428,28 @@
}
}
}
+
+ /**
+ * Sets the provider of the currently active HotwordDetectionService.
+ *
+ * @see HotwordDetectionServiceProvider
+ */
+ void setHotwordDetectionServiceProvider(@Nullable HotwordDetectionServiceProvider provider);
+
+ /**
+ * Gets the provider of the currently active HotwordDetectionService.
+ *
+ * @see HotwordDetectionServiceProvider
+ */
+ @Nullable
+ HotwordDetectionServiceProvider getHotwordDetectionServiceProvider();
+
+ /**
+ * Provides the uid of the currently active
+ * {@link android.service.voice.HotwordDetectionService}, which should be granted RECORD_AUDIO
+ * and CAPTURE_AUDIO_HOTWORD permissions.
+ */
+ interface HotwordDetectionServiceProvider {
+ int getUid();
+ }
}
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
index 65e4e95..262734f 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
@@ -389,7 +389,6 @@
*/
@ApprovalLevel
int approvalLevelForDomain(@NonNull PackageSetting pkgSetting, @NonNull Intent intent,
- @NonNull List<ResolveInfo> candidates,
@PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId);
/**
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index b1b4e2a..ba64d25 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -1717,7 +1717,6 @@
@Override
public int approvalLevelForDomain(@NonNull PackageSetting pkgSetting, @NonNull Intent intent,
- @NonNull List<ResolveInfo> candidates,
@PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId) {
String packageName = pkgSetting.getName();
if (!DomainVerificationUtils.isDomainVerificationIntent(intent, resolveInfoFlags)) {
@@ -1783,9 +1782,26 @@
return APPROVAL_LEVEL_NONE;
}
- if (!pkgUserState.installed || !pkgUserState.isPackageEnabled(pkg)) {
+ if (!pkgUserState.installed) {
if (DEBUG_APPROVAL) {
- debugApproval(packageName, debugObject, userId, false, "package not enabled");
+ debugApproval(packageName, debugObject, userId, false,
+ "package not installed for user");
+ }
+ return APPROVAL_LEVEL_NONE;
+ }
+
+ if (!pkgUserState.isPackageEnabled(pkg)) {
+ if (DEBUG_APPROVAL) {
+ debugApproval(packageName, debugObject, userId, false,
+ "package not enabled for user");
+ }
+ return APPROVAL_LEVEL_NONE;
+ }
+
+ if (pkgUserState.suspended) {
+ if (DEBUG_APPROVAL) {
+ debugApproval(packageName, debugObject, userId, false,
+ "package suspended for user");
}
return APPROVAL_LEVEL_NONE;
}
diff --git a/services/core/java/com/android/server/pm/verify/domain/TEST_MAPPING b/services/core/java/com/android/server/pm/verify/domain/TEST_MAPPING
index 5fcf411..ba4a62c 100644
--- a/services/core/java/com/android/server/pm/verify/domain/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/verify/domain/TEST_MAPPING
@@ -9,7 +9,10 @@
]
},
{
- "name": "CtsDomainVerificationDeviceTestCases"
+ "name": "CtsDomainVerificationDeviceStandaloneTestCases"
+ },
+ {
+ "name": "CtsDomainVerificationDeviceMultiUserTestCases"
},
{
"name": "CtsDomainVerificationHostTestCases"
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index a6c93de..94005b2 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -33,7 +33,10 @@
import android.location.LocationManagerInternal;
import android.net.Uri;
import android.os.IBinder;
+import android.os.Process;
import android.os.UserHandle;
+import android.service.voice.VoiceInteractionManagerInternal;
+import android.service.voice.VoiceInteractionManagerInternal.HotwordDetectionServiceIdentity;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -64,6 +67,11 @@
"android:activity_recognition_allow_listed_tags";
private static final String ACTIVITY_RECOGNITION_TAGS_SEPARATOR = ";";
+ private static ArraySet<String> sExpectedTags = new ArraySet<>(new String[] {
+ "awareness_provider", "activity_recognition_provider", "network_location_provider",
+ "network_location_calibration", "fused_location_provider", "geofencer_provider"});
+
+
@NonNull
private final Object mLock = new Object();
@@ -73,6 +81,9 @@
@NonNull
private final RoleManager mRoleManager;
+ @NonNull
+ private final VoiceInteractionManagerInternal mVoiceInteractionManagerInternal;
+
/**
* The locking policy around the location tags is a bit special. Since we want to
* avoid grabbing the lock on every op note we are taking the approach where the
@@ -96,6 +107,8 @@
public AppOpsPolicy(@NonNull Context context) {
mContext = context;
mRoleManager = mContext.getSystemService(RoleManager.class);
+ mVoiceInteractionManagerInternal = LocalServices.getService(
+ VoiceInteractionManagerInternal.class);
final LocationManagerInternal locationManagerInternal = LocalServices.getService(
LocationManagerInternal.class);
@@ -145,7 +158,7 @@
public int checkOperation(int code, int uid, String packageName,
@Nullable String attributionTag, boolean raw,
QuintFunction<Integer, Integer, String, String, Boolean, Integer> superImpl) {
- return superImpl.apply(code, uid, packageName, attributionTag, raw);
+ return superImpl.apply(code, resolveUid(code, uid), packageName, attributionTag, raw);
}
@Override
@@ -159,8 +172,8 @@
@Nullable String attributionTag, boolean shouldCollectAsyncNotedOp, @Nullable
String message, boolean shouldCollectMessage, @NonNull HeptFunction<Integer, Integer,
String, String, Boolean, String, Boolean, SyncNotedAppOp> superImpl) {
- return superImpl.apply(resolveDatasourceOp(code, uid, packageName, attributionTag), uid,
- packageName, attributionTag, shouldCollectAsyncNotedOp,
+ return superImpl.apply(resolveDatasourceOp(code, uid, packageName, attributionTag),
+ resolveUid(code, uid), packageName, attributionTag, shouldCollectAsyncNotedOp,
message, shouldCollectMessage);
}
@@ -185,8 +198,9 @@
String, Boolean, Boolean, String, Boolean, Integer, Integer,
SyncNotedAppOp> superImpl) {
return superImpl.apply(token, resolveDatasourceOp(code, uid, packageName, attributionTag),
- uid, packageName, attributionTag, startIfModeDefault, shouldCollectAsyncNotedOp,
- message, shouldCollectMessage, attributionFlags, attributionChainId);
+ resolveUid(code, uid), packageName, attributionTag, startIfModeDefault,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage, attributionFlags,
+ attributionChainId);
}
@Override
@@ -222,8 +236,14 @@
if (resolvedCode != code) {
if (isDatasourceAttributionTag(uid, packageName, attributionTag,
mLocationTags)) {
+ if (packageName.equals("com.google.android.gms")
+ && !sExpectedTags.contains(attributionTag)) {
+ Log.i("AppOpsDebugRemapping", "remapping " + packageName + " location "
+ + "for tag " + attributionTag);
+ }
return resolvedCode;
- } else if (packageName.equals("com.google.android.gms")) {
+ } else if (packageName.equals("com.google.android.gms")
+ && sExpectedTags.contains(attributionTag)) {
Log.i("AppOpsDebugRemapping", "NOT remapping " + packageName + " code "
+ code + " for tag " + attributionTag);
}
@@ -232,10 +252,14 @@
if (resolvedCode != code) {
if (isDatasourceAttributionTag(uid, packageName, attributionTag,
mActivityRecognitionTags)) {
- Log.i("AppOpsDebugRemapping", "remapping " + packageName + " code "
- + code + " to " + resolvedCode + " for tag " + attributionTag);
+ if (packageName.equals("com.google.android.gms")
+ && !sExpectedTags.contains(attributionTag)) {
+ Log.i("AppOpsDebugRemapping", "remapping " + packageName + " "
+ + "activity recognition for tag " + attributionTag);
+ }
return resolvedCode;
- } else if (packageName.equals("com.google.android.gms")) {
+ } else if (packageName.equals("com.google.android.gms")
+ && sExpectedTags.contains(attributionTag)) {
Log.i("AppOpsDebugRemapping", "NOT remapping " + packageName
+ " code " + code + " for tag " + attributionTag);
}
@@ -351,13 +375,15 @@
if (appIdTags != null) {
final ArraySet<String> packageTags = appIdTags.get(packageName);
if (packageTags != null && packageTags.contains(attributionTag)) {
- if (packageName.equals("com.google.android.gms")) {
+ if (packageName.equals("com.google.android.gms")
+ && !sExpectedTags.contains(attributionTag)) {
Log.i("AppOpsDebugRemapping", packageName + " tag "
+ attributionTag + " in " + packageTags);
}
return true;
}
- if (packageName.equals("com.google.android.gms")) {
+ if (packageName.equals("com.google.android.gms")
+ && sExpectedTags.contains(attributionTag)) {
Log.i("AppOpsDebugRemapping", packageName + " tag " + attributionTag
+ " NOT in " + packageTags);
}
@@ -387,4 +413,23 @@
}
return code;
}
+
+ private int resolveUid(int code, int uid) {
+ // The HotwordDetectionService is an isolated service, which ordinarily cannot hold
+ // permissions. So we allow it to assume the owning package identity for certain
+ // operations.
+ // Note: The package name coming from the audio server is already the one for the owning
+ // package, so we don't need to modify it.
+ if (Process.isIsolated(uid) // simple check which fails-fast for the common case
+ && (code == AppOpsManager.OP_RECORD_AUDIO
+ || code == AppOpsManager.OP_RECORD_AUDIO_HOTWORD)) {
+ final HotwordDetectionServiceIdentity hotwordDetectionServiceIdentity =
+ mVoiceInteractionManagerInternal.getHotwordDetectionServiceIdentity();
+ if (hotwordDetectionServiceIdentity != null
+ && uid == hotwordDetectionServiceIdentity.getIsolatedUid()) {
+ uid = hotwordDetectionServiceIdentity.getOwnerUid();
+ }
+ }
+ return uid;
+ }
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f3b8c7e..e6adeb3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1181,6 +1181,13 @@
if (FactoryTest.isLongPressOnPowerOffEnabled()) {
return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
}
+
+ // If the config indicates the assistant behavior but the device isn't yet provisioned, show
+ // global actions instead.
+ if (mLongPressOnPowerBehavior == LONG_PRESS_POWER_ASSISTANT && !isDeviceProvisioned()) {
+ return LONG_PRESS_POWER_GLOBAL_ACTIONS;
+ }
+
return mLongPressOnPowerBehavior;
}
@@ -3044,7 +3051,7 @@
private int handleStartTransitionForKeyguardLw(boolean keyguardGoingAway, long duration) {
final int res = applyKeyguardOcclusionChange();
if (res != 0) return res;
- if (!WindowManagerService.sEnableRemoteKeyguardAnimation && keyguardGoingAway) {
+ if (!WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation && keyguardGoingAway) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
startKeyguardExitAnimation(SystemClock.uptimeMillis(), duration);
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index cdce660..0535af5 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -264,7 +264,8 @@
*/
@Deprecated
public void setOccluded(boolean isOccluded, boolean animate) {
- if (!WindowManagerService.sEnableRemoteKeyguardAnimation && mKeyguardService != null) {
+ if (!WindowManagerService.sEnableRemoteKeyguardOccludeAnimation
+ && mKeyguardService != null) {
if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ") animate=" + animate);
mKeyguardService.setOccluded(isOccluded, animate);
}
@@ -405,7 +406,8 @@
}
public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
- if (!WindowManagerService.sEnableRemoteKeyguardAnimation && mKeyguardService != null) {
+ if (!WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation
+ && mKeyguardService != null) {
mKeyguardService.startKeyguardExitAnimation(startTime, fadeoutDuration);
}
}
diff --git a/services/core/java/com/android/server/servicewatcher/ServiceWatcherImpl.java b/services/core/java/com/android/server/servicewatcher/ServiceWatcherImpl.java
index e718ba3..631be38 100644
--- a/services/core/java/com/android/server/servicewatcher/ServiceWatcherImpl.java
+++ b/services/core/java/com/android/server/servicewatcher/ServiceWatcherImpl.java
@@ -135,6 +135,7 @@
if (forceRebind || !Objects.equals(mServiceConnection.getBoundServiceInfo(),
newBoundServiceInfo)) {
+ Log.i(TAG, "[" + mTag + "] chose new implementation " + newBoundServiceInfo);
MyServiceConnection oldServiceConnection = mServiceConnection;
MyServiceConnection newServiceConnection = new MyServiceConnection(newBoundServiceInfo);
mServiceConnection = newServiceConnection;
@@ -196,7 +197,9 @@
return;
}
- Log.i(TAG, "[" + mTag + "] binding to " + mBoundServiceInfo);
+ if (D) {
+ Log.d(TAG, "[" + mTag + "] binding to " + mBoundServiceInfo);
+ }
Intent bindIntent = new Intent(mBoundServiceInfo.getAction()).setComponent(
mBoundServiceInfo.getComponentName());
@@ -255,9 +258,7 @@
Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
Preconditions.checkState(mBinder == null);
- if (D) {
- Log.d(TAG, "[" + mTag + "] connected to " + component.toShortString());
- }
+ Log.i(TAG, "[" + mTag + "] connected to " + component.toShortString());
mBinder = binder;
@@ -280,9 +281,7 @@
return;
}
- if (D) {
- Log.d(TAG, "[" + mTag + "] disconnected from " + mBoundServiceInfo);
- }
+ Log.i(TAG, "[" + mTag + "] disconnected from " + mBoundServiceInfo);
mBinder = null;
if (mServiceListener != null) {
@@ -294,9 +293,11 @@
public final void onBindingDied(ComponentName component) {
Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
- Log.i(TAG, "[" + mTag + "] " + mBoundServiceInfo + " died");
+ Log.w(TAG, "[" + mTag + "] " + mBoundServiceInfo + " died");
- onServiceChanged(true);
+ // introduce a small delay to prevent spamming binding over and over, since the likely
+ // cause of a binding dying is some package event that may take time to recover from
+ mHandler.postDelayed(() -> onServiceChanged(true), 500);
}
@Override
diff --git a/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java b/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java
index bf54bd5..9b0ef15 100644
--- a/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java
+++ b/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java
@@ -67,7 +67,8 @@
* <ul>
* <li> The matrix does not automatically shrink but there is a compress() method that
* will recover unused space.
- * <li> Equality is a very, very expesive operation.
+ * <li> Equality is a very, very expensive operation because it must walk the matrices
+ * beimg compared element by element.
* </ul>
*/
@@ -79,10 +80,9 @@
static final int STEP = 64;
/**
- * There are 8 bits in a byte. The constant is defined here only to make it easy to
- * find in the code.
+ * The number of bits in the mValues array element.
*/
- private static final int BYTE = 8;
+ private static final int PACKING = 32;
/**
* Constants that index into the string array returned by matrixToString. The primary
@@ -123,7 +123,7 @@
/**
* The boolean array. This array is always {@code mOrder x mOrder} in size.
*/
- private byte[] mValues;
+ private int[] mValues;
/**
* A convenience function called when the elements are added to or removed from the storage.
@@ -157,10 +157,10 @@
throw new RuntimeException("mOrder is " + mOrder + " initCap is " + initialCapacity);
}
- mInUse = new boolean[mOrder];
+ mInUse = ArrayUtils.newUnpaddedBooleanArray(mOrder);
mKeys = ArrayUtils.newUnpaddedIntArray(mOrder);
mMap = ArrayUtils.newUnpaddedIntArray(mOrder);
- mValues = new byte[mOrder * mOrder / 8];
+ mValues = ArrayUtils.newUnpaddedIntArray(mOrder * mOrder / PACKING);
mSize = 0;
}
@@ -301,8 +301,8 @@
*/
private boolean valueAtInternal(int row, int col) {
int element = row * mOrder + col;
- int offset = element / BYTE;
- int mask = 1 << (element % BYTE);
+ int offset = element / PACKING;
+ int mask = 1 << (element % PACKING);
return (mValues[offset] & mask) != 0;
}
@@ -324,8 +324,8 @@
*/
private void setValueAtInternal(int row, int col, boolean value) {
int element = row * mOrder + col;
- int offset = element / BYTE;
- byte mask = (byte) (1 << (element % BYTE));
+ int offset = element / PACKING;
+ int mask = 1 << (element % PACKING);
if (value) {
mValues[offset] |= mask;
} else {
@@ -377,10 +377,10 @@
mSize++;
// Initialize the row and column corresponding to the new index.
- int valueRow = mOrder / BYTE;
- int offset = newIndex / BYTE;
- byte mask = (byte) (~(1 << (newIndex % BYTE)));
- Arrays.fill(mValues, newIndex * valueRow, (newIndex + 1) * valueRow, (byte) 0);
+ int valueRow = mOrder / PACKING;
+ int offset = newIndex / PACKING;
+ int mask = ~(1 << (newIndex % PACKING));
+ Arrays.fill(mValues, newIndex * valueRow, (newIndex + 1) * valueRow, 0);
for (int n = 0; n < mSize; n++) {
mValues[n * valueRow + offset] &= mask;
}
@@ -412,25 +412,36 @@
* Expand the 2D array. This also extends the free list.
*/
private void growMatrix() {
- resizeValues(mOrder + STEP);
+ resizeMatrix(mOrder + STEP);
}
/**
* Resize the values array to the new dimension.
*/
- private void resizeValues(int newOrder) {
-
- boolean[] newInuse = Arrays.copyOf(mInUse, newOrder);
+ private void resizeMatrix(int newOrder) {
+ if (newOrder % STEP != 0) {
+ throw new IllegalArgumentException("matrix order " + newOrder
+ + " is not a multiple of " + STEP);
+ }
int minOrder = Math.min(mOrder, newOrder);
- byte[] newValues = new byte[newOrder * newOrder / BYTE];
+ boolean[] newInUse = ArrayUtils.newUnpaddedBooleanArray(newOrder);
+ System.arraycopy(mInUse, 0, newInUse, 0, minOrder);
+ int[] newMap = ArrayUtils.newUnpaddedIntArray(newOrder);
+ System.arraycopy(mMap, 0, newMap, 0, minOrder);
+ int[] newKeys = ArrayUtils.newUnpaddedIntArray(newOrder);
+ System.arraycopy(mKeys, 0, newKeys, 0, minOrder);
+
+ int[] newValues = ArrayUtils.newUnpaddedIntArray(newOrder * newOrder / PACKING);
for (int i = 0; i < minOrder; i++) {
- int row = mOrder * i / BYTE;
- int newRow = newOrder * i / BYTE;
- System.arraycopy(mValues, row, newValues, newRow, minOrder / BYTE);
+ int row = mOrder * i / PACKING;
+ int newRow = newOrder * i / PACKING;
+ System.arraycopy(mValues, row, newValues, newRow, minOrder / PACKING);
}
- mInUse = newInuse;
+ mInUse = newInUse;
+ mMap = newMap;
+ mKeys = newKeys;
mValues = newValues;
mOrder = newOrder;
}
@@ -482,21 +493,21 @@
int src = mMap[srcIndex];
mInUse[src] = false;
mMap[srcIndex] = dst;
- System.arraycopy(mValues, src * mOrder / BYTE,
- mValues, dst * mOrder / BYTE,
- mOrder / BYTE);
- int srcOffset = (src / BYTE);
- byte srcMask = (byte) (1 << (src % BYTE));
- int dstOffset = (dst / BYTE);
- byte dstMask = (byte) (1 << (dst % BYTE));
+ System.arraycopy(mValues, src * mOrder / PACKING,
+ mValues, dst * mOrder / PACKING,
+ mOrder / PACKING);
+ int srcOffset = (src / PACKING);
+ int srcMask = 1 << (src % PACKING);
+ int dstOffset = (dst / PACKING);
+ int dstMask = 1 << (dst % PACKING);
for (int i = 0; i < mOrder; i++) {
if ((mValues[srcOffset] & srcMask) == 0) {
mValues[dstOffset] &= ~dstMask;
} else {
mValues[dstOffset] |= dstMask;
}
- srcOffset += mOrder / BYTE;
- dstOffset += mOrder / BYTE;
+ srcOffset += mOrder / PACKING;
+ dstOffset += mOrder / PACKING;
}
}
}
@@ -508,7 +519,7 @@
pack();
int unused = (mOrder - mSize) / STEP;
if (unused > 0) {
- resizeValues(mOrder - (unused * STEP));
+ resizeMatrix(mOrder - (unused * STEP));
}
}
diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
index 7320359..ee7bf5f 100644
--- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
+++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
@@ -122,7 +122,6 @@
@NonNull private final VcnContext mVcnContext;
@NonNull private final ParcelUuid mSubscriptionGroup;
- @NonNull private final Set<Integer> mRequiredUnderlyingNetworkCapabilities;
@NonNull private final UnderlyingNetworkTrackerCallback mCb;
@NonNull private final Dependencies mDeps;
@NonNull private final Handler mHandler;
@@ -147,13 +146,11 @@
@NonNull VcnContext vcnContext,
@NonNull ParcelUuid subscriptionGroup,
@NonNull TelephonySubscriptionSnapshot snapshot,
- @NonNull Set<Integer> requiredUnderlyingNetworkCapabilities,
@NonNull UnderlyingNetworkTrackerCallback cb) {
this(
vcnContext,
subscriptionGroup,
snapshot,
- requiredUnderlyingNetworkCapabilities,
cb,
new Dependencies());
}
@@ -162,16 +159,11 @@
@NonNull VcnContext vcnContext,
@NonNull ParcelUuid subscriptionGroup,
@NonNull TelephonySubscriptionSnapshot snapshot,
- @NonNull Set<Integer> requiredUnderlyingNetworkCapabilities,
@NonNull UnderlyingNetworkTrackerCallback cb,
@NonNull Dependencies deps) {
mVcnContext = Objects.requireNonNull(vcnContext, "Missing vcnContext");
mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
mLastSnapshot = Objects.requireNonNull(snapshot, "Missing snapshot");
- mRequiredUnderlyingNetworkCapabilities =
- Objects.requireNonNull(
- requiredUnderlyingNetworkCapabilities,
- "Missing requiredUnderlyingNetworkCapabilities");
mCb = Objects.requireNonNull(cb, "Missing cb");
mDeps = Objects.requireNonNull(deps, "Missing deps");
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 55e3ed6..4936970 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -674,7 +674,6 @@
mVcnContext,
subscriptionGroup,
mLastSnapshot,
- mConnectionConfig.getAllUnderlyingCapabilities(),
mUnderlyingNetworkTrackerCallback);
mIpSecManager = mVcnContext.getContext().getSystemService(IpSecManager.class);
@@ -2295,13 +2294,11 @@
VcnContext vcnContext,
ParcelUuid subscriptionGroup,
TelephonySubscriptionSnapshot snapshot,
- Set<Integer> requiredUnderlyingNetworkCapabilities,
UnderlyingNetworkTrackerCallback callback) {
return new UnderlyingNetworkTracker(
vcnContext,
subscriptionGroup,
snapshot,
- requiredUnderlyingNetworkCapabilities,
callback);
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index c888e54..53f1035 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -628,7 +628,7 @@
}
// scale if the crop height winds up not matching the recommended metrics
- needScale = wpData.mHeight != cropHint.height()
+ needScale = cropHint.height() > wpData.mHeight
|| cropHint.height() > GLHelper.getMaxTextureSize()
|| cropHint.width() > GLHelper.getMaxTextureSize();
@@ -752,7 +752,7 @@
f = new FileOutputStream(wallpaper.cropFile);
bos = new BufferedOutputStream(f, 32*1024);
- finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
+ finalCrop.compress(Bitmap.CompressFormat.PNG, 100, bos);
bos.flush(); // don't rely on the implicit flush-at-close when noting success
success = true;
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index a781520..2b6a838 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -102,7 +102,6 @@
import com.android.server.apphibernation.AppHibernationService;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
/**
@@ -216,7 +215,7 @@
/** whether the process of the launching activity didn't have any active activity. */
final boolean mProcessSwitch;
/** The activities that should be drawn. */
- final LinkedList<ActivityRecord> mPendingDrawActivities = new LinkedList<>();
+ final ArrayList<ActivityRecord> mPendingDrawActivities = new ArrayList<>(2);
/** The latest activity to have been launched. */
@NonNull ActivityRecord mLastLaunchedActivity;
@@ -328,6 +327,17 @@
return mPendingDrawActivities.isEmpty();
}
+ /** Only keep the records which can be drawn. */
+ void updatePendingDraw() {
+ for (int i = mPendingDrawActivities.size() - 1; i >= 0; i--) {
+ final ActivityRecord r = mPendingDrawActivities.get(i);
+ if (!r.mVisibleRequested) {
+ if (DEBUG_METRICS) Slog.i(TAG, "Discard pending draw " + r);
+ mPendingDrawActivities.remove(i);
+ }
+ }
+ }
+
/**
* @return {@code true} if the transition info should be sent to MetricsLogger, StatsLog, or
* LaunchObserver.
@@ -701,6 +711,7 @@
info.mCurrentTransitionDelayMs = info.calculateDelay(timestampNs);
info.mReason = activityToReason.valueAt(index);
info.mLoggedTransitionStarting = true;
+ info.updatePendingDraw();
if (info.allDrawn()) {
done(false /* abort */, info, "notifyTransitionStarting - all windows drawn",
timestampNs);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9c43dd3..45da45a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -308,6 +308,7 @@
import android.view.animation.Animation;
import android.window.IRemoteTransition;
import android.window.SizeConfigurationBuckets;
+import android.window.SplashScreen;
import android.window.SplashScreenView.SplashScreenViewParcelable;
import android.window.TaskSnapshot;
import android.window.WindowContainerToken;
@@ -6182,6 +6183,14 @@
}
private boolean shouldUseEmptySplashScreen(ActivityRecord sourceRecord) {
+ if (mPendingOptions != null) {
+ final int optionsStyle = mPendingOptions.getSplashScreenStyle();
+ if (optionsStyle == SplashScreen.SPLASH_SCREEN_STYLE_EMPTY) {
+ return true;
+ } else if (optionsStyle == SplashScreen.SPLASH_SCREEN_STYLE_ICON) {
+ return false;
+ }
+ }
if (sourceRecord == null) {
sourceRecord = searchCandidateLaunchingActivity();
}
@@ -8077,6 +8086,9 @@
setState(PAUSED, "relaunchActivityLocked");
}
+ // The activity may be waiting for stop, but that is no longer appropriate for it.
+ mTaskSupervisor.mStoppingActivities.remove(this);
+
configChangeFlags = 0;
deferRelaunchUntilPaused = false;
preserveWindowOnDeferredRelaunch = false;
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index e7c51a4..eaebb6f 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -800,7 +800,8 @@
}
private void handleNonAppWindowsInTransition(@TransitionOldType int transit, int flags) {
- if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY) {
+ if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
+ && !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) {
if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0
&& (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0
&& (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) == 0) {
@@ -812,8 +813,9 @@
}
}
}
- if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
- || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER) {
+ if ((transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
+ || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER)
+ && !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) {
mDisplayContent.startKeyguardExitOnNonAppWindows(
transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
(flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0,
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index e5a634f..b6b8ad1 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -128,12 +128,9 @@
if (w == null || winHint != null && w != winHint) {
return;
}
- final boolean surfaceReady = w.isDrawn() // Regular case
- || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
- final boolean needsLetterbox = surfaceReady && shouldShowLetterboxUi(w);
updateRoundedCorners(w);
updateWallpaperForLetterbox(w);
- if (needsLetterbox) {
+ if (shouldShowLetterboxUi(w)) {
if (mLetterbox == null) {
mLetterbox = new Letterbox(() -> mActivityRecord.makeChildSurface(null),
mActivityRecord.mWmService.mTransactionFactory,
@@ -161,19 +158,26 @@
}
}
- /**
- * @return {@code true} when the main window is letterboxed, this activity isn't transparent
- * and doesn't show a wallpaper.
- */
@VisibleForTesting
boolean shouldShowLetterboxUi(WindowState mainWindow) {
- return mainWindow.areAppWindowBoundsLetterboxed() && mActivityRecord.fillsParent()
+ return isSurfaceReadyAndVisible(mainWindow) && mainWindow.areAppWindowBoundsLetterboxed()
+ // Check that an activity isn't transparent.
+ && mActivityRecord.fillsParent()
// Check for FLAG_SHOW_WALLPAPER explicitly instead of using
// WindowContainer#showWallpaper because the later will return true when this
// activity is using blurred wallpaper for letterbox backgroud.
&& (mainWindow.mAttrs.flags & FLAG_SHOW_WALLPAPER) == 0;
}
+ @VisibleForTesting
+ boolean isSurfaceReadyAndVisible(WindowState mainWindow) {
+ boolean surfaceReady = mainWindow.isDrawn() // Regular case
+ // Waiting for relayoutWindow to call preserveSurface
+ || mainWindow.isDragResizeChanged();
+ return surfaceReady && (mActivityRecord.isVisible()
+ || mActivityRecord.isVisibleRequested());
+ }
+
private Color getLetterboxBackgroundColor() {
final WindowState w = mActivityRecord.findMainWindow();
if (w == null || w.isLetterboxedForDisplayCutout()) {
diff --git a/services/core/java/com/android/server/wm/PinnedTaskController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java
index 7b4b23e..31e2ede 100644
--- a/services/core/java/com/android/server/wm/PinnedTaskController.java
+++ b/services/core/java/com/android/server/wm/PinnedTaskController.java
@@ -268,7 +268,9 @@
matrix.postRotate(90);
}
matrix.postTranslate(dx, dy);
- t.setMatrix(pinnedTask.getSurfaceControl(), matrix, new float[9]);
+ final SurfaceControl leash = pinnedTask.getSurfaceControl();
+ t.setMatrix(leash, matrix, new float[9])
+ .setCornerRadius(leash, pipTx.mCornerRadius);
Slog.i(TAG, "Seamless rotation PiP tx=" + pipTx + " pos=" + dx + "," + dy);
return;
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 2b40b75..5362771 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -156,6 +156,7 @@
@VisibleForTesting
boolean mShouldAttachNavBarToAppDuringTransition;
private boolean mNavigationBarAttachedToApp;
+ private ActivityRecord mNavBarAttachedApp;
/**
* Animates the screenshot of task that used to be controlled by RecentsAnimation.
@@ -392,6 +393,18 @@
Binder.restoreCallingIdentity(token);
}
}
+
+ @Override
+ public void animateNavigationBarToApp(long duration) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mService.getWindowManagerLock()) {
+ animateNavigationBarForAppLaunch(duration);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
};
/**
@@ -613,7 +626,6 @@
|| mDisplayContent.getFadeRotationAnimationController() != null) {
return;
}
- ActivityRecord topActivity = null;
boolean shouldTranslateNavBar = false;
final boolean isDisplayLandscape =
mDisplayContent.getConfiguration().orientation == ORIENTATION_LANDSCAPE;
@@ -630,12 +642,12 @@
continue;
}
shouldTranslateNavBar = isSplitScreenSecondary;
- topActivity = task.getTopVisibleActivity();
+ mNavBarAttachedApp = task.getTopVisibleActivity();
break;
}
final WindowState navWindow = getNavigationBarWindow();
- if (topActivity == null || navWindow == null || navWindow.mToken == null) {
+ if (mNavBarAttachedApp == null || navWindow == null || navWindow.mToken == null) {
return;
}
mNavigationBarAttachedToApp = true;
@@ -643,9 +655,9 @@
final SurfaceControl.Transaction t = navWindow.mToken.getPendingTransaction();
final SurfaceControl navSurfaceControl = navWindow.mToken.getSurfaceControl();
if (shouldTranslateNavBar) {
- navWindow.setSurfaceTranslationY(-topActivity.getBounds().top);
+ navWindow.setSurfaceTranslationY(-mNavBarAttachedApp.getBounds().top);
}
- t.reparent(navSurfaceControl, topActivity.getSurfaceControl());
+ t.reparent(navSurfaceControl, mNavBarAttachedApp.getSurfaceControl());
t.show(navSurfaceControl);
final WindowContainer imeContainer = mDisplayContent.getImeContainer();
@@ -695,9 +707,25 @@
}
}
+ void animateNavigationBarForAppLaunch(long duration) {
+ if (!mShouldAttachNavBarToAppDuringTransition
+ // Skip the case where the nav bar is controlled by fade rotation.
+ || mDisplayContent.getFadeRotationAnimationController() != null
+ || mNavigationBarAttachedToApp
+ || mNavBarAttachedApp == null) {
+ return;
+ }
+
+ final NavBarFadeAnimationController controller =
+ new NavBarFadeAnimationController(mDisplayContent);
+ controller.fadeOutAndInSequentially(duration, null /* fadeOutParent */,
+ mNavBarAttachedApp.getSurfaceControl());
+ }
+
void addTaskToTargets(Task task, OnAnimationFinishedCallback finishedCallback) {
if (mRunner != null) {
mIsAddingTaskToTargets = task != null;
+ mNavBarAttachedApp = task == null ? null : task.getTopVisibleActivity();
// No need to send task appeared when the task target already exists, or when the
// task is being managed as a multi-window mode outside of recents (e.g. bubbles).
if (isAnimatingTask(task) || skipAnimation(task)) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 82d1c04..7af8d8b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -7653,17 +7653,23 @@
void clearLastRecentsAnimationTransaction() {
mLastRecentsAnimationTransaction = null;
mLastRecentsAnimationOverlay = null;
- // reset also the transform introduced by mLastRecentsAnimationTransaction
- getPendingTransaction().setMatrix(mSurfaceControl, Matrix.IDENTITY_MATRIX, new float[9]);
+ // reset also the crop and transform introduced by mLastRecentsAnimationTransaction
+ Rect bounds = getBounds();
+ getPendingTransaction().setMatrix(mSurfaceControl, Matrix.IDENTITY_MATRIX, new float[9])
+ .setWindowCrop(mSurfaceControl, bounds.width(), bounds.height());
}
void maybeApplyLastRecentsAnimationTransaction() {
if (mLastRecentsAnimationTransaction != null) {
+ final SurfaceControl.Transaction tx = getPendingTransaction();
if (mLastRecentsAnimationOverlay != null) {
- getPendingTransaction().reparent(mLastRecentsAnimationOverlay, mSurfaceControl);
+ tx.reparent(mLastRecentsAnimationOverlay, mSurfaceControl);
}
PictureInPictureSurfaceTransaction.apply(mLastRecentsAnimationTransaction,
- mSurfaceControl, getPendingTransaction());
+ mSurfaceControl, tx);
+ // If we are transferring the transform from the root task entering PIP, then also show
+ // the new task immediately
+ tx.show(mSurfaceControl);
mLastRecentsAnimationTransaction = null;
mLastRecentsAnimationOverlay = null;
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 42e2d2f..0cd09807 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -401,7 +401,8 @@
if (dc == null) {
return;
}
- if (transit == TRANSIT_KEYGUARD_GOING_AWAY) {
+ if (transit == TRANSIT_KEYGUARD_GOING_AWAY
+ && !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) {
if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0
&& (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0
&& (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) == 0) {
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 5635c33..95e5fc2 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -340,7 +340,7 @@
rawChanged = true;
}
- boolean changed = wallpaperWin.mWinAnimator.setWallpaperOffset(xOffset, yOffset,
+ boolean changed = wallpaperWin.setWallpaperOffset(xOffset, yOffset,
wallpaperWin.mShouldScaleWallpaper
? zoomOutToScale(wallpaperWin.mWallpaperZoomOut) : 1);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1042a0b..6d51849 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -422,18 +422,41 @@
SystemProperties.getBoolean(DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY, true);
/**
+ * Use WMShell for app transition.
+ */
+ public static final String ENABLE_SHELL_TRANSITIONS = "persist.debug.shell_transit";
+
+ /**
+ * @see #ENABLE_SHELL_TRANSITIONS
+ */
+ public static final boolean sEnableShellTransitions =
+ SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, false);
+
+ /**
* Run Keyguard animation as remote animation in System UI instead of local animation in
* the server process.
+ *
+ * 0: Runs all keyguard animation as local animation
+ * 1: Only runs keyguard going away animation as remote animation
+ * 2: Runs all keyguard animation as remote animation
*/
private static final String ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY =
"persist.wm.enable_remote_keyguard_animation";
+ private static final int sEnableRemoteKeyguardAnimation =
+ SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 1);
+
/**
* @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
*/
- public static boolean sEnableRemoteKeyguardAnimation =
- SystemProperties.getBoolean(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, false);
+ public static final boolean sEnableRemoteKeyguardGoingAwayAnimation = !sEnableShellTransitions
+ && sEnableRemoteKeyguardAnimation >= 1;
+ /**
+ * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
+ */
+ public static final boolean sEnableRemoteKeyguardOccludeAnimation = !sEnableShellTransitions
+ && sEnableRemoteKeyguardAnimation >= 2;
/**
* Allows a fullscreen windowing mode activity to launch in its desired orientation directly
@@ -2887,6 +2910,7 @@
+ " for the display " + displayId + " that does not exist.");
return;
}
+ remoteAnimationAdapter.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid());
displayContent.mAppTransition.overridePendingAppTransitionRemote(
remoteAnimationAdapter);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b28297e..03762b3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -25,6 +25,7 @@
import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.graphics.GraphicsProtos.dumpPointProto;
+import static android.hardware.display.DisplayManager.SWITCHING_TYPE_NONE;
import static android.hardware.input.InputManager.BLOCK_UNTRUSTED_TOUCHES;
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
import static android.os.PowerManager.DRAW_WAKE_LOCK;
@@ -445,6 +446,17 @@
float mOverrideScale = 1;
float mHScale=1, mVScale=1;
float mLastHScale=1, mLastVScale=1;
+
+ // An offset in pixel of the surface contents from the window position. Used for Wallpaper
+ // to provide the effect of scrolling within a large surface. We just use these values as
+ // a cache.
+ int mXOffset = 0;
+ int mYOffset = 0;
+
+ // A scale factor for the surface contents, that will be applied from the center of the visible
+ // region.
+ float mWallpaperScale = 1f;
+
final Matrix mTmpMatrix = new Matrix();
final float[] mTmpMatrixArray = new float[9];
@@ -3917,7 +3929,9 @@
void notifyInsetsChanged() {
ProtoLog.d(WM_DEBUG_IME, "notifyInsetsChanged for %s ", this);
try {
- mClient.insetsChanged(getCompatInsetsState());
+ mClient.insetsChanged(getCompatInsetsState(),
+ hasMoved(),
+ mWindowFrames.isFrameSizeChangeReported());
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver inset state change w=" + this, e);
}
@@ -3933,7 +3947,9 @@
getDisplayContent().getInsetsStateController();
try {
mClient.insetsControlChanged(getCompatInsetsState(),
- stateController.getControlsForDispatch(this));
+ stateController.getControlsForDispatch(this),
+ hasMoved(),
+ mWindowFrames.isFrameSizeChangeReported());
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver inset state change to w=" + this, e);
}
@@ -5433,20 +5449,28 @@
mFrameRateSelectionPriority);
}
- final float refreshRate = refreshRatePolicy.getPreferredRefreshRate(this);
- if (mAppPreferredFrameRate != refreshRate) {
- mAppPreferredFrameRate = refreshRate;
- getPendingTransaction().setFrameRate(
- mSurfaceControl, mAppPreferredFrameRate,
- Surface.FRAME_RATE_COMPATIBILITY_EXACT, Surface.CHANGE_FRAME_RATE_ALWAYS);
+ // If refresh rate switching is disabled there is no point to set the frame rate on the
+ // surface as the refresh rate will be limited by display manager to a single value
+ // and SurfaceFlinger wouldn't be able to change it anyways.
+ if (mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()
+ != SWITCHING_TYPE_NONE) {
+ final float refreshRate = refreshRatePolicy.getPreferredRefreshRate(this);
+ if (mAppPreferredFrameRate != refreshRate) {
+ mAppPreferredFrameRate = refreshRate;
+ getPendingTransaction().setFrameRate(
+ mSurfaceControl, mAppPreferredFrameRate,
+ Surface.FRAME_RATE_COMPATIBILITY_EXACT, Surface.CHANGE_FRAME_RATE_ALWAYS);
+ }
}
}
private void updateScaleIfNeeded() {
- if (mLastGlobalScale != mGlobalScale || mLastHScale != mHScale ||
- mLastVScale != mVScale ) {
+ float newHScale = mHScale * mGlobalScale * mWallpaperScale;
+ float newVScale = mVScale * mGlobalScale * mWallpaperScale;
+ if (mLastHScale != newHScale ||
+ mLastVScale != newVScale ) {
getPendingTransaction().setMatrix(getSurfaceControl(),
- mGlobalScale*mHScale, 0, 0, mGlobalScale*mVScale);
+ newHScale, 0, 0, newVScale);
mLastGlobalScale = mGlobalScale;
mLastHScale = mHScale;
mLastVScale = mVScale;
@@ -5484,6 +5508,7 @@
mSurfacePlacementNeeded = false;
transformFrameToSurfacePosition(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top,
mSurfacePosition);
+ mSurfacePosition.offset(mXOffset, mYOffset);
// Freeze position while we're unrotated, so the surface remains at the position it was
// prior to the rotation.
@@ -6096,4 +6121,15 @@
void markRedrawForSyncReported() {
mRedrawForSyncReported = true;
}
+
+ boolean setWallpaperOffset(int dx, int dy, float scale) {
+ if (mXOffset == dx && mYOffset == dy && Float.compare(mWallpaperScale, scale) == 0) {
+ return false;
+ }
+ mXOffset = dx;
+ mYOffset = dy;
+ mWallpaperScale = scale;
+ scheduleAnimation();
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index ea3b065..9a6e444 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -169,16 +169,6 @@
int mAttrType;
- // An offset in pixel of the surface contents from the window position. Used for Wallpaper
- // to provide the effect of scrolling within a large surface. We just use these values as
- // a cache.
- int mXOffset = 0;
- int mYOffset = 0;
-
- // A scale factor for the surface contents, that will be applied from the center of the visible
- // region.
- float mWallpaperScale = 1f;
-
private final Rect mTmpSize = new Rect();
/**
@@ -502,18 +492,6 @@
}
final WindowState w = mWin;
-
- if (!w.mSeamlesslyRotated) {
- // Used to offset the WSA when stack position changes before a resize.
- int xOffset = mXOffset;
- int yOffset = mYOffset;
- if (!mIsWallpaper) {
- mSurfaceController.setPosition(t, xOffset, yOffset);
- } else {
- setWallpaperPositionAndScale(t, xOffset, yOffset, mWallpaperScale);
- }
- }
-
final Task task = w.getTask();
if (shouldConsumeMainWindowSizeTransaction()) {
if (isInBlastSync()) {
@@ -575,14 +553,8 @@
"SURFACE controller=%s alpha=%f HScale=%f, VScale=%f: %s",
mSurfaceController, mShownAlpha, w.mHScale, w.mVScale, w);
- boolean prepared = true;
-
- if (mIsWallpaper) {
- setWallpaperPositionAndScale(t, mXOffset, mYOffset, mWallpaperScale);
- } else {
- prepared =
- mSurfaceController.prepareToShowInTransaction(t, mShownAlpha);
- }
+ boolean prepared =
+ mSurfaceController.prepareToShowInTransaction(t, mShownAlpha);
if (prepared && mDrawState == HAS_DRAWN) {
if (mLastHidden) {
@@ -635,53 +607,6 @@
}
}
- boolean setWallpaperOffset(int dx, int dy, float scale) {
- if (mXOffset == dx && mYOffset == dy && Float.compare(mWallpaperScale, scale) == 0) {
- return false;
- }
- mXOffset = dx;
- mYOffset = dy;
- mWallpaperScale = scale;
-
- if (mSurfaceController != null) {
- try {
- if (SHOW_LIGHT_TRANSACTIONS) {
- Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
- }
- mService.openSurfaceTransaction();
- setWallpaperPositionAndScale(SurfaceControl.getGlobalTransaction(), dx, dy, scale);
- } catch (RuntimeException e) {
- Slog.w(TAG, "Error positioning surface of " + mWin
- + " pos=(" + dx + "," + dy + ")", e);
- } finally {
- mService.closeSurfaceTransaction("setWallpaperOffset");
- if (SHOW_LIGHT_TRANSACTIONS) {
- Slog.i(TAG, "<<< CLOSE TRANSACTION setWallpaperOffset");
- }
- }
- }
-
- return true;
- }
-
- private void setWallpaperPositionAndScale(SurfaceControl.Transaction t, int dx, int dy,
- float scale) {
- DisplayInfo displayInfo = mWin.getDisplayInfo();
- Matrix matrix = mWin.mTmpMatrix;
- matrix.setTranslate(dx, dy);
- matrix.postScale(scale, scale, displayInfo.logicalWidth / 2f,
- displayInfo.logicalHeight / 2f);
- matrix.getValues(mWin.mTmpMatrixArray);
- matrix.reset();
-
- mSurfaceController.setPosition(t,mWin.mTmpMatrixArray[MTRANS_X],
- mWin.mTmpMatrixArray[MTRANS_Y]);
- mSurfaceController.setMatrix(t, mWin.mTmpMatrixArray[MSCALE_X],
- mWin.mTmpMatrixArray[MSKEW_Y],
- mWin.mTmpMatrixArray[MSKEW_X],
- mWin.mTmpMatrixArray[MSCALE_Y]);
- }
-
/**
* Try to change the pixel format without recreating the surface. This
* will be common in the case of changing from PixelFormat.OPAQUE to
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index b754644..e13ef99 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1987,43 +1987,39 @@
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
jobject jLights = env->NewObject(gArrayListClassInfo.clazz, gArrayListClassInfo.constructor);
- std::vector<int> lightIds = im->getInputManager()->getReader()->getLightIds(deviceId);
+ std::vector<InputDeviceLightInfo> lights =
+ im->getInputManager()->getReader()->getLights(deviceId);
- for (size_t i = 0; i < lightIds.size(); i++) {
- const InputDeviceLightInfo* lightInfo =
- im->getInputManager()->getReader()->getLightInfo(deviceId, lightIds[i]);
- if (lightInfo == nullptr) {
- ALOGW("Failed to get input device %d light info for id %d", deviceId, lightIds[i]);
- continue;
- }
+ for (size_t i = 0; i < lights.size(); i++) {
+ const InputDeviceLightInfo& lightInfo = lights[i];
jint jTypeId =
env->GetStaticIntField(gLightClassInfo.clazz, gLightClassInfo.lightTypeInput);
jint jCapability = 0;
- if (lightInfo->type == InputDeviceLightType::MONO) {
+ if (lightInfo.type == InputDeviceLightType::MONO) {
jCapability = env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightCapabilityBrightness);
- } else if (lightInfo->type == InputDeviceLightType::RGB ||
- lightInfo->type == InputDeviceLightType::MULTI_COLOR) {
+ } else if (lightInfo.type == InputDeviceLightType::RGB ||
+ lightInfo.type == InputDeviceLightType::MULTI_COLOR) {
jCapability =
env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightCapabilityBrightness) |
env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightCapabilityRgb);
- } else if (lightInfo->type == InputDeviceLightType::PLAYER_ID) {
+ } else if (lightInfo.type == InputDeviceLightType::PLAYER_ID) {
jTypeId = env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightTypePlayerId);
} else {
- ALOGW("Unknown light type %d", lightInfo->type);
+ ALOGW("Unknown light type %d", lightInfo.type);
continue;
}
ScopedLocalRef<jobject> lightObj(env,
env->NewObject(gLightClassInfo.clazz,
gLightClassInfo.constructor,
- static_cast<jint>(lightInfo->id),
- env->NewStringUTF(lightInfo->name.c_str()),
- static_cast<jint>(lightInfo->ordinal),
+ static_cast<jint>(lightInfo.id),
+ env->NewStringUTF(lightInfo.name.c_str()),
+ static_cast<jint>(lightInfo.ordinal),
jTypeId, jCapability));
// Add light object to list
env->CallBooleanMethod(jLights, gArrayListClassInfo.add, lightObj.get());
@@ -2218,39 +2214,28 @@
static jobjectArray nativeGetSensorList(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
- std::vector<InputDeviceInfo> devices = im->getInputManager()->getReader()->getInputDevices();
- // Find the input device by deviceId
- auto it = std::find_if(devices.begin(), devices.end(),
- [deviceId](InputDeviceInfo& info) { return info.getId() == deviceId; });
+ std::vector<InputDeviceSensorInfo> sensors =
+ im->getInputManager()->getReader()->getSensors(deviceId);
- if (it == devices.end()) {
- // Return an array of size 0
- return env->NewObjectArray(0, gInputSensorInfo.clazz, nullptr);
- }
+ jobjectArray arr = env->NewObjectArray(sensors.size(), gInputSensorInfo.clazz, nullptr);
+ for (int i = 0; i < sensors.size(); i++) {
+ const InputDeviceSensorInfo& sensorInfo = sensors[i];
- std::vector<InputDeviceSensorType> types = it->getSensorTypes();
- jobjectArray arr = env->NewObjectArray(types.size(), gInputSensorInfo.clazz, nullptr);
- for (int i = 0; i < types.size(); i++) {
- const InputDeviceSensorInfo* sensorInfo = it->getSensorInfo(types[i]);
- if (sensorInfo == nullptr) {
- ALOGW("Failed to get input device %d sensor info for type %s", deviceId,
- NamedEnum::string(types[i]).c_str());
- continue;
- }
-
- jobject info =
- createInputSensorInfo(env, env->NewStringUTF(sensorInfo->name.c_str()),
- env->NewStringUTF(sensorInfo->vendor.c_str()),
- (jint)sensorInfo->version, 0 /* handle */,
- (jint)sensorInfo->type, (jfloat)sensorInfo->maxRange,
- (jfloat)sensorInfo->resolution, (jfloat)sensorInfo->power,
- (jfloat)sensorInfo->minDelay,
- (jint)sensorInfo->fifoReservedEventCount,
- (jint)sensorInfo->fifoMaxEventCount,
- env->NewStringUTF(sensorInfo->stringType.c_str()),
- env->NewStringUTF("") /* requiredPermission */,
- (jint)sensorInfo->maxDelay, (jint)sensorInfo->flags,
- (jint)sensorInfo->id);
+ jobject info = createInputSensorInfo(env, env->NewStringUTF(sensorInfo.name.c_str()),
+ env->NewStringUTF(sensorInfo.vendor.c_str()),
+ static_cast<jint>(sensorInfo.version), 0 /* handle */,
+ static_cast<jint>(sensorInfo.type),
+ static_cast<jfloat>(sensorInfo.maxRange),
+ static_cast<jfloat>(sensorInfo.resolution),
+ static_cast<jfloat>(sensorInfo.power),
+ static_cast<jfloat>(sensorInfo.minDelay),
+ static_cast<jint>(sensorInfo.fifoReservedEventCount),
+ static_cast<jint>(sensorInfo.fifoMaxEventCount),
+ env->NewStringUTF(sensorInfo.stringType.c_str()),
+ env->NewStringUTF("") /* requiredPermission */,
+ static_cast<jint>(sensorInfo.maxDelay),
+ static_cast<jint>(sensorInfo.flags),
+ static_cast<jint>(sensorInfo.id));
env->SetObjectArrayElement(arr, i, info);
env->DeleteLocalRef(info);
}
diff --git a/services/core/jni/stats/SurfaceFlingerPuller.cpp b/services/core/jni/stats/SurfaceFlingerPuller.cpp
index 0e28da7..8873673 100644
--- a/services/core/jni/stats/SurfaceFlingerPuller.cpp
+++ b/services/core/jni/stats/SurfaceFlingerPuller.cpp
@@ -158,7 +158,8 @@
atom.total_jank_frames_sf_prediction_error(),
atom.total_jank_frames_app_buffer_stuffing(),
atom.display_refresh_rate_bucket(), atom.render_rate_bucket(),
- frameRateVote.value(), appDeadlineMisses.value());
+ frameRateVote.value(), appDeadlineMisses.value(),
+ atom.game_mode());
}
return AStatsManager_PULL_SUCCESS;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index dddf3df..0128d35 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -22,6 +22,7 @@
import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
@@ -990,13 +991,24 @@
@Override
public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
Bundle prevRestrictions) {
- final boolean newlyDisallowed =
- newRestrictions.getBoolean(UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE);
- final boolean previouslyDisallowed =
- prevRestrictions.getBoolean(UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE);
- final boolean restrictionChanged = (newlyDisallowed != previouslyDisallowed);
+ resetCrossProfileIntentFiltersIfNeeded(userId, newRestrictions, prevRestrictions);
+ resetUserVpnIfNeeded(userId, newRestrictions, prevRestrictions);
+ }
- if (restrictionChanged) {
+ private void resetUserVpnIfNeeded(
+ int userId, Bundle newRestrictions, Bundle prevRestrictions) {
+ final boolean newlyEnforced =
+ !prevRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_VPN)
+ && newRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_VPN);
+ if (newlyEnforced) {
+ mDpms.clearUserConfiguredVpns(userId);
+ }
+ }
+
+ private void resetCrossProfileIntentFiltersIfNeeded(
+ int userId, Bundle newRestrictions, Bundle prevRestrictions) {
+ if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
+ UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE)) {
final int parentId = mUserManagerInternal.getProfileParentId(userId);
if (parentId == userId) {
return;
@@ -1007,13 +1019,55 @@
Slogf.i(LOG_TAG, "Resetting cross-profile intent filters on restriction "
+ "change");
mDpms.resetDefaultCrossProfileIntentFilters(parentId);
- mContext.sendBroadcastAsUser(new Intent(
- DevicePolicyManager.ACTION_DATA_SHARING_RESTRICTION_APPLIED),
+ mContext.sendBroadcastAsUser(
+ new Intent(DevicePolicyManager.ACTION_DATA_SHARING_RESTRICTION_APPLIED),
UserHandle.of(userId));
}
}
}
+ private void clearUserConfiguredVpns(int userId) {
+ final String adminConfiguredVpnPkg;
+ synchronized (getLockObject()) {
+ final ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userId);
+ if (owner == null) {
+ Slogf.wtf(LOG_TAG, "Admin not found");
+ return;
+ }
+ adminConfiguredVpnPkg = owner.mAlwaysOnVpnPackage;
+ }
+
+ // Clear always-on configuration if it wasn't set by the admin.
+ if (adminConfiguredVpnPkg == null) {
+ mInjector.getVpnManager().setAlwaysOnVpnPackageForUser(userId, null, false, null);
+ }
+
+ // Clear app authorizations to establish VPNs. When DISALLOW_CONFIG_VPN is enforced apps
+ // won't be able to get those authorizations unless it is configured by an admin.
+ final List<AppOpsManager.PackageOps> allVpnOps = mInjector.getAppOpsManager()
+ .getPackagesForOps(new int[] {AppOpsManager.OP_ACTIVATE_VPN});
+ if (allVpnOps == null) {
+ return;
+ }
+ for (AppOpsManager.PackageOps pkgOps : allVpnOps) {
+ if (UserHandle.getUserId(pkgOps.getUid()) != userId
+ || pkgOps.getPackageName().equals(adminConfiguredVpnPkg)) {
+ continue;
+ }
+ if (pkgOps.getOps().size() != 1) {
+ Slogf.wtf(LOG_TAG, "Unexpected number of ops returned");
+ continue;
+ }
+ final @Mode int mode = pkgOps.getOps().get(0).getMode();
+ if (mode == MODE_ALLOWED) {
+ Slogf.i(LOG_TAG, String.format("Revoking VPN authorization for package %s uid %d",
+ pkgOps.getPackageName(), pkgOps.getUid()));
+ mInjector.getAppOpsManager().setMode(AppOpsManager.OP_ACTIVATE_VPN, pkgOps.getUid(),
+ pkgOps.getPackageName(), MODE_DEFAULT);
+ }
+ }
+ }
+
private final class UserLifecycleListener implements UserManagerInternal.UserLifecycleListener {
@Override
@@ -6559,6 +6613,19 @@
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_ALWAYS_ON_VPN_PACKAGE);
+ if (vpnPackage == null) {
+ final String prevVpnPackage;
+ synchronized (getLockObject()) {
+ prevVpnPackage = getProfileOwnerOrDeviceOwnerLocked(caller).mAlwaysOnVpnPackage;
+ // If the admin is clearing VPN package but hasn't configure any VPN previously,
+ // ignore it so that it doesn't interfere with user-configured VPNs.
+ if (TextUtils.isEmpty(prevVpnPackage)) {
+ return true;
+ }
+ }
+ revokeVpnAuthorizationForPackage(prevVpnPackage, caller.getUserId());
+ }
+
final int userId = caller.getUserId();
mInjector.binderWithCleanCallingIdentity(() -> {
if (vpnPackage != null && !isPackageInstalledForUser(vpnPackage, userId)) {
@@ -6581,14 +6648,14 @@
userId, vpnPackage, lockdown, lockdownAllowlist)) {
throw new UnsupportedOperationException();
}
- DevicePolicyEventLogger
- .createEvent(DevicePolicyEnums.SET_ALWAYS_ON_VPN_PACKAGE)
- .setAdmin(caller.getComponentName())
- .setStrings(vpnPackage)
- .setBoolean(lockdown)
- .setInt(lockdownAllowlist != null ? lockdownAllowlist.size() : 0)
- .write();
});
+ DevicePolicyEventLogger
+ .createEvent(DevicePolicyEnums.SET_ALWAYS_ON_VPN_PACKAGE)
+ .setAdmin(caller.getComponentName())
+ .setStrings(vpnPackage)
+ .setBoolean(lockdown)
+ .setInt(lockdownAllowlist != null ? lockdownAllowlist.size() : 0)
+ .write();
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
if (!TextUtils.equals(vpnPackage, admin.mAlwaysOnVpnPackage)
@@ -6601,6 +6668,23 @@
return true;
}
+ private void revokeVpnAuthorizationForPackage(String vpnPackage, int userId) {
+ mInjector.binderWithCleanCallingIdentity(() -> {
+ try {
+ final ApplicationInfo ai = mIPackageManager.getApplicationInfo(
+ vpnPackage, /* flags= */ 0, userId);
+ if (ai == null) {
+ Slogf.w(LOG_TAG, "Non-existent VPN package: " + vpnPackage);
+ } else {
+ mInjector.getAppOpsManager().setMode(AppOpsManager.OP_ACTIVATE_VPN,
+ ai.uid, vpnPackage, MODE_DEFAULT);
+ }
+ } catch (RemoteException e) {
+ Slogf.e(LOG_TAG, "Can't talk to package managed", e);
+ }
+ });
+ }
+
@Override
public String getAlwaysOnVpnPackage(ComponentName admin) throws SecurityException {
Objects.requireNonNull(admin, "ComponentName is null");
@@ -8390,12 +8474,6 @@
return who != null && who.equals(profileOwner);
}
- private boolean isProfileOwnerUncheckedLocked(ComponentName who, int userId) {
- ensureLocked();
- final ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId);
- return who != null && who.equals(profileOwner);
- }
-
/**
* Returns {@code true} if the provided caller identity is of a profile owner.
* @param caller identity of caller.
@@ -10005,14 +10083,23 @@
return true;
}
- private AccessibilityManager getAccessibilityManagerForUser(int userId) {
+ /**
+ * Invoke a method in AccessibilityManager ensuring the client is removed.
+ */
+ private <T> T withAccessibilityManager(
+ int userId, Function<AccessibilityManager, T> function) {
// Not using AccessibilityManager.getInstance because that guesses
// at the user you require based on callingUid and caches for a given
// process.
- IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
- IAccessibilityManager service = iBinder == null
+ final IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
+ final IAccessibilityManager service = iBinder == null
? null : IAccessibilityManager.Stub.asInterface(iBinder);
- return new AccessibilityManager(mContext, service, userId);
+ final AccessibilityManager am = new AccessibilityManager(mContext, service, userId);
+ try {
+ return function.apply(am);
+ } finally {
+ am.removeClient();
+ }
}
@Override
@@ -10025,22 +10112,21 @@
if (packageList != null) {
int userId = caller.getUserId();
- List<AccessibilityServiceInfo> enabledServices = null;
+ final List<AccessibilityServiceInfo> enabledServices;
long id = mInjector.binderClearCallingIdentity();
try {
UserInfo user = getUserInfo(userId);
if (user.isManagedProfile()) {
userId = user.profileGroupId;
}
- AccessibilityManager accessibilityManager = getAccessibilityManagerForUser(userId);
- enabledServices = accessibilityManager.getEnabledAccessibilityServiceList(
- FEEDBACK_ALL_MASK);
+ enabledServices = withAccessibilityManager(userId,
+ am -> am.getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK));
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
if (enabledServices != null) {
- List<String> enabledPackages = new ArrayList<String>();
+ List<String> enabledPackages = new ArrayList<>();
for (AccessibilityServiceInfo service : enabledServices) {
enabledPackages.add(service.getResolveInfo().serviceInfo.packageName);
}
@@ -10122,10 +10208,9 @@
if (user.isManagedProfile()) {
userId = user.profileGroupId;
}
- AccessibilityManager accessibilityManager =
- getAccessibilityManagerForUser(userId);
- List<AccessibilityServiceInfo> installedServices =
- accessibilityManager.getInstalledAccessibilityServiceList();
+ final List<AccessibilityServiceInfo> installedServices =
+ withAccessibilityManager(userId,
+ AccessibilityManager::getInstalledAccessibilityServiceList);
if (installedServices != null) {
for (AccessibilityServiceInfo service : installedServices) {
@@ -13660,16 +13745,6 @@
+ " is not device owner");
}
- private ComponentName getOwnerComponent(String packageName, int userId) {
- if (isDeviceOwnerPackage(packageName, userId)) {
- return mOwners.getDeviceOwnerComponent();
- }
- if (isProfileOwnerPackage(packageName, userId)) {
- return mOwners.getProfileOwnerComponent(userId);
- }
- return null;
- }
-
/**
* Return device owner or profile owner set on a given user.
*/
@@ -15992,7 +16067,20 @@
Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(hasCrossUsersPermission(caller, userHandle));
+ final int packageUid = mInjector.binderWithCleanCallingIdentity(() -> {
+ try {
+ return mInjector.getPackageManager().getPackageUidAsUser(packageName, userHandle);
+ } catch (NameNotFoundException e) {
+ Slogf.w(LOG_TAG, e,
+ "Couldn't find package %s in user %d", packageName, userHandle);
+ return -1;
+ }
+ });
+ if (caller.getUid() != packageUid) {
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS)
+ || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL));
+ }
synchronized (getLockObject()) {
if (mInjector.settingsSecureGetIntForUser(
@@ -16016,9 +16104,9 @@
return Collections.emptyList();
}
Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
-
- final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(hasCrossUsersPermission(caller, userHandle));
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS)
+ || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL));
synchronized (getLockObject()) {
final ActiveAdmin admin = getProfileOwnerAdminLocked(userHandle);
@@ -17462,14 +17550,9 @@
@Override
public boolean isUsbDataSignalingEnabled(String packageName) {
- final CallerIdentity caller = getCallerIdentity(packageName);
- Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
- "USB data signaling can only be controlled by a device owner or "
- + "a profile owner on an organization-owned device.");
-
synchronized (getLockObject()) {
- final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
+ final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(
+ getCallerIdentity(packageName));
return admin.mUsbDataSignalingEnabled;
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
index 280f12f..685cf05 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
@@ -19,17 +19,26 @@
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
+import static android.app.admin.DevicePolicyManager.REQUIRED_APP_MANAGED_DEVICE;
+import static android.app.admin.DevicePolicyManager.REQUIRED_APP_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.REQUIRED_APP_MANAGED_USER;
+import static android.content.pm.PackageManager.GET_META_DATA;
+import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.devicepolicy.DevicePolicyManagerService.dumpResources;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.util.ArraySet;
@@ -39,9 +48,13 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.inputmethod.InputMethodManagerInternal;
+import com.android.server.pm.ApexManager;
import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -51,6 +64,18 @@
public class OverlayPackagesProvider {
protected static final String TAG = "OverlayPackagesProvider";
+ private static final Map<String, String> sActionToMetadataKeyMap = new HashMap<>();
+ {
+ sActionToMetadataKeyMap.put(ACTION_PROVISION_MANAGED_USER, REQUIRED_APP_MANAGED_USER);
+ sActionToMetadataKeyMap.put(ACTION_PROVISION_MANAGED_PROFILE, REQUIRED_APP_MANAGED_PROFILE);
+ sActionToMetadataKeyMap.put(ACTION_PROVISION_MANAGED_DEVICE, REQUIRED_APP_MANAGED_DEVICE);
+ }
+ private static final Set<String> sAllowedActions = new HashSet<>();
+ {
+ sAllowedActions.add(ACTION_PROVISION_MANAGED_USER);
+ sAllowedActions.add(ACTION_PROVISION_MANAGED_PROFILE);
+ sAllowedActions.add(ACTION_PROVISION_MANAGED_DEVICE);
+ }
private final PackageManager mPm;
private final Context mContext;
@@ -64,6 +89,8 @@
interface Injector {
@NonNull
List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId);
+
+ String getActiveApexPackageNameContainingPackage(String packageName);
}
private static final class DefaultInjector implements Injector {
@@ -72,6 +99,11 @@
public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
return InputMethodManagerInternal.get().getInputMethodListAsUser(userId);
}
+
+ @Override
+ public String getActiveApexPackageNameContainingPackage(String packageName) {
+ return ApexManager.getInstance().getActiveApexPackageNameContainingPackage(packageName);
+ }
}
@VisibleForTesting
@@ -83,7 +115,8 @@
/**
* Computes non-required apps. All the system apps with a launcher that are not in
- * the required set of packages will be considered as non-required apps.
+ * the required set of packages, and all mainline modules that are not declared as required
+ * via metadata in their manifests, will be considered as non-required apps.
*
* Note: If an app is mistakenly listed as both required and disallowed, it will be treated as
* disallowed.
@@ -99,15 +132,76 @@
@NonNull
public Set<String> getNonRequiredApps(@NonNull ComponentName admin, int userId,
@NonNull String provisioningAction) {
+ requireNonNull(admin);
+ checkArgument(sAllowedActions.contains(provisioningAction));
final Set<String> nonRequiredApps = getLaunchableApps(userId);
// Newly installed system apps are uninstalled when they are not required and are either
// disallowed or have a launcher icon.
nonRequiredApps.removeAll(getRequiredApps(provisioningAction, admin.getPackageName()));
nonRequiredApps.removeAll(getSystemInputMethods(userId));
nonRequiredApps.addAll(getDisallowedApps(provisioningAction));
+ nonRequiredApps.removeAll(
+ getRequiredAppsMainlineModules(nonRequiredApps, provisioningAction));
return nonRequiredApps;
}
+ /**
+ * Returns a subset of {@code packageNames} whose packages are mainline modules declared as
+ * required apps via their app metadata.
+ * @see DevicePolicyManager#REQUIRED_APP_MANAGED_USER
+ * @see DevicePolicyManager#REQUIRED_APP_MANAGED_DEVICE
+ * @see DevicePolicyManager#REQUIRED_APP_MANAGED_PROFILE
+ */
+ private Set<String> getRequiredAppsMainlineModules(
+ Set<String> packageNames,
+ String provisioningAction) {
+ final Set<String> result = new HashSet<>();
+ for (String packageName : packageNames) {
+ if (!isMainlineModule(packageName)) {
+ continue;
+ }
+ if (!isRequiredAppDeclaredInMetadata(packageName, provisioningAction)) {
+ continue;
+ }
+ result.add(packageName);
+ }
+ return result;
+ }
+
+ private boolean isRequiredAppDeclaredInMetadata(String packageName, String provisioningAction) {
+ PackageInfo packageInfo;
+ try {
+ packageInfo = mPm.getPackageInfo(packageName, GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ final String metadataKey = sActionToMetadataKeyMap.get(provisioningAction);
+ return packageInfo.applicationInfo.metaData.getBoolean(metadataKey);
+ }
+
+ /**
+ * Returns {@code true} if the provided package name is a mainline module.
+ * <p>There are 2 types of mainline modules: a regular mainline module and apk-in-apex module.
+ */
+ private boolean isMainlineModule(String packageName) {
+ return isRegularMainlineModule(packageName) || isApkInApexMainlineModule(packageName);
+ }
+
+ private boolean isRegularMainlineModule(String packageName) {
+ try {
+ mPm.getModuleInfo(packageName, /* flags= */ 0);
+ return true;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ private boolean isApkInApexMainlineModule(String packageName) {
+ final String apexPackageName =
+ mInjector.getActiveApexPackageNameContainingPackage(packageName);
+ return apexPackageName != null;
+ }
+
private Set<String> getLaunchableApps(int userId) {
final Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
index 48d2d73..532823a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
@@ -18,8 +18,6 @@
import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
-import static com.android.server.devicepolicy.DevicePolicyManagerService.LOG_TAG;
-
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -142,9 +140,21 @@
}
private List<String> getAccessibilityServices() {
- final List<AccessibilityServiceInfo> accessibilityServiceInfos =
- getAccessibilityManagerForUser(mContext.getUserId())
- .getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK);
+ final List<AccessibilityServiceInfo> accessibilityServiceInfos;
+ // Not using AccessibilityManager.getInstance because that guesses
+ // at the user you require based on callingUid and caches for a given
+ // process.
+ final IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
+ final IAccessibilityManager service = iBinder == null
+ ? null : IAccessibilityManager.Stub.asInterface(iBinder);
+ final AccessibilityManager am =
+ new AccessibilityManager(mContext, service, mContext.getUserId());
+ try {
+ accessibilityServiceInfos = am.getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK);
+ } finally {
+ am.removeClient();
+ }
+
final List<String> result = new ArrayList<>();
for (final AccessibilityServiceInfo serviceInfo : accessibilityServiceInfos) {
final ComponentName componentName =
@@ -192,12 +202,6 @@
return resolveInfos != null && !resolveInfos.isEmpty();
}
- private AccessibilityManager getAccessibilityManagerForUser(int userId) {
- final IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
- final IAccessibilityManager service =
- iBinder == null ? null : IAccessibilityManager.Stub.asInterface(iBinder);
- return new AccessibilityManager(mContext, service, userId);
- }
void dump(IndentingPrintWriter pw) {
pw.println("PersonalAppsSuspensionHelper");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/UpdateInstaller.java b/services/devicepolicy/java/com/android/server/devicepolicy/UpdateInstaller.java
index 7148ed4..ce9fa2d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/UpdateInstaller.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/UpdateInstaller.java
@@ -68,7 +68,7 @@
notifyCallbackOnError(
InstallSystemUpdateCallback.UPDATE_ERROR_BATTERY_LOW,
"The battery level must be above "
- + mConstants.BATTERY_THRESHOLD_NOT_CHARGING + " while not charging or"
+ + mConstants.BATTERY_THRESHOLD_NOT_CHARGING + " while not charging or "
+ "above " + mConstants.BATTERY_THRESHOLD_CHARGING + " while charging");
return;
}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 47d59b2..757c9de 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -89,6 +89,11 @@
// Max interval after system invoked the DL when readlog collection can be enabled.
static constexpr auto readLogsMaxInterval = 2h;
+
+ // How long should we wait till dataLoader reports destroyed.
+ static constexpr auto destroyTimeout = 60s;
+
+ static constexpr auto anyStatus = INT_MIN;
};
static const Constants& constants() {
@@ -2554,7 +2559,7 @@
mControl = {};
mHealthControl = {};
mHealthListener = {};
- mStatusCondition.wait_until(lock, now + 60s, [this] {
+ mStatusCondition.wait_until(lock, now + Constants::destroyTimeout, [this] {
return mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
});
mStatusListener = {};
@@ -2754,8 +2759,16 @@
switch (targetStatus) {
case IDataLoaderStatusListener::DATA_LOADER_DESTROYED: {
switch (currentStatus) {
+ case IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE:
+ case IDataLoaderStatusListener::DATA_LOADER_UNRECOVERABLE:
+ destroy();
+ // DataLoader is broken, just assume it's destroyed.
+ compareAndSetCurrentStatus(currentStatus,
+ IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
+ return true;
case IDataLoaderStatusListener::DATA_LOADER_BINDING:
- setCurrentStatus(IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
+ compareAndSetCurrentStatus(currentStatus,
+ IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
return true;
default:
return destroy();
@@ -2776,7 +2789,11 @@
case IDataLoaderStatusListener::DATA_LOADER_UNRECOVERABLE:
// Before binding need to make sure we are unbound.
// Otherwise we'll get stuck binding.
- return destroy();
+ destroy();
+ // DataLoader is broken, just assume it's destroyed.
+ compareAndSetCurrentStatus(currentStatus,
+ IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
+ return true;
case IDataLoaderStatusListener::DATA_LOADER_DESTROYED:
case IDataLoaderStatusListener::DATA_LOADER_BINDING:
return bind();
@@ -2815,6 +2832,11 @@
}
void IncrementalService::DataLoaderStub::setCurrentStatus(int newStatus) {
+ compareAndSetCurrentStatus(Constants::anyStatus, newStatus);
+}
+
+void IncrementalService::DataLoaderStub::compareAndSetCurrentStatus(int expectedStatus,
+ int newStatus) {
int oldStatus, oldTargetStatus, newTargetStatus;
DataLoaderStatusListener listener;
{
@@ -2822,6 +2844,9 @@
if (mCurrentStatus == newStatus) {
return;
}
+ if (expectedStatus != Constants::anyStatus && expectedStatus != mCurrentStatus) {
+ return;
+ }
oldStatus = mCurrentStatus;
oldTargetStatus = mTargetStatus;
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index 5de7325..b81e1b1 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -255,6 +255,7 @@
binder::Status onStatusChanged(MountId mount, int newStatus) final;
void setCurrentStatus(int newStatus);
+ void compareAndSetCurrentStatus(int expectedStatus, int newStatus);
sp<content::pm::IDataLoader> getDataLoader();
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index 094c5fb..59d96d2 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -808,7 +808,9 @@
METRICS_MILLIS_SINCE_OLDEST_PENDING_READ()
.c_str()),
&millisSinceOldestPendingRead));
- ASSERT_EQ(expectedMillisSinceOldestPendingRead, millisSinceOldestPendingRead);
+ // Allow 10ms.
+ ASSERT_LE(expectedMillisSinceOldestPendingRead, millisSinceOldestPendingRead);
+ ASSERT_GE(expectedMillisSinceOldestPendingRead + 10, millisSinceOldestPendingRead);
int storageHealthStatusCode = -1;
ASSERT_TRUE(
result.getInt(String16(BnIncrementalService::METRICS_STORAGE_HEALTH_STATUS_CODE()
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index d55d060..ef1201e 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -254,6 +254,18 @@
return null;
}
+ ConversationInfo getConversationInfo(String packageName, int userId, String shortcutId) {
+ UserData userData = getUnlockedUserData(userId);
+ if (userData != null) {
+ PackageData packageData = userData.getPackageData(packageName);
+ // App may have been uninstalled.
+ if (packageData != null) {
+ return packageData.getConversationInfo(shortcutId);
+ }
+ }
+ return null;
+ }
+
@Nullable
private ConversationChannel getConversationChannel(String packageName, int userId,
String shortcutId, ConversationInfo conversationInfo) {
@@ -277,7 +289,7 @@
int uid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
NotificationChannel parentChannel =
mNotificationManagerInternal.getNotificationChannel(packageName, uid,
- conversationInfo.getParentNotificationChannelId());
+ conversationInfo.getNotificationChannelId());
NotificationChannelGroup parentChannelGroup = null;
if (parentChannel != null) {
parentChannelGroup =
@@ -302,7 +314,7 @@
String shortcutId = conversationInfo.getShortcutId();
ConversationChannel channel = getConversationChannel(packageData.getPackageName(),
packageData.getUserId(), shortcutId, conversationInfo);
- if (channel == null || channel.getParentNotificationChannel() == null) {
+ if (channel == null || channel.getNotificationChannel() == null) {
return;
}
conversationChannels.add(channel);
@@ -791,8 +803,8 @@
private boolean isCachedRecentConversation(ConversationInfo conversationInfo) {
return conversationInfo.isShortcutCachedForNotification()
- && conversationInfo.getNotificationChannelId() == null
- && conversationInfo.getParentNotificationChannelId() != null
+ && Objects.equals(conversationInfo.getNotificationChannelId(),
+ conversationInfo.getParentNotificationChannelId())
&& conversationInfo.getLastEventTimestamp() > 0L;
}
@@ -910,7 +922,7 @@
}
@VisibleForTesting
- NotificationListenerService getNotificationListenerServiceForTesting(@UserIdInt int userId) {
+ NotificationListener getNotificationListenerServiceForTesting(@UserIdInt int userId) {
return mNotificationListeners.get(userId);
}
@@ -1132,7 +1144,7 @@
}
@Override
- public void onNotificationPosted(StatusBarNotification sbn) {
+ public void onNotificationPosted(StatusBarNotification sbn, RankingMap map) {
if (sbn.getUser().getIdentifier() != mUserId) {
return;
}
@@ -1145,16 +1157,22 @@
});
if (packageData != null) {
+ Ranking rank = new Ranking();
+ map.getRanking(sbn.getKey(), rank);
ConversationInfo conversationInfo = packageData.getConversationInfo(shortcutId);
if (conversationInfo == null) {
return;
}
if (DEBUG) Log.d(TAG, "Last event from notification: " + sbn.getPostTime());
- ConversationInfo updated = new ConversationInfo.Builder(conversationInfo)
+ ConversationInfo.Builder updated = new ConversationInfo.Builder(conversationInfo)
.setLastEventTimestamp(sbn.getPostTime())
- .setParentNotificationChannelId(sbn.getNotification().getChannelId())
- .build();
- packageData.getConversationStore().addOrUpdate(updated);
+ .setNotificationChannelId(rank.getChannel().getId());
+ if (!TextUtils.isEmpty(rank.getChannel().getParentChannelId())) {
+ updated.setParentNotificationChannelId(rank.getChannel().getParentChannelId());
+ } else {
+ updated.setParentNotificationChannelId(sbn.getNotification().getChannelId());
+ }
+ packageData.getConversationStore().addOrUpdate(updated.build());
EventHistoryImpl eventHistory = packageData.getEventStore().getOrCreateEventHistory(
EventStore.CATEGORY_SHORTCUT_BASED, shortcutId);
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index 6c5c1d4..b4f8b6e 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -16,6 +16,7 @@
package com.android.server.pm.test.override
+import android.app.PropertyInvalidatedCache
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
@@ -26,8 +27,10 @@
import com.android.server.pm.AppsFilter
import com.android.server.pm.ComponentResolver
import com.android.server.pm.PackageManagerService
+import com.android.server.pm.PackageManagerTracedLock
import com.android.server.pm.PackageSetting
import com.android.server.pm.Settings
+import com.android.server.pm.UserManagerInternal
import com.android.server.pm.UserManagerService
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.parsing.pkg.PackageImpl
@@ -42,6 +45,7 @@
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
+import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -63,6 +67,7 @@
private const val VALID_PKG = "com.android.server.pm.test.override"
private const val SHARED_PKG = "com.android.server.pm.test.override.shared"
private const val INVALID_PKG = "com.android.server.pm.test.override.invalid"
+ private const val NON_EXISTENT_PKG = "com.android.server.pm.test.override.nonexistent"
private const val SEND_PENDING_BROADCAST = 1 // PackageManagerService.SEND_PENDING_BROADCAST
@@ -94,7 +99,8 @@
// Start with an array of the simplest known inputs and expected outputs
Params(VALID_PKG, AppType.SYSTEM_APP, Result.Changed),
Params(SHARED_PKG, AppType.SYSTEM_APP, Result.Changed),
- Params(INVALID_PKG, AppType.SYSTEM_APP, SecurityException::class.java)
+ Params(INVALID_PKG, AppType.SYSTEM_APP, SecurityException::class.java),
+ Params(NON_EXISTENT_PKG, AppType.SYSTEM_APP, SecurityException::class.java)
)
.flatMap { param ->
mutableListOf(param).apply {
@@ -120,6 +126,13 @@
}
}
+ @BeforeClass
+ @JvmStatic
+ fun disablePropertyInvalidatedCache() {
+ // Disable binder caches in this process.
+ PropertyInvalidatedCache.disableForTestMode()
+ }
+
data class Params(
val pkgName: String,
private val appType: AppType,
@@ -210,8 +223,10 @@
fun verifyExpectedResult() {
if (params.componentName != null) {
val activityInfo = service.getActivityInfo(params.componentName, 0, userId)
- assertThat(activityInfo.nonLocalizedLabel).isEqualTo(params.expectedLabel)
- assertThat(activityInfo.icon).isEqualTo(params.expectedIcon)
+ if (activityInfo != null) {
+ assertThat(activityInfo.nonLocalizedLabel).isEqualTo(params.expectedLabel)
+ assertThat(activityInfo.icon).isEqualTo(params.expectedIcon)
+ }
}
}
@@ -294,34 +309,41 @@
SHARED_PKG to makePkg(SHARED_PKG) { uid = Binder.getCallingUid() },
INVALID_PKG to makePkg(INVALID_PKG) { uid = Binder.getCallingUid() + 1 }
)
- val mockedPkgSettings = mapOf(
+ val mockedPkgSettings = mutableMapOf(
VALID_PKG to makePkgSetting(VALID_PKG),
SHARED_PKG to makePkgSetting(SHARED_PKG),
INVALID_PKG to makePkgSetting(INVALID_PKG)
)
- // Add pkgSetting under test so its attributes override the defaults added above
- .plus(params.pkgName to mockPkgSetting)
- val mockActivity: ParsedActivity = mock {
- whenever(this.packageName) { params.pkgName }
- whenever(this.nonLocalizedLabel) { DEFAULT_LABEL }
- whenever(this.icon) { DEFAULT_ICON }
- whenever(this.componentName) { params.componentName }
- whenever(this.name) { params.componentName?.className }
- whenever(this.isEnabled) { true }
- whenever(this.isDirectBootAware) { params.isSystem }
+ var mockActivity: ParsedActivity? = null
+ if (mockedPkgSettings.containsKey(params.pkgName)) {
+ // Add pkgSetting under test so its attributes override the defaults added above
+ mockedPkgSettings.put(params.pkgName, mockPkgSetting)
+
+ mockActivity = mock<ParsedActivity> {
+ whenever(this.packageName) { params.pkgName }
+ whenever(this.nonLocalizedLabel) { DEFAULT_LABEL }
+ whenever(this.icon) { DEFAULT_ICON }
+ whenever(this.componentName) { params.componentName }
+ whenever(this.name) { params.componentName?.className }
+ whenever(this.isEnabled) { true }
+ whenever(this.isDirectBootAware) { params.isSystem }
+ }
}
val mockSettings = Settings(mockedPkgSettings)
val mockComponentResolver: ComponentResolver = mockThrowOnUnmocked {
params.componentName?.let {
- whenever(this.componentExists(same(it))) { true }
+ whenever(this.componentExists(same(it))) { mockActivity != null }
whenever(this.getActivity(same(it))) { mockActivity }
}
}
val mockUserManagerService: UserManagerService = mockThrowOnUnmocked {
val matcher: (Int) -> Boolean = { it == userId || it == userIdDifferent }
whenever(this.exists(intThat(matcher))) { true }
+ }
+ val mockUserManagerInternal: UserManagerInternal = mockThrowOnUnmocked {
+ val matcher: (Int) -> Boolean = { it == userId || it == userIdDifferent }
whenever(this.isUserUnlockingOrUnlocked(intThat(matcher))) { true }
}
val mockActivityTaskManager: ActivityTaskManagerInternal = mockThrowOnUnmocked {
@@ -340,18 +362,19 @@
}
}
val mockInjector: PackageManagerService.Injector = mock {
- whenever(this.lock) { Object() }
+ whenever(this.lock) { PackageManagerTracedLock() }
whenever(this.componentResolver) { mockComponentResolver }
whenever(this.userManagerService) { mockUserManagerService }
+ whenever(this.getUserManagerInternal()) { mockUserManagerInternal }
whenever(this.settings) { mockSettings }
whenever(this.getLocalService(ActivityTaskManagerInternal::class.java)) {
mockActivityTaskManager
}
whenever(this.appsFilter) { mockAppsFilter }
whenever(this.context) { mockContext }
+ whenever(this.getHandler()) { testHandler }
}
val testParams = PackageManagerService.TestParams().apply {
- this.handler = testHandler
this.pendingPackageBroadcasts = mockPendingBroadcasts
this.resolveComponentName = ComponentName("android", ".Test")
this.packages = ArrayMap<String, AndroidPackage>().apply { putAll(mockedPkgs) }
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 24e11af..ff7cd75 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -45,6 +45,7 @@
"service-permission.impl",
"service-blobstore",
"service-appsearch",
+ "androidx.test.core",
"androidx.test.runner",
"androidx.test.ext.truth",
"mockito-target-extended-minus-junit4",
diff --git a/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java b/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java
index f01120e..5a6275d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java
@@ -24,19 +24,25 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.when;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.os.Looper;
import android.os.RecoverySystem;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.os.storage.StorageManager;
import android.platform.test.annotations.Presubmit;
import android.util.Log;
-import android.view.WindowManager;
import androidx.test.InstrumentationRegistry;
@@ -68,7 +74,13 @@
@Override
public Object getSystemService(String name) {
Log.v(TAG, "getSystemService(): " + name);
- return name.equals(Context.STORAGE_SERVICE) ? mSm : super.getSystemService(name);
+ if (name.equals(Context.STORAGE_SERVICE)) {
+ return mSm;
+ }
+ if (name.equals(Context.USER_SERVICE)) {
+ return mUserManager;
+ }
+ return super.getSystemService(name);
}
};
@@ -85,15 +97,17 @@
private StorageManager mSm;
@Mock
- private WindowManager mWm;
+ private UserManager mUserManager;
@Before
public void startSession() {
mSession = mockitoSession()
.initMocks(this)
.mockStatic(RecoverySystem.class)
+ .mockStatic(UserManager.class)
.strictness(Strictness.LENIENT)
.startMocking();
+ setPendingResultForUser(UserHandle.myUserId());
}
@After
@@ -148,6 +162,32 @@
verifyWipeExternalData();
}
+ @Test
+ public void testNonSystemUser() throws Exception {
+ expectWipeNonSystemUser();
+
+ Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
+ setPendingResultForUser(/* userId= */ 10);
+ mReceiver.onReceive(mContext, intent);
+
+ verifyNoRebootWipeUserData();
+ verifyNoWipeExternalData();
+ verifyWipeNonSystemUser();
+ }
+
+ @Test
+ public void testHeadlessSystemUser() throws Exception {
+ expectNoWipeExternalData();
+ expectRebootWipeUserData();
+ expectHeadlessSystemUserMode();
+
+ Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
+ setPendingResultForUser(/* userId= */ 10);
+ mReceiver.onReceive(mContext, intent);
+
+ verifyRebootWipeUserData();
+ verifyNoWipeExternalData();
+ }
private void expectNoWipeExternalData() {
// This is a trick to simplify how the order of methods are called: as wipeAdoptableDisks()
@@ -185,6 +225,18 @@
}).when(mSm).wipeAdoptableDisks();
}
+ private void expectWipeNonSystemUser() {
+ when(mUserManager.removeUserOrSetEphemeral(anyInt(), anyBoolean()))
+ .thenReturn(UserManager.REMOVE_RESULT_REMOVED);
+ }
+
+ private void expectHeadlessSystemUserMode() {
+ doAnswer((inv) -> {
+ Log.i(TAG, inv.toString());
+ return true;
+ }).when(() -> UserManager.isHeadlessSystemUserMode());
+ }
+
private void verifyRebootWipeUserData() throws Exception {
verifyRebootWipeUserData(/* shutdown= */ false, /* reason= */ null, /* force= */ false,
/* wipeEuicc= */ false);
@@ -200,6 +252,11 @@
eq(force), eq(wipeEuicc)));
}
+ private void verifyNoRebootWipeUserData() {
+ verify(()-> RecoverySystem.rebootWipeUserData(
+ any(), anyBoolean(), anyString(), anyBoolean(), anyBoolean()), never());
+ }
+
private void verifyWipeExternalData() {
verify(mSm).wipeAdoptableDisks();
}
@@ -207,4 +264,21 @@
private void verifyNoWipeExternalData() {
verify(mSm, never()).wipeAdoptableDisks();
}
+
+ private void verifyWipeNonSystemUser() {
+ verify(mUserManager).removeUserOrSetEphemeral(anyInt(), anyBoolean());
+ }
+
+ private void setPendingResultForUser(int userId) {
+ mReceiver.setPendingResult(new BroadcastReceiver.PendingResult(
+ Activity.RESULT_OK,
+ "resultData",
+ /* resultExtras= */ null,
+ BroadcastReceiver.PendingResult.TYPE_UNREGISTERED,
+ /* ordered= */ true,
+ /* sticky= */ false,
+ /* token= */ null,
+ userId,
+ /* flags= */ 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 d5e1cd6..21de791 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -58,7 +58,8 @@
import static com.android.server.alarm.AlarmManagerService.ACTIVE_INDEX;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
-import static com.android.server.alarm.AlarmManagerService.AlarmHandler.EXACT_ALARM_DENY_LIST_CHANGED;
+import static com.android.server.alarm.AlarmManagerService.AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_ADDED;
+import static com.android.server.alarm.AlarmManagerService.AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REMOVE_EXACT_ALARMS;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REMOVE_FOR_CANCELED;
@@ -103,10 +104,8 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -155,6 +154,8 @@
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.usage.AppStandbyInternal;
@@ -175,6 +176,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
@@ -370,8 +372,9 @@
.mockStatic(LocalServices.class)
.spyStatic(Looper.class)
.mockStatic(MetricsHelper.class)
- .mockStatic(Settings.Global.class)
+ .mockStatic(PermissionManagerService.class)
.mockStatic(ServiceManager.class)
+ .mockStatic(Settings.Global.class)
.mockStatic(SystemProperties.class)
.spyStatic(UserHandle.class)
.strictness(Strictness.WARN)
@@ -394,7 +397,7 @@
doCallRealMethod().when((MockedVoidMethod) () ->
LocalServices.addService(eq(AlarmManagerInternal.class), any()));
doCallRealMethod().when(() -> LocalServices.getService(AlarmManagerInternal.class));
- doReturn(false).when(() -> UserHandle.isCore(TEST_CALLING_UID));
+ doReturn(false).when(() -> UserHandle.isCore(anyInt()));
when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
eq(TEST_CALLING_USER), anyLong())).thenReturn(STANDBY_BUCKET_ACTIVE);
doReturn(Looper.getMainLooper()).when(Looper::myLooper);
@@ -983,8 +986,7 @@
verify(mService.mHandler, atLeastOnce()).sendMessageAtTime(messageCaptor.capture(),
anyLong());
final Message lastMessage = messageCaptor.getValue();
- assertEquals("Unexpected message send to handler", lastMessage.what,
- what);
+ assertEquals("Unexpected message send to handler", what, lastMessage.what);
mService.mHandler.handleMessage(lastMessage);
}
@@ -1876,6 +1878,8 @@
@Test
public void hasScheduleExactAlarmBinderCallNotDenyListed() throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
mockExactAlarmPermissionGrant(true, false, MODE_DEFAULT);
assertTrue(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
@@ -1891,6 +1895,8 @@
@Test
public void hasScheduleExactAlarmBinderCallDenyListed() throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
mockExactAlarmPermissionGrant(true, true, MODE_ERRORED);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
@@ -1905,7 +1911,25 @@
}
@Test
+ public void hasScheduleExactAlarmBinderCallChangeDisabled() throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
+
+ mockExactAlarmPermissionGrant(true, false, MODE_DEFAULT);
+ assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
+
+ mockExactAlarmPermissionGrant(true, true, MODE_ALLOWED);
+ assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
+ }
+
+ private void mockChangeEnabled(long changeId, boolean enabled) {
+ doReturn(enabled).when(() -> CompatChanges.isChangeEnabled(eq(changeId), anyString(),
+ any(UserHandle.class)));
+ }
+
+ @Test
public void hasScheduleExactAlarmBinderCallNotDeclared() throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
mockExactAlarmPermissionGrant(false, false, MODE_DEFAULT);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
@@ -1918,9 +1942,7 @@
@Test
public void noPermissionCheckWhenChangeDisabled() throws RemoteException {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
// alarm clock
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 0,
@@ -1946,9 +1968,7 @@
@Test
public void exactBinderCallWhenChangeDisabled() throws Exception {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
final PendingIntent alarmPi = getNewMockPendingIntent();
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
@@ -1963,9 +1983,7 @@
@Test
public void exactAllowWhileIdleBinderCallWhenChangeDisabled() throws Exception {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
final PendingIntent alarmPi = getNewMockPendingIntent();
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
@@ -1985,9 +2003,7 @@
@Test
public void inexactAllowWhileIdleBinderCallWhenChangeDisabled() throws Exception {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
final PendingIntent alarmPi = getNewMockPendingIntent();
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_HEURISTIC, 0,
@@ -2006,9 +2022,7 @@
@Test
public void alarmClockBinderCallWhenChangeDisabled() throws Exception {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
final PendingIntent alarmPi = getNewMockPendingIntent();
final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class);
@@ -2023,9 +2037,7 @@
@Test
public void alarmClockBinderCall() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
@@ -2060,7 +2072,6 @@
} else {
setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, "");
}
-
when(mAppOpsManager.checkOpNoThrow(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID,
TEST_CALLING_PACKAGE)).thenReturn(mode);
}
@@ -2068,9 +2079,7 @@
@Test
public void alarmClockBinderCallWithoutPermission() throws RemoteException {
setDeviceConfigBoolean(KEY_CRASH_NON_CLOCK_APPS, true);
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
@@ -2089,9 +2098,7 @@
@Test
public void exactBinderCallWithPermission() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
final PendingIntent alarmPi = getNewMockPendingIntent();
@@ -2115,9 +2122,7 @@
@Test
public void exactBinderCallWithAllowlist() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
// If permission is denied, only then allowlist will be checked.
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
@@ -2137,9 +2142,7 @@
@Test
public void exactAllowWhileIdleBinderCallWithPermission() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
final PendingIntent alarmPi = getNewMockPendingIntent();
@@ -2162,9 +2165,7 @@
@Test
public void exactAllowWhileIdleBinderCallWithAllowlist() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
// If permission is denied, only then allowlist will be checked.
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
@@ -2191,9 +2192,7 @@
@Test
public void exactBinderCallsWithoutPermissionWithoutAllowlist() throws RemoteException {
setDeviceConfigBoolean(KEY_CRASH_NON_CLOCK_APPS, true);
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false);
@@ -2220,9 +2219,7 @@
public void inexactAllowWhileIdleBinderCall() throws RemoteException {
// Both permission and power exemption status don't matter for these alarms.
// We only want to test that the flags and idleOptions are correct.
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
final PendingIntent alarmPi = getNewMockPendingIntent();
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 4321, WINDOW_HEURISTIC, 0,
@@ -2244,9 +2241,7 @@
@Test
public void binderCallWithUserAllowlist() throws RemoteException {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
@@ -2266,10 +2261,7 @@
@Test
public void minWindowChangeEnabled() {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(
- eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, true);
final int minWindow = 73;
setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
@@ -2315,10 +2307,7 @@
@Test
public void minWindowChangeDisabled() {
- doReturn(false).when(
- () -> CompatChanges.isChangeEnabled(
- eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, false);
final long minWindow = 73;
setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
@@ -2335,10 +2324,7 @@
@Test
public void minWindowPriorityAlarm() {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(
- eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, true);
final long minWindow = 73;
setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
@@ -2356,76 +2342,135 @@
}
@Test
- public void denyListPackagesAdded() {
+ public void denyListChanged() {
mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[]{"p1", "p2", "p3"});
+ when(mActivityManagerInternal.getStartedUserIds()).thenReturn(EmptyArray.INT);
+
setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, "p2,p4,p5");
- assertAndHandleMessageSync(EXACT_ALARM_DENY_LIST_CHANGED);
+
+ final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mService.mHandler, times(2)).sendMessageAtTime(messageCaptor.capture(),
+ anyLong());
+
+ final List<Message> messages = messageCaptor.getAllValues();
+ for (final Message msg : messages) {
+ assertTrue("Unwanted message sent to handler: " + msg.what,
+ msg.what == EXACT_ALARM_DENY_LIST_PACKAGES_ADDED
+ || msg.what == EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED);
+ mService.mHandler.handleMessage(msg);
+ }
ArraySet<String> added = new ArraySet<>(new String[]{"p4", "p5"});
- verify(mService).handlePackagesAddedToExactAlarmsDenyListLocked(eq(added));
+ verify(mService).handleChangesToExactAlarmDenyList(eq(added), eq(true));
+
+ ArraySet<String> removed = new ArraySet<>(new String[]{"p1", "p3"});
+ verify(mService).handleChangesToExactAlarmDenyList(eq(removed), eq(false));
}
@Test
- public void denyListPackagesRemoved() {
- clearInvocations(mService.mHandler);
- mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[]{"p1", "p2", "p3"});
- setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, "p2");
- verifyNoMoreInteractions(mService.mHandler);
+ public void permissionGrantedDueToDenyList() {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
+ final String[] packages = {"example.package.1", "example.package.2"};
+
+ final int appId1 = 232;
+ final int appId2 = 431;
+
+ final int userId1 = 42;
+ final int userId2 = 53;
+
+ registerAppIds(packages, new Integer[]{appId1, appId2});
+
+ when(mActivityManagerInternal.getStartedUserIds()).thenReturn(new int[]{userId1, userId2});
+
+ when(mPermissionManagerInternal.getAppOpPermissionPackages(
+ SCHEDULE_EXACT_ALARM)).thenReturn(packages);
+ mService.refreshExactAlarmCandidates();
+
+ final long allowListDuration = 53442;
+ when(mActivityManagerInternal.getBootTimeTempAllowListDuration()).thenReturn(
+ allowListDuration);
+
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId1), MODE_ALLOWED);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId1), MODE_DEFAULT);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId2), MODE_IGNORED);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId2), MODE_ERRORED);
+
+ mService.handleChangesToExactAlarmDenyList(new ArraySet<>(packages), false);
+
+ // No permission revoked.
+ verify(mService, never()).removeExactAlarmsOnPermissionRevokedLocked(anyInt(), anyString());
+
+ // Permission got granted only for (appId1, userId2).
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ final ArgumentCaptor<UserHandle> userCaptor = ArgumentCaptor.forClass(UserHandle.class);
+
+ verify(mMockContext).sendBroadcastAsUser(intentCaptor.capture(), userCaptor.capture(),
+ isNull(), bundleCaptor.capture());
+
+ assertEquals(userId2, userCaptor.getValue().getIdentifier());
+
+ // Validate the intent.
+ assertEquals(AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED,
+ intentCaptor.getValue().getAction());
+ assertEquals(packages[0], intentCaptor.getValue().getPackage());
+
+ // Validate the options.
+ final BroadcastOptions bOptions = new BroadcastOptions(bundleCaptor.getValue());
+ assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ bOptions.getTemporaryAppAllowlistType());
+ assertEquals(allowListDuration, bOptions.getTemporaryAppAllowlistDuration());
+ assertEquals(PowerExemptionManager.REASON_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED,
+ bOptions.getTemporaryAppAllowlistReasonCode());
}
@Test
- public void removeExactAlarmsOnPackageAddedToDenyList() {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ public void permissionRevokedDueToDenyList() {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- // basic exact alarm
- setTestAlarm(ELAPSED_REALTIME, 1, 0, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID,
- null);
- // exact and allow-while-idle alarm
- setTestAlarm(ELAPSED_REALTIME, 2, 0, getNewMockPendingIntent(), 0, FLAG_ALLOW_WHILE_IDLE,
- TEST_CALLING_UID, null);
- // alarm clock
- setWakeFromIdle(RTC_WAKEUP, 3, getNewMockPendingIntent());
+ final String[] packages = {"example.package.1", "example.package.2"};
- final PendingIntent inexact = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME, 4, 10, inexact, 0, 0, TEST_CALLING_UID, null);
+ final int appId1 = 232;
+ final int appId2 = 431;
- final PendingIntent inexactAwi = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME, 5, 10, inexactAwi, 0, FLAG_ALLOW_WHILE_IDLE,
- TEST_CALLING_UID, null);
+ final int userId1 = 42;
+ final int userId2 = 53;
- final String differentPackage = "different.package";
- final PendingIntent exactButDifferentPackage = getNewMockPendingIntent(
- TEST_CALLING_UID, differentPackage);
- setTestAlarm(ELAPSED_REALTIME, 6, 0, exactButDifferentPackage, 0, 0,
- TEST_CALLING_UID, differentPackage, null);
- assertEquals(6, mService.mAlarmStore.size());
+ registerAppIds(packages, new Integer[]{appId1, appId2});
- when(mAppOpsManager.checkOpNoThrow(eq(OP_SCHEDULE_EXACT_ALARM), anyInt(),
- anyString())).thenReturn(MODE_DEFAULT);
- setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, TEST_CALLING_PACKAGE);
- assertAndHandleMessageSync(EXACT_ALARM_DENY_LIST_CHANGED);
- verify(mService).handlePackagesAddedToExactAlarmsDenyListLocked(
- argThat(set -> (set.size() == 1 && set.contains(TEST_CALLING_PACKAGE))));
+ when(mActivityManagerInternal.getStartedUserIds()).thenReturn(new int[]{userId1, userId2});
- final ArrayList<Alarm> remaining = mService.mAlarmStore.asList();
- assertEquals(3, remaining.size());
- assertTrue("Basic inexact alarm removed",
- remaining.removeIf(a -> a.matches(inexact, null)));
- assertTrue("Inexact allow-while-idle alarm removed",
- remaining.removeIf(a -> a.matches(inexactAwi, null)));
- assertTrue("Alarm from different package removed",
- remaining.removeIf(a -> a.matches(exactButDifferentPackage, null)));
+ when(mPermissionManagerInternal.getAppOpPermissionPackages(
+ SCHEDULE_EXACT_ALARM)).thenReturn(packages);
+ mService.refreshExactAlarmCandidates();
- // Mock should return false by default.
- verify(mDeviceIdleInternal, atLeastOnce()).isAppOnWhitelist(
- UserHandle.getAppId(TEST_CALLING_UID));
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId1), MODE_ALLOWED);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId1), MODE_DEFAULT);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId2), MODE_IGNORED);
+ mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId2), MODE_ERRORED);
+
+ mService.handleChangesToExactAlarmDenyList(new ArraySet<>(packages), true);
+
+ // Permission got revoked only for (appId1, userId2)
+ verify(mService, never()).removeExactAlarmsOnPermissionRevokedLocked(
+ eq(UserHandle.getUid(userId1, appId1)), eq(packages[0]));
+ verify(mService, never()).removeExactAlarmsOnPermissionRevokedLocked(
+ eq(UserHandle.getUid(userId1, appId2)), eq(packages[1]));
+ verify(mService, never()).removeExactAlarmsOnPermissionRevokedLocked(
+ eq(UserHandle.getUid(userId2, appId2)), eq(packages[1]));
+
+ verify(mService).removeExactAlarmsOnPermissionRevokedLocked(
+ eq(UserHandle.getUid(userId2, appId1)), eq(packages[0]));
}
@Test
- public void opScheduleExactAlarmRevoked() throws Exception {
+ public void opChangedPermissionRevoked() throws Exception {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
+ mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ALLOWED);
mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+
mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
assertAndHandleMessageSync(REMOVE_EXACT_ALARMS);
verify(mService).removeExactAlarmsOnPermissionRevokedLocked(TEST_CALLING_UID,
@@ -2433,10 +2478,39 @@
}
@Test
- public void opScheduleExactAlarmGranted() throws Exception {
+ public void opChangedChangeDisabled() throws Exception {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
+
+ mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ALLOWED);
+ mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+
+ mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
+
+ verify(mService.mHandler, never()).sendMessageAtTime(
+ argThat(m -> m.what == REMOVE_EXACT_ALARMS), anyLong());
+ }
+
+ @Test
+ public void opChangedNoPermissionChangeDueToDenyList() throws Exception {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
+
+ mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ERRORED);
+ mockExactAlarmPermissionGrant(true, true, MODE_DEFAULT);
+
+ mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
+
+ verify(mService.mHandler, never()).sendMessageAtTime(
+ argThat(m -> m.what == REMOVE_EXACT_ALARMS), anyLong());
+ }
+
+ @Test
+ public void opChangedPermissionGranted() throws Exception {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
final long durationMs = 20000L;
when(mActivityManagerInternal.getBootTimeTempAllowListDuration()).thenReturn(durationMs);
+ mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ERRORED);
mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
@@ -2462,9 +2536,7 @@
@Test
public void removeExactAlarmsOnPermissionRevoked() {
- doReturn(true).when(
- () -> CompatChanges.isChangeEnabled(eq(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION),
- anyString(), any(UserHandle.class)));
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
// basic exact alarm
setTestAlarm(ELAPSED_REALTIME, 0, 0, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID,
@@ -2501,6 +2573,9 @@
// Mock should return false by default.
verify(mDeviceIdleInternal, atLeastOnce()).isAppOnWhitelist(
UserHandle.getAppId(TEST_CALLING_UID));
+
+ verify(() -> PermissionManagerService.killUid(eq(TEST_CALLING_UID), eq(TEST_CALLING_USER),
+ anyString()));
}
@Test
@@ -2567,6 +2642,86 @@
}
@Test
+ public void onLastOpScheduleExactAlarmOnUserStart() {
+ final int userId = 54;
+ SystemService.TargetUser mockTargetUser = mock(SystemService.TargetUser.class);
+ when(mockTargetUser.getUserIdentifier()).thenReturn(userId);
+
+ final Integer[] appIds = new Integer[]{43, 254, 7731};
+ final int unknownAppId = 2347;
+ final String[] packageNames = new String[]{"p43", "p254", "p7731"};
+ final int[] appOpModes = new int[]{MODE_ALLOWED, MODE_IGNORED, MODE_ERRORED};
+ mService.mExactAlarmCandidates = new ArraySet<>(appIds);
+ mService.mExactAlarmCandidates.add(unknownAppId);
+
+ for (int i = 0; i < appIds.length; i++) {
+ final int uid = UserHandle.getUid(userId, appIds[i]);
+ final AndroidPackage pkg = mock(AndroidPackage.class);
+ when(pkg.getPackageName()).thenReturn(packageNames[i]);
+
+ when(mPackageManagerInternal.getPackage(uid)).thenReturn(pkg);
+ when(mAppOpsManager.checkOpNoThrow(OP_SCHEDULE_EXACT_ALARM, uid,
+ packageNames[i])).thenReturn(appOpModes[i]);
+ }
+
+ final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+ doReturn(true).when(mService.mHandler).post(runnableCaptor.capture());
+
+ mService.onUserStarting(mockTargetUser);
+ runnableCaptor.getValue().run();
+
+ assertEquals(appIds.length, mService.mLastOpScheduleExactAlarm.size());
+ for (int i = 0; i < appIds.length; i++) {
+ final int uid = UserHandle.getUid(userId, appIds[i]);
+ assertEquals(appOpModes[i], mService.mLastOpScheduleExactAlarm.get(uid, -1));
+ }
+ assertTrue(mService.mLastOpScheduleExactAlarm.indexOfKey(
+ UserHandle.getUid(userId, unknownAppId)) < 0);
+ }
+
+ @Test
+ public void refreshExactAlarmCandidatesRemovesExactAlarmsIfNeeded() {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+
+ mService.mExactAlarmCandidates = new ArraySet<>(new Integer[]{1, 2, 5});
+ final String[] updatedRequesters = new String[]{"p11", "p2", "p9"};
+ final Integer[] appIds = new Integer[]{11, 2, 9};
+ registerAppIds(updatedRequesters, appIds);
+
+ when(mPermissionManagerInternal.getAppOpPermissionPackages(
+ SCHEDULE_EXACT_ALARM)).thenReturn(updatedRequesters);
+
+ final PendingIntent exactAppId1 = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 0, 0, exactAppId1, 0, 0,
+ UserHandle.getUid(TEST_CALLING_USER, 1), null);
+
+ final PendingIntent exactAppId2 = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 0, 0, exactAppId2, 0, 0,
+ UserHandle.getUid(TEST_CALLING_USER, 2), null);
+
+ final PendingIntent exactAppId5 = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 0, 0, exactAppId5, 0, 0,
+ UserHandle.getUid(TEST_CALLING_USER, 5), null);
+
+ final PendingIntent inexactAppId5 = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 0, 23, inexactAppId5, 0, 0,
+ UserHandle.getUid(TEST_CALLING_USER, 5), null);
+
+ assertEquals(4, mService.mAlarmStore.size());
+
+ mService.refreshExactAlarmCandidates();
+ // App ids 1 and 5 lost the permission, so there alarms should be removed.
+
+ final ArrayList<Alarm> remaining = mService.mAlarmStore.asList();
+ assertEquals(2, remaining.size());
+
+ assertTrue("Inexact alarm removed",
+ remaining.removeIf(a -> a.matches(inexactAppId5, null)));
+ assertTrue("Alarm from app id 2 removed",
+ remaining.removeIf(a -> a.matches(exactAppId2, null)));
+ }
+
+ @Test
public void refreshExactAlarmCandidatesOnPackageAdded() {
final String[] exactAlarmRequesters = new String[]{"p11", "p2", "p9"};
final Integer[] appIds = new Integer[]{11, 2, 9};
diff --git a/services/tests/mockingservicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java b/services/tests/mockingservicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
new file mode 100644
index 0000000..da0b83e
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
@@ -0,0 +1,235 @@
+/*
+ * 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 static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.DeviceConfig;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.server.appsearch.AppSearchConfig;
+import com.android.server.appsearch.external.localstorage.stats.CallStats;
+import com.android.server.testables.TestableDeviceConfig;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+/**
+ * Tests covering the functionalities in {@link PlatformLogger} requiring overriding some flags
+ * in {@link DeviceConfig}.
+ *
+ * <p>To add tests NOT rely on overriding the configs, please add them in
+ * the tests for {@link PlatformLogger} in servicetests.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class PlatformLoggerTest {
+ private static final int TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS = 100;
+ private static final int TEST_DEFAULT_SAMPLING_INTERVAL = 10;
+ private static final String TEST_PACKAGE_NAME = "packageName";
+ private AppSearchConfig mAppSearchConfig;
+
+ @Rule
+ public final TestableDeviceConfig.TestableDeviceConfigRule
+ mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+
+ @Before
+ public void setUp() throws Exception {
+ mAppSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+ }
+
+ @Test
+ public void testCreateExtraStatsLocked_samplingIntervalNotSet_returnsDefault() {
+ PlatformLogger logger = new PlatformLogger(
+ ApplicationProvider.getApplicationContext(),
+ UserHandle.of(UserHandle.USER_NULL),
+ mAppSearchConfig);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ Long.toString(TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(TEST_DEFAULT_SAMPLING_INTERVAL),
+ false);
+
+ // Make sure default sampling interval is used if there is no config set.
+ assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
+ CallStats.CALL_TYPE_UNKNOWN).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
+ assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
+ CallStats.CALL_TYPE_INITIALIZE).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
+ assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
+ CallStats.CALL_TYPE_SEARCH).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
+ assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
+ CallStats.CALL_TYPE_FLUSH).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
+ }
+
+
+ @Test
+ public void testCreateExtraStatsLocked_samplingIntervalSet_returnsConfigured() {
+ int putDocumentSamplingInterval = 1;
+ int batchCallSamplingInterval = 2;
+ PlatformLogger logger = new PlatformLogger(
+ ApplicationProvider.getApplicationContext(),
+ UserHandle.of(UserHandle.USER_NULL), mAppSearchConfig);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ Long.toString(TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(TEST_DEFAULT_SAMPLING_INTERVAL),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(putDocumentSamplingInterval),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ Integer.toString(batchCallSamplingInterval),
+ false);
+
+ // The default sampling interval should be used if no sampling interval is
+ // provided for certain call type.
+ assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
+ CallStats.CALL_TYPE_INITIALIZE).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
+ assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
+ CallStats.CALL_TYPE_FLUSH).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
+
+ // The configured sampling interval is used if sampling interval is available
+ // for certain call type.
+ assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
+ CallStats.CALL_TYPE_PUT_DOCUMENT).mSamplingInterval).isEqualTo(
+ putDocumentSamplingInterval);
+ assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
+ CallStats.CALL_TYPE_PUT_DOCUMENTS).mSamplingInterval).isEqualTo(
+ batchCallSamplingInterval);
+ assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
+ CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH).mSamplingInterval).isEqualTo(
+ batchCallSamplingInterval);
+ }
+
+ @Test
+ public void testShouldLogForTypeLocked_trueWhenSampleIntervalIsOne() {
+ final String testPackageName = "packageName";
+ PlatformLogger logger = new PlatformLogger(
+ ApplicationProvider.getApplicationContext(),
+ UserHandle.of(UserHandle.USER_NULL),
+ mAppSearchConfig);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Long.toString(1),
+ false);
+
+ // Sample should always be logged for the first time if sampling is disabled(value is one).
+ assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isTrue();
+ assertThat(logger.createExtraStatsLocked(testPackageName,
+ CallStats.CALL_TYPE_PUT_DOCUMENT).mSkippedSampleCount).isEqualTo(0);
+ }
+
+ @Test
+ public void testShouldLogForTypeLocked_falseWhenSampleIntervalIsNegative() {
+ final String testPackageName = "packageName";
+ PlatformLogger logger = new PlatformLogger(
+ ApplicationProvider.getApplicationContext(),
+ UserHandle.of(UserHandle.USER_NULL),
+ mAppSearchConfig);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Long.toString(-1),
+ false);
+
+ // Makes sure sample will be excluded due to sampling if sample interval is negative.
+ assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isFalse();
+ // Skipped count should be 0 since it doesn't pass the sampling.
+ assertThat(logger.createExtraStatsLocked(testPackageName,
+ CallStats.CALL_TYPE_PUT_DOCUMENT).mSkippedSampleCount).isEqualTo(0);
+ }
+
+ @Test
+ public void testShouldLogForTypeLocked_falseWhenWithinCoolOffInterval() {
+ // Next sample won't be excluded due to sampling.
+ final int samplingInterval = 1;
+ // Next sample would guaranteed to be too close.
+ final int minTimeIntervalBetweenSamplesMillis = Integer.MAX_VALUE;
+ final String testPackageName = "packageName";
+ PlatformLogger logger = new PlatformLogger(
+ ApplicationProvider.getApplicationContext(),
+ UserHandle.of(UserHandle.USER_NULL),
+ mAppSearchConfig);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Long.toString(samplingInterval),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ Long.toString(minTimeIntervalBetweenSamplesMillis),
+ false);
+ logger.setLastPushTimeMillisLocked(SystemClock.elapsedRealtime());
+
+ // Makes sure sample will be excluded due to rate limiting if samples are too close.
+ assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isFalse();
+ assertThat(logger.createExtraStatsLocked(testPackageName,
+ CallStats.CALL_TYPE_PUT_DOCUMENT).mSkippedSampleCount).isEqualTo(1);
+ }
+
+ @Test
+ public void testShouldLogForTypeLocked_trueWhenOutsideOfCoolOffInterval() {
+ // Next sample won't be excluded due to sampling.
+ final int samplingInterval = 1;
+ // Next sample would guaranteed to be included.
+ final int minTimeIntervalBetweenSamplesMillis = 0;
+ final String testPackageName = "packageName";
+ PlatformLogger logger = new PlatformLogger(
+ ApplicationProvider.getApplicationContext(),
+ UserHandle.of(UserHandle.USER_NULL),
+ mAppSearchConfig);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Long.toString(samplingInterval),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ Long.toString(minTimeIntervalBetweenSamplesMillis),
+ false);
+ logger.setLastPushTimeMillisLocked(SystemClock.elapsedRealtime());
+
+ // Makes sure sample will be logged if it is not too close to previous sample.
+ assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isTrue();
+ assertThat(logger.createExtraStatsLocked(testPackageName,
+ CallStats.CALL_TYPE_PUT_DOCUMENT).mSkippedSampleCount).isEqualTo(0);
+ }
+}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 9d055e0..339a5f9 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -118,6 +118,11 @@
":PackageParserTestApp3",
":PackageParserTestApp4",
":apex.test",
+ ":test.rebootless_apex_v1",
+ ":test.rebootless_apex_v2",
+ ":com.android.apex.cts.shim.v1_prebuilt",
+ ":com.android.apex.cts.shim.v2_different_certificate_prebuilt",
+ ":com.android.apex.cts.shim.v2_unsigned_apk_container_prebuilt",
],
resource_zips: [":FrameworksServicesTests_apks_as_resources"],
}
diff --git a/services/tests/servicestests/apks/install-split-base/AndroidManifest.xml b/services/tests/servicestests/apks/install-split-base/AndroidManifest.xml
index 1ff41e1..ac563c6 100644
--- a/services/tests/servicestests/apks/install-split-base/AndroidManifest.xml
+++ b/services/tests/servicestests/apks/install-split-base/AndroidManifest.xml
@@ -15,8 +15,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.frameworks.servicestests.install_split"
- android:isolatedSplits="true">
+ package="com.android.frameworks.servicestests.install_split"
+ android:isolatedSplits="true"
+ android:versionCode="9001"
+ android:versionName="1.0"
+ >
<application android:label="ClassloaderSplitApp">
<activity android:name=".BaseActivity"
diff --git a/services/tests/servicestests/apks/install-split-feature-a/AndroidManifest.xml b/services/tests/servicestests/apks/install-split-feature-a/AndroidManifest.xml
index dfeec8c..28c251c 100644
--- a/services/tests/servicestests/apks/install-split-feature-a/AndroidManifest.xml
+++ b/services/tests/servicestests/apks/install-split-feature-a/AndroidManifest.xml
@@ -15,8 +15,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.frameworks.servicestests.install_split"
- featureSplit="feature_a">
+ package="com.android.frameworks.servicestests.install_split"
+ featureSplit="feature_a"
+ android:versionCode="9001"
+ android:versionName="1.0"
+ >
<application>
<activity android:name=".feature_a.FeatureAActivity"
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
index eace99f..e19aa72 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
@@ -59,6 +59,7 @@
import androidx.test.filters.FlakyTest;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
@@ -79,7 +80,9 @@
public class ActivityManagerTest {
private static final String TAG = "ActivityManagerTest";
- private static final String TEST_APP = "com.android.servicestests.apps.simpleservicetestapp1";
+ private static final String TEST_APP1 = "com.android.servicestests.apps.simpleservicetestapp1";
+ private static final String TEST_APP2 = "com.android.servicestests.apps.simpleservicetestapp2";
+ private static final String TEST_APP3 = "com.android.servicestests.apps.simpleservicetestapp3";
private static final String TEST_CLASS =
"com.android.servicestests.apps.simpleservicetestapp.SimpleService";
private static final int TEST_LOOPS = 100;
@@ -135,13 +138,13 @@
final PackageManager pm = mContext.getPackageManager();
int uid = 0;
try {
- uid = pm.getPackageUid(TEST_APP, 0);
+ uid = pm.getPackageUid(TEST_APP1, 0);
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(e);
}
Intent intent = new Intent();
- intent.setClassName(TEST_APP, TEST_CLASS);
+ intent.setClassName(TEST_APP1, TEST_CLASS);
// Create a service connection with auto creation.
CountDownLatch latch = new CountDownLatch(1);
@@ -156,7 +159,7 @@
// Create a service connection without any flags.
intent = new Intent();
- intent.setClassName(TEST_APP, TEST_CLASS);
+ intent.setClassName(TEST_APP1, TEST_CLASS);
latch = new CountDownLatch(1);
MyServiceConnection otherConnection = new MyServiceConnection(latch);
mContext.bindService(intent, otherConnection, 0);
@@ -242,7 +245,7 @@
public void testFgsProcStatsTracker() throws Exception {
final PackageManager pm = mContext.getPackageManager();
final long timeout = 5000;
- int uid = pm.getPackageUid(TEST_APP, 0);
+ int uid = pm.getPackageUid(TEST_APP1, 0);
final MyUidImportanceListener uidListener1 = new MyUidImportanceListener(uid);
final MyUidImportanceListener uidListener2 = new MyUidImportanceListener(uid);
final ActivityManager am = mContext.getSystemService(ActivityManager.class);
@@ -275,12 +278,12 @@
am.addOnUidImportanceListener(uidListener1,
RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE);
am.addOnUidImportanceListener(uidListener2, RunningAppProcessInfo.IMPORTANCE_GONE);
- runShellCommand("cmd deviceidle whitelist +" + TEST_APP);
+ runShellCommand("cmd deviceidle whitelist +" + TEST_APP1);
toggleScreenOn(true);
final Intent intent = new Intent(ACTION_FGS_STATS_TEST);
final ComponentName cn = ComponentName.unflattenFromString(
- TEST_APP + "/" + TEST_FGS_CLASS);
+ TEST_APP1 + "/" + TEST_FGS_CLASS);
final Bundle bundle = new Bundle();
intent.setComponent(cn);
bundle.putBinder(EXTRA_MESSENGER, messenger.getBinder());
@@ -314,10 +317,10 @@
timeout * 2, TimeUnit.MILLISECONDS));
} finally {
toggleScreenOn(true);
- runShellCommand("cmd deviceidle whitelist -" + TEST_APP);
+ runShellCommand("cmd deviceidle whitelist -" + TEST_APP1);
am.removeOnUidImportanceListener(uidListener1);
am.removeOnUidImportanceListener(uidListener2);
- am.forceStopPackage(TEST_APP);
+ am.forceStopPackage(TEST_APP1);
mContext.unregisterReceiver(receiver);
}
}
@@ -358,7 +361,7 @@
ActivityManagerConstants.KEY_MAX_SERVICE_INACTIVITY + "=" + waitFor);
final Intent intent = new Intent();
- intent.setClassName(TEST_APP, TEST_CLASS);
+ intent.setClassName(TEST_APP1, TEST_CLASS);
final CountDownLatch latch = new CountDownLatch(1);
autoConnection = new MyServiceConnection(latch);
@@ -370,7 +373,7 @@
} catch (InterruptedException e) {
fail("Unable to bind to service " + intent.getComponent());
}
- assertFalse(TEST_APP + " shouldn't be frozen now.", isAppFrozen(TEST_APP));
+ assertFalse(TEST_APP1 + " shouldn't be frozen now.", isAppFrozen(TEST_APP1));
// Trigger oomAdjUpdate/
toggleScreenOn(false);
@@ -380,7 +383,7 @@
Thread.sleep(waitFor * 4);
// It still shouldn't be frozen, although it's been in cached state.
- assertFalse(TEST_APP + " shouldn't be frozen now.", isAppFrozen(TEST_APP));
+ assertFalse(TEST_APP1 + " shouldn't be frozen now.", isAppFrozen(TEST_APP1));
} finally {
toggleScreenOn(true);
if (amConstantsSettings != null) {
@@ -424,7 +427,7 @@
final long shortTimeoutMs = 5_000;
final long backgroundSettleMs = 10_000;
final PackageManager pm = mContext.getPackageManager();
- final int uid = pm.getPackageUid(TEST_APP, 0);
+ final int uid = pm.getPackageUid(TEST_APP1, 0);
final MyUidImportanceListener uidListener1 = new MyUidImportanceListener(uid);
final MyUidImportanceListener uidListener2 = new MyUidImportanceListener(uid);
SettingsSession<String> amConstantsSettings = null;
@@ -462,11 +465,11 @@
Thread.sleep(currentBackgroundSettleMs);
amConstantsSettings.set(
ActivityManagerConstants.KEY_BACKGROUND_SETTLE_TIME + "=" + backgroundSettleMs);
- runShellCommand("cmd appops set " + TEST_APP + " RUN_ANY_IN_BACKGROUND allow");
+ runShellCommand("cmd appops set " + TEST_APP1 + " RUN_ANY_IN_BACKGROUND allow");
final Intent intent = new Intent(ACTION_FGS_STATS_TEST);
final ComponentName cn = ComponentName.unflattenFromString(
- TEST_APP + "/" + TEST_FGS_CLASS);
+ TEST_APP1 + "/" + TEST_FGS_CLASS);
final Bundle bundle = new Bundle();
intent.setComponent(cn);
bundle.putBinder(EXTRA_MESSENGER, messenger.getBinder());
@@ -491,21 +494,21 @@
RunningAppProcessInfo.IMPORTANCE_GONE, backgroundSettleMs + shortTimeoutMs));
// Set the FAS state.
- runShellCommand("cmd appops set " + TEST_APP + " RUN_ANY_IN_BACKGROUND deny");
+ runShellCommand("cmd appops set " + TEST_APP1 + " RUN_ANY_IN_BACKGROUND deny");
// Now it should've been killed.
assertTrue("Should have been killed", uidListener2.waitFor(
RunningAppProcessInfo.IMPORTANCE_GONE, backgroundSettleMs + shortTimeoutMs));
// Start the FGS.
// Temporarily allow RUN_ANY_IN_BACKGROUND to start FGS.
- runShellCommand("cmd appops set " + TEST_APP + " RUN_ANY_IN_BACKGROUND allow");
+ runShellCommand("cmd appops set " + TEST_APP1 + " RUN_ANY_IN_BACKGROUND allow");
latchHolder[0] = new CountDownLatch(1);
mContext.startForegroundService(intent);
assertTrue("Timed out to start fg service", uidListener1.waitFor(
RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, shortTimeoutMs));
assertTrue("Timed out to get the remote messenger", latchHolder[0].await(
shortTimeoutMs, TimeUnit.MILLISECONDS));
- runShellCommand("cmd appops set " + TEST_APP + " RUN_ANY_IN_BACKGROUND deny");
+ runShellCommand("cmd appops set " + TEST_APP1 + " RUN_ANY_IN_BACKGROUND deny");
// It shouldn't be killed since it's not cached.
assertFalse("FGS shouldn't be killed", uidListener2.waitFor(
RunningAppProcessInfo.IMPORTANCE_GONE, backgroundSettleMs + shortTimeoutMs));
@@ -523,14 +526,14 @@
// Start the FGS.
// Temporarily allow RUN_ANY_IN_BACKGROUND to start FGS.
- runShellCommand("cmd appops set " + TEST_APP + " RUN_ANY_IN_BACKGROUND allow");
+ runShellCommand("cmd appops set " + TEST_APP1 + " RUN_ANY_IN_BACKGROUND allow");
latchHolder[0] = new CountDownLatch(1);
mContext.startForegroundService(intent);
assertTrue("Timed out to start fg service", uidListener1.waitFor(
RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, shortTimeoutMs));
assertTrue("Timed out to get the remote messenger", latchHolder[0].await(
shortTimeoutMs, TimeUnit.MILLISECONDS));
- runShellCommand("cmd appops set " + TEST_APP + " RUN_ANY_IN_BACKGROUND deny");
+ runShellCommand("cmd appops set " + TEST_APP1 + " RUN_ANY_IN_BACKGROUND deny");
assertFalse("FGS shouldn't be killed", uidListener2.waitFor(
RunningAppProcessInfo.IMPORTANCE_GONE, backgroundSettleMs + shortTimeoutMs));
@@ -542,7 +545,7 @@
assertFalse("FGS shouldn't be killed", uidListener2.waitFor(
RunningAppProcessInfo.IMPORTANCE_GONE, backgroundSettleMs + shortTimeoutMs));
} finally {
- runShellCommand("cmd appops set " + TEST_APP + " RUN_ANY_IN_BACKGROUND default");
+ runShellCommand("cmd appops set " + TEST_APP1 + " RUN_ANY_IN_BACKGROUND default");
if (amConstantsSettings != null) {
amConstantsSettings.close();
}
@@ -554,6 +557,82 @@
}
}
+ @Ignore("Need to disable calling uid check in ActivityManagerService.killPids before this test")
+ @Test
+ public void testKillPids() throws Exception {
+ final long timeout = 5000;
+ final long shortTimeout = 2000;
+ final ActivityManager am = mContext.getSystemService(ActivityManager.class);
+ final PackageManager pm = mContext.getPackageManager();
+ final int uid1 = pm.getPackageUid(TEST_APP1, 0);
+ final int uid2 = pm.getPackageUid(TEST_APP2, 0);
+ final int uid3 = pm.getPackageUid(TEST_APP3, 0);
+ final MyUidImportanceListener uid1Listener1 = new MyUidImportanceListener(uid1);
+ final MyUidImportanceListener uid1Listener2 = new MyUidImportanceListener(uid1);
+ final MyUidImportanceListener uid2Listener1 = new MyUidImportanceListener(uid2);
+ final MyUidImportanceListener uid2Listener2 = new MyUidImportanceListener(uid2);
+ final MyUidImportanceListener uid3Listener1 = new MyUidImportanceListener(uid3);
+ final MyUidImportanceListener uid3Listener2 = new MyUidImportanceListener(uid3);
+ try {
+ am.addOnUidImportanceListener(uid1Listener1, RunningAppProcessInfo.IMPORTANCE_SERVICE);
+ am.addOnUidImportanceListener(uid1Listener2, RunningAppProcessInfo.IMPORTANCE_GONE);
+ am.addOnUidImportanceListener(uid2Listener1, RunningAppProcessInfo.IMPORTANCE_SERVICE);
+ am.addOnUidImportanceListener(uid2Listener2, RunningAppProcessInfo.IMPORTANCE_GONE);
+ am.addOnUidImportanceListener(uid3Listener1, RunningAppProcessInfo.IMPORTANCE_SERVICE);
+ am.addOnUidImportanceListener(uid3Listener2, RunningAppProcessInfo.IMPORTANCE_GONE);
+ runShellCommand("cmd deviceidle whitelist +" + TEST_APP1);
+ runShellCommand("cmd deviceidle whitelist +" + TEST_APP2);
+ runShellCommand("cmd deviceidle whitelist +" + TEST_APP3);
+ final int[] pids = new int[3];
+ // Test sync kills
+ pids[0] = startTargetService(am, TEST_APP1, TEST_CLASS, uid1, TEST_APP1,
+ uid1Listener1, timeout);
+ pids[1] = startTargetService(am, TEST_APP2, TEST_CLASS, uid2, TEST_APP2,
+ uid2Listener1, timeout);
+ pids[2] = startTargetService(am, TEST_APP3, TEST_CLASS, uid3, TEST_APP3,
+ uid3Listener1, timeout);
+ Thread.sleep(shortTimeout);
+ mService.killPids(pids, "testKillPids", false);
+ assertTrue("Timed out to kill process", uid1Listener2.waitFor(
+ RunningAppProcessInfo.IMPORTANCE_GONE, timeout));
+ assertTrue("Timed out to kill process", uid2Listener2.waitFor(
+ RunningAppProcessInfo.IMPORTANCE_GONE, timeout));
+ assertTrue("Timed out to kill process", uid3Listener2.waitFor(
+ RunningAppProcessInfo.IMPORTANCE_GONE, timeout));
+ } finally {
+ runShellCommand("cmd deviceidle whitelist -" + TEST_APP1);
+ runShellCommand("cmd deviceidle whitelist -" + TEST_APP2);
+ runShellCommand("cmd deviceidle whitelist -" + TEST_APP3);
+ am.removeOnUidImportanceListener(uid1Listener1);
+ am.removeOnUidImportanceListener(uid1Listener2);
+ am.removeOnUidImportanceListener(uid2Listener1);
+ am.removeOnUidImportanceListener(uid2Listener2);
+ am.removeOnUidImportanceListener(uid3Listener1);
+ am.removeOnUidImportanceListener(uid3Listener2);
+ am.forceStopPackage(TEST_APP1);
+ am.forceStopPackage(TEST_APP2);
+ am.forceStopPackage(TEST_APP3);
+ }
+ }
+
+ private int startTargetService(ActivityManager am, String targetPakage, String targetService,
+ int targetUid, String targetProcessName, MyUidImportanceListener uidListener,
+ long timeout) throws Exception {
+ final Intent intent = new Intent();
+ intent.setComponent(ComponentName.unflattenFromString(targetPakage + "/" + targetService));
+ mContext.startService(intent);
+ assertTrue("Timed out to start service", uidListener.waitFor(
+ RunningAppProcessInfo.IMPORTANCE_SERVICE, timeout));
+ final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses();
+ for (int i = processes.size() - 1; i >= 0; i--) {
+ final RunningAppProcessInfo info = processes.get(i);
+ if (info.uid == targetUid && targetProcessName.equals(info.processName)) {
+ return info.pid;
+ }
+ }
+ return -1;
+ }
+
/**
* Make sure the screen state.
*/
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 755795d..3bcbcbdb 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
@@ -25,11 +25,18 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.PackageIdentifier;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
import androidx.test.core.app.ApplicationProvider;
@@ -43,13 +50,15 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
import java.util.Collections;
+import java.util.Map;
/** This tests AppSearchImpl when it's running with a platform-backed VisibilityStore. */
public class AppSearchImplPlatformTest {
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
- private MockPackageManager mMockPackageManager = new MockPackageManager();
+ private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
private AppSearchImpl mAppSearchImpl;
private int mGlobalQuerierUid;
@@ -57,20 +66,28 @@
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
- mContext =
- new ContextWrapper(context) {
+ mContext = new ContextWrapper(context) {
+ @Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return new ContextWrapper(super.createContextAsUser(user, flags)) {
@Override
public PackageManager getPackageManager() {
- return mMockPackageManager.getMockPackageManager();
+ return getMockPackageManager(user);
}
};
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return createContextAsUser(getUser(), /*flags=*/ 0).getPackageManager();
+ }
+ };
// Give ourselves global query permissions
mAppSearchImpl =
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
mContext,
- mContext.getUserId(),
/*logger=*/ null);
mGlobalQuerierUid =
@@ -85,14 +102,19 @@
int uidFoo = 1;
// Make sure foo package will pass package manager checks.
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
// Make sure we have global query privileges and "foo" doesn't
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
// Set schema1
String prefix = PrefixUtil.createPrefix("package", "database");
@@ -145,19 +167,16 @@
/*schemaVersion=*/ 0);
// Check that "schema1" still has the same visibility settings
- SystemUtil.runWithShellPermissionIdentity(
- () -> {
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- mContext.getPackageName(),
- mGlobalQuerierUid))
- .isFalse();
- },
+ SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ mContext.getPackageName(),
+ mGlobalQuerierUid))
+ .isFalse(),
READ_GLOBAL_APP_SEARCH_DATA);
assertThat(
@@ -172,19 +191,16 @@
.isTrue();
// "schema2" has default visibility settings
- SystemUtil.runWithShellPermissionIdentity(
- () -> {
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema2",
- mContext.getPackageName(),
- mGlobalQuerierUid))
- .isTrue();
- },
+ SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema2",
+ mContext.getPackageName(),
+ mGlobalQuerierUid))
+ .isTrue(),
READ_GLOBAL_APP_SEARCH_DATA);
assertThat(
@@ -207,14 +223,19 @@
int uidFoo = 1;
// Make sure foo package will pass package manager checks.
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
// Make sure we have global query privileges and "foo" doesn't
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -320,8 +341,10 @@
@Test
public void testSetSchema_defaultPlatformVisible() throws Exception {
// Make sure we have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -348,8 +371,10 @@
@Test
public void testSetSchema_platformHidden() throws Exception {
// Make sure we have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -378,8 +403,9 @@
String packageName = "com.package";
// Make sure package doesn't global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageName, PERMISSION_DENIED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, packageName)).thenReturn(PERMISSION_DENIED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -410,12 +436,16 @@
int uidFoo = 1;
// Make sure foo package will pass package manager checks.
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
// Make sure foo doesn't have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -439,4 +469,14 @@
uidFoo))
.isTrue();
}
+
+ @NonNull
+ private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+ PackageManager pm = mMockPackageManagers.get(user);
+ if (pm == null) {
+ pm = Mockito.mock(PackageManager.class);
+ mMockPackageManagers.put(user, pm);
+ }
+ return pm;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/MockPackageManager.java b/services/tests/servicestests/src/com/android/server/appsearch/MockPackageManager.java
deleted file mode 100644
index 60e1a8f..0000000
--- a/services/tests/servicestests/src/com/android/server/appsearch/MockPackageManager.java
+++ /dev/null
@@ -1,94 +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.
- */
-
-// TODO(b/169883602): This is purposely a different package from the path so that AppSearchImplTest
-// can use it without an extra import. This should be moved into a proper package once
-// AppSearchImpl-VisibilityStore's dependencies are refactored.
-package com.android.server.appsearch.external.localstorage;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-import android.annotation.NonNull;
-import android.annotation.UserIdInt;
-import android.content.pm.PackageManager;
-
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/** Mock to help test package name, UID, and certificate verification. */
-public class MockPackageManager {
-
- @Mock private PackageManager mMockPackageManager;
-
- public MockPackageManager() {
- MockitoAnnotations.initMocks(this);
- }
-
- @NonNull
- public PackageManager getMockPackageManager() {
- return mMockPackageManager;
- }
-
- /** Mock a checkPermission call. */
- public void mockCheckPermission(String permission, String packageName, int permissionResult) {
- when(mMockPackageManager.checkPermission(permission, packageName))
- .thenReturn(permissionResult);
- }
-
- /** Mock a NameNotFoundException if the package name isn't installed. */
- public void mockThrowsNameNotFoundException(String packageName) {
- try {
- when(mMockPackageManager.getPackageUidAsUser(eq(packageName), /*userId=*/ anyInt()))
- .thenThrow(new PackageManager.NameNotFoundException());
- when(mMockPackageManager.getPackageUidAsUser(
- eq(packageName), /*flags=*/ anyInt(), /*userId=*/ anyInt()))
- .thenThrow(new PackageManager.NameNotFoundException());
- } catch (PackageManager.NameNotFoundException e) {
- // Shouldn't ever happen since we're mocking the exception
- e.printStackTrace();
- }
- }
-
- /** Mocks that {@code uid} contains the {@code packageName} */
- public void mockGetPackageUidAsUser(String packageName, @UserIdInt int callerUserId, int uid) {
- try {
- when(mMockPackageManager.getPackageUidAsUser(eq(packageName), eq(callerUserId)))
- .thenReturn(uid);
- when(mMockPackageManager.getPackageUidAsUser(
- eq(packageName), /*flags=*/ anyInt(), eq(callerUserId)))
- .thenReturn(uid);
- } catch (PackageManager.NameNotFoundException e) {
- // Shouldn't ever happen since we're mocking the method.
- e.printStackTrace();
- }
- }
-
- /** Mocks that {@code packageName} has been signed with {@code sha256Cert}. */
- public void mockAddSigningCertificate(String packageName, byte[] sha256Cert) {
- when(mMockPackageManager.hasSigningCertificate(
- packageName, sha256Cert, PackageManager.CERT_INPUT_SHA256))
- .thenReturn(true);
- }
-
- /** Mocks that {@code packageName} has NOT been signed with {@code sha256Cert}. */
- public void mockRemoveSigningCertificate(String packageName, byte[] sha256Cert) {
- when(mMockPackageManager.hasSigningCertificate(
- packageName, sha256Cert, PackageManager.CERT_INPUT_SHA256))
- .thenReturn(false);
- }
-}
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 d9cfc54..6ac4d13 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
@@ -25,10 +25,17 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
import android.app.appsearch.PackageIdentifier;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
import androidx.test.core.app.ApplicationProvider;
@@ -43,39 +50,47 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
import java.util.Collections;
+import java.util.Map;
public class VisibilityStoreTest {
-
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
- private MockPackageManager mMockPackageManager = new MockPackageManager();
+ private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
- private AppSearchImpl mAppSearchImpl;
private VisibilityStore mVisibilityStore;
private int mUid;
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
- mContext =
- new ContextWrapper(context) {
+ mContext = new ContextWrapper(context) {
+ @Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return new ContextWrapper(super.createContextAsUser(user, flags)) {
@Override
public PackageManager getPackageManager() {
- return mMockPackageManager.getMockPackageManager();
+ return getMockPackageManager(user);
}
};
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return createContextAsUser(getUser(), /*flags=*/ 0).getPackageManager();
+ }
+ };
// Give ourselves global query permissions
- mAppSearchImpl =
+ AppSearchImpl appSearchImpl =
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
mContext,
- mContext.getUserId(),
/*logger=*/ null);
mUid = mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
- mVisibilityStore = mAppSearchImpl.getVisibilityStoreLocked();
+ mVisibilityStore = appSearchImpl.getVisibilityStoreLocked();
}
/**
@@ -103,8 +118,10 @@
@Test
public void testSetVisibility_platformSurfaceable() throws Exception {
// Make sure we have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
mVisibilityStore.setVisibility(
"package",
@@ -210,10 +227,13 @@
int uidNotFooOrBar = 3;
// Make sure none of them have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameBar, PERMISSION_DENIED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameBar))
+ .thenReturn(PERMISSION_DENIED);
// By default, a schema isn't package accessible.
assertThat(
@@ -237,32 +257,43 @@
ImmutableList.of(new PackageIdentifier(packageNameBar, sha256CertBar))));
// Should fail if PackageManager doesn't see that it has the proper certificate
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockRemoveSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(false);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isFalse();
// Should fail if PackageManager doesn't think the package belongs to the uid
- mMockPackageManager.mockGetPackageUidAsUser(
- packageNameFoo, mContext.getUserId(), uidNotFooOrBar);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidNotFooOrBar);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isFalse();
// But if uid and certificate match, then we should have access
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isTrue();
- mMockPackageManager.mockGetPackageUidAsUser(packageNameBar, mContext.getUserId(), uidBar);
- mMockPackageManager.mockAddSigningCertificate(packageNameBar, sha256CertBar);
+ when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
+ .thenReturn(uidBar);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaBar", packageNameBar, uidBar))
@@ -278,15 +309,21 @@
"prefix/schemaFoo",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))));
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isTrue();
- mMockPackageManager.mockGetPackageUidAsUser(packageNameBar, mContext.getUserId(), uidBar);
- mMockPackageManager.mockAddSigningCertificate(packageNameBar, sha256CertBar);
+ when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
+ .thenReturn(uidBar);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaBar", packageNameBar, uidBar))
@@ -302,11 +339,13 @@
int uidFoo = 1;
// Pretend we can't find the Foo package.
- mMockPackageManager.mockThrowsNameNotFoundException(packageNameFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenThrow(new PackageManager.NameNotFoundException());
// Make sure "foo" doesn't have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
// Grant package access
mVisibilityStore.setVisibility(
@@ -332,10 +371,12 @@
int uidFoo = 1;
// Set it up such that the test package has global query privileges, but "foo" doesn't.
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
mVisibilityStore.setVisibility(
/*packageName=*/ "",
@@ -354,8 +395,11 @@
mUid))
.isTrue();
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
/*packageName=*/ "",
@@ -365,4 +409,14 @@
uidFoo))
.isTrue();
}
+
+ @NonNull
+ private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+ PackageManager pm = mMockPackageManagers.get(user);
+ if (pm == null) {
+ pm = Mockito.mock(PackageManager.class);
+ mMockPackageManagers.put(user, pm);
+ }
+ return pm;
+ }
}
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 031532b..5a8c44c 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
@@ -86,7 +86,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
/*logger=*/ null);
}
@@ -494,9 +493,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
// Insert schema
List<AppSearchSchema> schemas =
@@ -557,9 +554,7 @@
// Initialize AppSearchImpl. This should cause a reset.
appSearchImpl.close();
- appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, testLogger);
+ appSearchImpl = AppSearchImpl.create(appsearchDir, context, testLogger);
// Check recovery state
InitializeStats initStats = testLogger.mInitializeStats;
@@ -1688,7 +1683,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
/*logger=*/ null);
// Initial check that we could do something at first.
@@ -1836,9 +1830,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1864,8 +1856,7 @@
// That document should be visible even from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
getResult =
appSearchImpl2.getDocument(
"package", "database", "namespace1", "id1", Collections.emptyMap());
@@ -1877,9 +1868,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1929,8 +1918,7 @@
// Only the second document should be retrievable from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
expectThrows(
AppSearchException.class,
() ->
@@ -1951,9 +1939,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -2011,8 +1997,7 @@
// Only the second document should be retrievable from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
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 d1ca759..f0a6ef1 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
@@ -40,7 +40,6 @@
import com.android.server.appsearch.proto.QueryStatsProto;
import com.android.server.appsearch.proto.ScoringSpecProto;
import com.android.server.appsearch.proto.TermMatchType;
-import com.android.server.appsearch.visibilitystore.VisibilityStore;
import org.junit.Before;
import org.junit.Rule;
@@ -64,7 +63,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
/*logger=*/ null);
mLogger = new TestLogger();
}
@@ -292,7 +290,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
mLogger);
InitializeStats iStats = mLogger.mInitializeStats;
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
index 734f05a..7c275e1 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
@@ -16,119 +16,64 @@
package com.android.server.appsearch.stats;
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
-import android.os.SystemClock;
import android.os.UserHandle;
-import android.util.SparseIntArray;
+import android.util.ArrayMap;
import androidx.test.core.app.ApplicationProvider;
-import com.android.server.appsearch.external.localstorage.MockPackageManager;
+import com.android.server.appsearch.AppSearchConfig;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mockito;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+/**
+ * Tests covering the functionalities in {@link PlatformLogger} NOT requiring overriding any flags
+ * in {@link android.provider.DeviceConfig}.
+ *
+ * <p>To add tests rely on overriding the flags, please add them in the
+ * tests for {@link PlatformLogger} in mockingservicestests.
+ */
public class PlatformLoggerTest {
- private static final int TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS = 100;
- private static final int TEST_DEFAULT_SAMPLING_INTERVAL = 10;
- private static final String TEST_PACKAGE_NAME = "packageName";
- private MockPackageManager mMockPackageManager = new MockPackageManager();
+ private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
- mContext =
- new ContextWrapper(context) {
+ mContext = new ContextWrapper(context) {
+ @Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return new ContextWrapper(super.createContextAsUser(user, flags)) {
@Override
public PackageManager getPackageManager() {
- return mMockPackageManager.getMockPackageManager();
+ return getMockPackageManager(user);
}
};
- }
-
- static int calculateHashCodeMd5withBigInteger(@NonNull String str) throws
- NoSuchAlgorithmException, UnsupportedEncodingException {
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(str.getBytes(/*charsetName=*/ "UTF-8"));
- byte[] digest = md.digest();
- return new BigInteger(digest).intValue();
- }
-
- @Test
- public void testCreateExtraStatsLocked_nullSamplingIntervalMap_returnsDefault() {
- PlatformLogger logger = new PlatformLogger(
- ApplicationProvider.getApplicationContext(),
- UserHandle.of(UserHandle.USER_NULL),
- new PlatformLogger.Config(
- TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- TEST_DEFAULT_SAMPLING_INTERVAL,
- /*samplingIntervals=*/ new SparseIntArray()));
-
- // Make sure default sampling interval is used if samplingMap is not provided.
- assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_UNKNOWN).mSamplingInterval).isEqualTo(
- TEST_DEFAULT_SAMPLING_INTERVAL);
- assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_INITIALIZE).mSamplingInterval).isEqualTo(
- TEST_DEFAULT_SAMPLING_INTERVAL);
- assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_SEARCH).mSamplingInterval).isEqualTo(
- TEST_DEFAULT_SAMPLING_INTERVAL);
- assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_FLUSH).mSamplingInterval).isEqualTo(
- TEST_DEFAULT_SAMPLING_INTERVAL);
- }
-
-
- @Test
- public void testCreateExtraStatsLocked_with_samplingIntervalMap_returnsConfigured() {
- int putDocumentSamplingInterval = 1;
- int querySamplingInterval = 2;
- final SparseIntArray samplingIntervals = new SparseIntArray();
- samplingIntervals.put(CallStats.CALL_TYPE_PUT_DOCUMENT, putDocumentSamplingInterval);
- samplingIntervals.put(CallStats.CALL_TYPE_SEARCH, querySamplingInterval);
- PlatformLogger logger = new PlatformLogger(
- ApplicationProvider.getApplicationContext(),
- UserHandle.of(UserHandle.USER_NULL),
- new PlatformLogger.Config(
- TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- TEST_DEFAULT_SAMPLING_INTERVAL,
- samplingIntervals));
-
- // The default sampling interval should be used if no sampling interval is
- // provided for certain call type.
- assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_INITIALIZE).mSamplingInterval).isEqualTo(
- TEST_DEFAULT_SAMPLING_INTERVAL);
- assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_FLUSH).mSamplingInterval).isEqualTo(
- TEST_DEFAULT_SAMPLING_INTERVAL);
-
- // The configured sampling interval is used if sampling interval is available
- // for certain call type.
- assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_PUT_DOCUMENT).mSamplingInterval).isEqualTo(
- putDocumentSamplingInterval);
- assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_SEARCH).mSamplingInterval).isEqualTo(
- querySamplingInterval);
+ }
+ };
}
@Test
@@ -201,87 +146,6 @@
assertThat(PlatformLogger.calculateHashCodeMd5(/*str=*/ null)).isEqualTo(-1);
}
- @Test
- public void testShouldLogForTypeLocked_trueWhenSampleIntervalIsOne() {
- final int samplingInterval = 1;
- final String testPackageName = "packageName";
- PlatformLogger logger = new PlatformLogger(
- ApplicationProvider.getApplicationContext(),
- UserHandle.of(UserHandle.USER_NULL),
- new PlatformLogger.Config(
- TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- samplingInterval,
- /*samplingIntervals=*/ new SparseIntArray()));
-
- // Sample should always be logged for the first time if sampling is disabled(value is one).
- assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isTrue();
- assertThat(logger.createExtraStatsLocked(testPackageName,
- CallStats.CALL_TYPE_PUT_DOCUMENT).mSkippedSampleCount).isEqualTo(0);
- }
-
- @Test
- public void testShouldLogForTypeLocked_falseWhenSampleIntervalIsNegative() {
- final int samplingInterval = -1;
- final String testPackageName = "packageName";
- PlatformLogger logger = new PlatformLogger(
- ApplicationProvider.getApplicationContext(),
- UserHandle.of(UserHandle.USER_NULL),
- new PlatformLogger.Config(
- TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- samplingInterval,
- /*samplingIntervals=*/ new SparseIntArray()));
-
- // Makes sure sample will be excluded due to sampling if sample interval is negative.
- assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isFalse();
- // Skipped count should be 0 since it doesn't pass the sampling.
- assertThat(logger.createExtraStatsLocked(testPackageName,
- CallStats.CALL_TYPE_PUT_DOCUMENT).mSkippedSampleCount).isEqualTo(0);
- }
-
- @Test
- public void testShouldLogForTypeLocked_falseWhenWithinCoolOffInterval() {
- // Next sample won't be excluded due to sampling.
- final int samplingInterval = 1;
- // Next sample would guaranteed to be too close.
- final int minTimeIntervalBetweenSamplesMillis = Integer.MAX_VALUE;
- final String testPackageName = "packageName";
- PlatformLogger logger = new PlatformLogger(
- ApplicationProvider.getApplicationContext(),
- UserHandle.of(UserHandle.USER_NULL),
- new PlatformLogger.Config(
- minTimeIntervalBetweenSamplesMillis,
- samplingInterval,
- /*samplingIntervals=*/ new SparseIntArray()));
- logger.setLastPushTimeMillisLocked(SystemClock.elapsedRealtime());
-
- // Makes sure sample will be excluded due to rate limiting if samples are too close.
- assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isFalse();
- assertThat(logger.createExtraStatsLocked(testPackageName,
- CallStats.CALL_TYPE_PUT_DOCUMENT).mSkippedSampleCount).isEqualTo(1);
- }
-
- @Test
- public void testShouldLogForTypeLocked_trueWhenOutsideOfCoolOffInterval() {
- // Next sample won't be excluded due to sampling.
- final int samplingInterval = 1;
- // Next sample would guaranteed to be included.
- final int minTimeIntervalBetweenSamplesMillis = 0;
- final String testPackageName = "packageName";
- PlatformLogger logger = new PlatformLogger(
- ApplicationProvider.getApplicationContext(),
- UserHandle.of(UserHandle.USER_NULL),
- new PlatformLogger.Config(
- minTimeIntervalBetweenSamplesMillis,
- samplingInterval,
- /*samplingIntervals=*/ new SparseIntArray()));
- logger.setLastPushTimeMillisLocked(SystemClock.elapsedRealtime());
-
- // Makes sure sample will be logged if it is not too close to previous sample.
- assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isTrue();
- assertThat(logger.createExtraStatsLocked(testPackageName,
- CallStats.CALL_TYPE_PUT_DOCUMENT).mSkippedSampleCount).isEqualTo(0);
- }
-
/** Makes sure the caching works while getting the UID for calling package. */
@Test
public void testGetPackageUidAsUser() throws Exception {
@@ -290,43 +154,52 @@
PlatformLogger logger = new PlatformLogger(
mContext,
mContext.getUser(),
- new PlatformLogger.Config(
- TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- TEST_DEFAULT_SAMPLING_INTERVAL,
- /*samplingIntervals=*/ new SparseIntArray()));
- mMockPackageManager.mockGetPackageUidAsUser(testPackageName, mContext.getUserId(), testUid);
+ AppSearchConfig.create(DIRECT_EXECUTOR));
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(testPackageName, /*flags=*/0)).thenReturn(testUid);
- //
// First time, no cache
- //
PlatformLogger.ExtraStats extraStats = logger.createExtraStatsLocked(testPackageName,
CallStats.CALL_TYPE_PUT_DOCUMENT);
-
- verify(mMockPackageManager.getMockPackageManager(), times(1)).getPackageUidAsUser(
- eq(testPackageName), /*userId=*/ anyInt());
+ verify(mockPackageManager, times(1))
+ .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
assertThat(extraStats.mPackageUid).isEqualTo(testUid);
- //
// Second time, we have cache
- //
extraStats = logger.createExtraStatsLocked(testPackageName,
CallStats.CALL_TYPE_PUT_DOCUMENT);
// Count is still one since we will use the cache
- verify(mMockPackageManager.getMockPackageManager(), times(1)).getPackageUidAsUser(
- eq(testPackageName), /*userId=*/ anyInt());
+ verify(mockPackageManager, times(1))
+ .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
assertThat(extraStats.mPackageUid).isEqualTo(testUid);
- //
// Remove the cache and try again
- //
assertThat(logger.removeCachedUidForPackage(testPackageName)).isEqualTo(testUid);
extraStats = logger.createExtraStatsLocked(testPackageName,
CallStats.CALL_TYPE_PUT_DOCUMENT);
// count increased by 1 since cache is cleared
- verify(mMockPackageManager.getMockPackageManager(), times(2)).getPackageUidAsUser(
- eq(testPackageName), /*userId=*/ anyInt());
+ verify(mockPackageManager, times(2))
+ .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
assertThat(extraStats.mPackageUid).isEqualTo(testUid);
}
+
+ private static int calculateHashCodeMd5withBigInteger(@NonNull String str)
+ throws NoSuchAlgorithmException {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(str.getBytes(StandardCharsets.UTF_8));
+ byte[] digest = md.digest();
+ return new BigInteger(digest).intValue();
+ }
+
+ @NonNull
+ private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+ PackageManager pm = mMockPackageManagers.get(user);
+ if (pm == null) {
+ pm = Mockito.mock(PackageManager.class);
+ mMockPackageManagers.put(user, pm);
+ }
+ return pm;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index 6f0c8e1..aec70f4 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS;
import static junit.framework.Assert.assertEquals;
@@ -234,6 +236,27 @@
eq(mReceiver),
eq(TEST_OP_PACKAGE_NAME),
eq(promptInfo));
+ verify(mReceiver).onError(eq(TYPE_NONE), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
+ }
+
+ @Test
+ public void testAuthenticate_missingRequiredParam() throws Exception {
+ mAuthService = new AuthService(mContext, mInjector);
+ mAuthService.onStart();
+
+ final PromptInfo promptInfo = new PromptInfo();
+ final long sessionId = 0;
+ final int userId = 0;
+
+ mAuthService.mImpl.authenticate(
+ null /* token */,
+ sessionId,
+ userId,
+ mReceiver,
+ TEST_OP_PACKAGE_NAME,
+ promptInfo);
+ waitForIdle();
+ verify(mReceiver).onError(eq(TYPE_NONE), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
}
@Test
@@ -259,7 +282,6 @@
eq(authenticators));
}
-
@Test
public void testHasEnrolledBiometrics_callsBiometricServiceHasEnrolledBiometrics() throws
Exception {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
index 4afb7dd..2892bf5 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -18,6 +18,7 @@
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_NEGATIVE;
import static com.android.server.biometrics.BiometricServiceStateProto.*;
@@ -38,7 +39,6 @@
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustManager;
import android.content.Context;
-import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.IBiometricAuthenticator;
@@ -67,6 +67,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
+import java.util.function.Consumer;
@Presubmit
@SmallTest
@@ -245,9 +246,6 @@
assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
assertEquals(BiometricSensor.STATE_COOKIE_RETURNED,
session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getSensorState());
- session.onErrorReceived(fingerprintSensorId,
- session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getCookie(),
- BiometricConstants.BIOMETRIC_ERROR_VENDOR, 0 /* vendorCode */);
session.onStartFingerprint();
}
assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
@@ -258,6 +256,21 @@
@Test
public void testCancelAuthentication_whenStateAuthCalled_invokesCancel()
throws RemoteException {
+ testInvokesCancel(session -> session.onCancelAuthSession(false /* force */));
+ }
+
+ @Test
+ public void testCancelAuthentication_whenStateAuthForcedCalled_invokesCancel()
+ throws RemoteException {
+ testInvokesCancel(session -> session.onCancelAuthSession(true /* force */));
+ }
+
+ @Test
+ public void testCancelAuthentication_whenDialogDismissed() throws RemoteException {
+ testInvokesCancel(session -> session.onDialogDismissed(DISMISSED_REASON_NEGATIVE, null));
+ }
+
+ private void testInvokesCancel(Consumer<AuthSession> sessionConsumer) throws RemoteException {
final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
@@ -269,7 +282,8 @@
session.goToInitialState();
assertEquals(STATE_AUTH_CALLED, session.getState());
- session.onCancelAuthSession(false /* force */);
+
+ sessionConsumer.accept(session);
verify(faceAuthenticator).cancelAuthenticationFromService(eq(mToken), eq(TEST_PACKAGE));
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index ae836ce..7c7afb7 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -1036,7 +1036,7 @@
}
@Test
- public void testDismissedReasonNegative_whilePaused_doesntInvokeHalCancel() throws Exception {
+ public void testDismissedReasonNegative_whilePaused_invokeHalCancel() throws Exception {
setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */, null /* authenticators */);
@@ -1050,14 +1050,12 @@
BiometricPrompt.DISMISSED_REASON_NEGATIVE, null /* credentialAttestation */);
waitForIdle();
- verify(mBiometricService.mSensors.get(0).impl,
- never()).cancelAuthenticationFromService(
- any(),
- any());
+ verify(mBiometricService.mSensors.get(0).impl)
+ .cancelAuthenticationFromService(any(), any());
}
@Test
- public void testDismissedReasonUserCancel_whilePaused_doesntInvokeHalCancel() throws
+ public void testDismissedReasonUserCancel_whilePaused_invokesHalCancel() throws
Exception {
setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
@@ -1072,10 +1070,8 @@
BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
waitForIdle();
- verify(mBiometricService.mSensors.get(0).impl,
- never()).cancelAuthenticationFromService(
- any(),
- any());
+ verify(mBiometricService.mSensors.get(0).impl)
+ .cancelAuthenticationFromService(any(), any());
}
@Test
@@ -1091,11 +1087,8 @@
BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
waitForIdle();
- // doesn't send cancel to HAL
- verify(mBiometricService.mSensors.get(0).impl,
- never()).cancelAuthenticationFromService(
- any(),
- any());
+ verify(mBiometricService.mSensors.get(0).impl)
+ .cancelAuthenticationFromService(any(), any());
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_FACE),
eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
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 654d9fc..5447a58 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -15,6 +15,9 @@
*/
package com.android.server.devicepolicy;
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_DEFAULT;
+import static android.app.AppOpsManager.OP_ACTIVATE_VPN;
import static android.app.Notification.EXTRA_TEXT;
import static android.app.Notification.EXTRA_TITLE;
import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
@@ -6521,6 +6524,8 @@
when(getServices().settings.settingsSecureGetIntForUser(
Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
0, CALLER_USER_HANDLE)).thenReturn(1);
+ mContext.permissions.add(permission.INTERACT_ACROSS_USERS);
+
assertThat(dpm.isPackageAllowedToAccessCalendar("TEST_PACKAGE")).isFalse();
}
@@ -6532,6 +6537,8 @@
when(getServices().settings.settingsSecureGetIntForUser(
Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
0, CALLER_USER_HANDLE)).thenReturn(0);
+ mContext.permissions.add(permission.INTERACT_ACROSS_USERS);
+
assertThat(dpm.isPackageAllowedToAccessCalendar(testPackage)).isFalse();
}
@@ -6543,6 +6550,33 @@
when(getServices().settings.settingsSecureGetIntForUser(
Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
0, CALLER_USER_HANDLE)).thenReturn(1);
+ mContext.permissions.add(permission.INTERACT_ACROSS_USERS);
+
+ assertThat(dpm.isPackageAllowedToAccessCalendar(testPackage)).isTrue();
+ }
+
+ @Test
+ public void testIsPackageAllowedToAccessCalendar_requiresPermission() {
+ final String testPackage = "TEST_PACKAGE";
+
+ assertExpectException(SecurityException.class, /* messageRegex= */ null,
+ () -> dpm.isPackageAllowedToAccessCalendar(testPackage));
+ }
+
+ @Test
+ public void testIsPackageAllowedToAccessCalendar_samePackageAndSameUser_noPermissionRequired()
+ throws Exception {
+ final String testPackage = "TEST_PACKAGE";
+ setAsProfileOwner(admin1);
+ dpm.setCrossProfileCalendarPackages(admin1, null);
+ when(getServices().settings.settingsSecureGetIntForUser(
+ Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
+ 0, CALLER_USER_HANDLE)).thenReturn(1);
+ doReturn(mContext.binder.callingUid)
+ .when(getServices().packageManager).getPackageUidAsUser(
+ eq(testPackage),
+ anyInt());
+
assertThat(dpm.isPackageAllowedToAccessCalendar(testPackage)).isTrue();
}
@@ -7436,6 +7470,101 @@
assertThrows(SecurityException.class, () -> dpm.setRecommendedGlobalProxy(admin1, null));
}
+ @Test
+ public void testSetAlwaysOnVpnPackage_clearsAdminVpn() throws Exception {
+ setDeviceOwner();
+
+ when(getServices().vpnManager
+ .setAlwaysOnVpnPackageForUser(anyInt(), any(), anyBoolean(), any()))
+ .thenReturn(true);
+
+ // Set VPN package to admin package.
+ dpm.setAlwaysOnVpnPackage(admin1, admin1.getPackageName(), false, null);
+
+ verify(getServices().vpnManager).setAlwaysOnVpnPackageForUser(
+ UserHandle.USER_SYSTEM, admin1.getPackageName(), false, null);
+
+ // Clear VPN package.
+ dpm.setAlwaysOnVpnPackage(admin1, null, false, null);
+
+ // Change should be propagated to VpnManager
+ verify(getServices().vpnManager).setAlwaysOnVpnPackageForUser(
+ UserHandle.USER_SYSTEM, null, false, null);
+ // The package should lose authorization to start VPN.
+ verify(getServices().appOpsManager).setMode(OP_ACTIVATE_VPN,
+ DpmMockContext.CALLER_SYSTEM_USER_UID, admin1.getPackageName(), MODE_DEFAULT);
+ }
+
+ @Test
+ public void testSetAlwaysOnVpnPackage_doesntKillUserVpn() throws Exception {
+ setDeviceOwner();
+
+ when(getServices().vpnManager
+ .setAlwaysOnVpnPackageForUser(anyInt(), any(), anyBoolean(), any()))
+ .thenReturn(true);
+
+ // this time it shouldn't go into VpnManager anymore.
+ dpm.setAlwaysOnVpnPackage(admin1, null, false, null);
+
+ verifyNoMoreInteractions(getServices().vpnManager);
+ verifyNoMoreInteractions(getServices().appOpsManager);
+ }
+
+ @Test
+ public void testDisallowConfigVpn_clearsUserVpn() throws Exception {
+ final String userVpnPackage = "org.some.vpn.servcie";
+ final int userVpnUid = 20374;
+
+ setDeviceOwner();
+
+ setupVpnAuthorization(userVpnPackage, userVpnUid);
+
+ simulateRestrictionAdded(UserManager.DISALLOW_CONFIG_VPN);
+
+ verify(getServices().vpnManager).setAlwaysOnVpnPackageForUser(
+ UserHandle.USER_SYSTEM, null, false, null);
+ verify(getServices().appOpsManager).setMode(OP_ACTIVATE_VPN,
+ userVpnUid, userVpnPackage, MODE_DEFAULT);
+ }
+
+ @Test
+ public void testDisallowConfigVpn_doesntKillAdminVpn() throws Exception {
+ setDeviceOwner();
+
+ when(getServices().vpnManager
+ .setAlwaysOnVpnPackageForUser(anyInt(), any(), anyBoolean(), any()))
+ .thenReturn(true);
+
+ // Set VPN package to admin package.
+ dpm.setAlwaysOnVpnPackage(admin1, admin1.getPackageName(), false, null);
+ setupVpnAuthorization(admin1.getPackageName(), DpmMockContext.CALLER_SYSTEM_USER_UID);
+ clearInvocations(getServices().vpnManager);
+
+ simulateRestrictionAdded(UserManager.DISALLOW_CONFIG_VPN);
+
+ // Admin-set package should remain always-on and should retain its authorization.
+ verifyNoMoreInteractions(getServices().vpnManager);
+ verify(getServices().appOpsManager, never()).setMode(OP_ACTIVATE_VPN,
+ DpmMockContext.CALLER_SYSTEM_USER_UID, admin1.getPackageName(), MODE_DEFAULT);
+ }
+
+ private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) {
+ final AppOpsManager.PackageOps vpnOp = new AppOpsManager.PackageOps(userVpnPackage,
+ userVpnUid, List.of(new AppOpsManager.OpEntry(
+ OP_ACTIVATE_VPN, MODE_ALLOWED, Collections.emptyMap())));
+ when(getServices().appOpsManager.getPackagesForOps(any(int[].class)))
+ .thenReturn(List.of(vpnOp));
+ }
+
+ private void simulateRestrictionAdded(String restriction) {
+ RestrictionsListener listener = new RestrictionsListener(
+ mServiceContext, getServices().userManagerInternal, dpms);
+
+ final Bundle newRestrictions = new Bundle();
+ newRestrictions.putBoolean(restriction, true);
+ listener.onUserRestrictionsChanged(UserHandle.USER_SYSTEM, newRestrictions, new Bundle());
+ }
+
private void setUserUnlocked(int userHandle, boolean unlocked) {
when(getServices().userManager.isUserUnlocked(eq(userHandle))).thenReturn(unlocked);
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 2e00468..d10419d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -230,6 +230,8 @@
return mMockSystemServices.appOpsManager;
case Context.CROSS_PROFILE_APPS_SERVICE:
return mMockSystemServices.crossProfileApps;
+ case Context.VPN_MANAGEMENT_SERVICE:
+ return mMockSystemServices.vpnManager;
}
throw new UnsupportedOperationException();
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 9cc0572..8a2919d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -50,6 +50,7 @@
import android.net.ConnectivityManager;
import android.net.IIpConnectivityMetrics;
import android.net.Uri;
+import android.net.VpnManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.PowerManager;
@@ -123,6 +124,7 @@
public final PersistentDataBlockManagerInternal persistentDataBlockManagerInternal;
public final AppOpsManager appOpsManager;
public final UsbManager usbManager;
+ public final VpnManager vpnManager;
/** Note this is a partial mock, not a real mock. */
public final PackageManager packageManager;
public final BuildMock buildMock = new BuildMock();
@@ -169,6 +171,7 @@
persistentDataBlockManagerInternal = mock(PersistentDataBlockManagerInternal.class);
appOpsManager = mock(AppOpsManager.class);
usbManager = mock(UsbManager.class);
+ vpnManager = mock(VpnManager.class);
// Package manager is huge, so we use a partial mock instead.
packageManager = spy(realContext.getPackageManager());
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
index 24e226a..a8f24ce 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
@@ -19,6 +19,9 @@
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
+import static android.app.admin.DevicePolicyManager.REQUIRED_APP_MANAGED_DEVICE;
+import static android.app.admin.DevicePolicyManager.REQUIRED_APP_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.REQUIRED_APP_MANAGED_USER;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -31,13 +34,17 @@
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ModuleInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
+import android.os.Bundle;
import android.test.mock.MockPackageManager;
import android.view.inputmethod.InputMethodInfo;
+import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -51,8 +58,10 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -76,6 +85,8 @@
private FakePackageManager mPackageManager;
private String[] mSystemAppsWithLauncher;
+ private Set<String> mRegularMainlineModules = new HashSet<>();
+ private Map<String, String> mMainlineModuleToDeclaredMetadataMap = new HashMap<>();
private OverlayPackagesProvider mHelper;
@Before
@@ -168,7 +179,7 @@
setSystemAppsWithLauncher("app.a", "app.b");
setSystemInputMethods("app.a");
- verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_PROFILE, "app.a", "app.b");
+ verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_PROFILE, "app.b");
}
@Test
@@ -257,6 +268,93 @@
R.array.vendor_disallowed_apps_managed_profile);
}
+ @Test
+ public void testGetNonRequiredApps_mainlineModules_managedProfile_works() {
+ setupApexModulesWithManagedProfile("package1");
+ setupRegularModulesWithManagedProfile("package2");
+ setSystemAppsWithLauncher("package1", "package2", "package3");
+
+ verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_PROFILE, "package3");
+ }
+
+ @Test
+ public void testGetNonRequiredApps_mainlineModules_managedDevice_works() {
+ setupApexModulesWithManagedDevice("package1");
+ setupRegularModulesWithManagedDevice("package2");
+ setSystemAppsWithLauncher("package1", "package2", "package3");
+
+ verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_DEVICE, "package3");
+ }
+
+ @Test
+ public void testGetNonRequiredApps_mainlineModules_managedUser_works() {
+ setupApexModulesWithManagedUser("package1");
+ setupRegularModulesWithManagedUser("package2");
+ setSystemAppsWithLauncher("package1", "package2", "package3");
+
+ verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_USER, "package3");
+ }
+
+ @Test
+ public void testGetNonRequiredApps_mainlineModules_noMetadata_works() {
+ setupApexModulesWithNoMetadata("package1");
+ setupRegularModulesWithNoMetadata("package2");
+ setSystemAppsWithLauncher("package1", "package2", "package3");
+
+ verifyAppsAreNonRequired(
+ ACTION_PROVISION_MANAGED_PROFILE, "package1", "package2", "package3");
+ }
+
+ private void setupRegularModulesWithManagedUser(String... regularModules) {
+ setupRegularModulesWithMetadata(regularModules, REQUIRED_APP_MANAGED_USER);
+ }
+
+ private void setupRegularModulesWithManagedDevice(String... regularModules) {
+ setupRegularModulesWithMetadata(regularModules, REQUIRED_APP_MANAGED_DEVICE);
+ }
+
+ private void setupRegularModulesWithManagedProfile(String... regularModules) {
+ setupRegularModulesWithMetadata(regularModules, REQUIRED_APP_MANAGED_PROFILE);
+ }
+
+ private void setupRegularModulesWithNoMetadata(String... regularModules) {
+ mRegularMainlineModules.addAll(Arrays.asList(regularModules));
+ }
+
+ private void setupRegularModulesWithMetadata(String[] regularModules, String metadataKey) {
+ for (String regularModule : regularModules) {
+ mRegularMainlineModules.add(regularModule);
+ mMainlineModuleToDeclaredMetadataMap.put(regularModule, metadataKey);
+ }
+ }
+
+ private void setupApexModulesWithManagedUser(String... apexPackageNames) {
+ setupApexModulesWithMetadata(apexPackageNames, REQUIRED_APP_MANAGED_USER);
+ }
+
+ private void setupApexModulesWithManagedDevice(String... apexPackageNames) {
+ setupApexModulesWithMetadata(apexPackageNames, REQUIRED_APP_MANAGED_DEVICE);
+ }
+
+ private void setupApexModulesWithManagedProfile(String... apexPackageNames) {
+ setupApexModulesWithMetadata(apexPackageNames, REQUIRED_APP_MANAGED_PROFILE);
+ }
+
+ private void setupApexModulesWithNoMetadata(String... apexPackageNames) {
+ for (String apexPackageName : apexPackageNames) {
+ when(mInjector.getActiveApexPackageNameContainingPackage(eq(apexPackageName)))
+ .thenReturn("apex");
+ }
+ }
+
+ private void setupApexModulesWithMetadata(String[] apexPackageNames, String metadataKey) {
+ for (String apexPackageName : apexPackageNames) {
+ when(mInjector.getActiveApexPackageNameContainingPackage(eq(apexPackageName)))
+ .thenReturn("apex");
+ mMainlineModuleToDeclaredMetadataMap.put(apexPackageName, metadataKey);
+ }
+ }
+
private ArrayList<String> getStringArrayInRealResources(int id) {
return new ArrayList<>(Arrays.asList(mRealResources.getStringArray(id)));
}
@@ -383,5 +481,29 @@
}
return result;
}
+
+ @NonNull
+ @Override
+ public PackageInfo getPackageInfo(String packageName, int flags) {
+ final PackageInfo packageInfo = new PackageInfo();
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.metaData = new Bundle();
+ if (mMainlineModuleToDeclaredMetadataMap.containsKey(packageName)) {
+ applicationInfo.metaData.putBoolean(
+ mMainlineModuleToDeclaredMetadataMap.get(packageName), true);
+ }
+ packageInfo.applicationInfo = applicationInfo;
+ return packageInfo;
+ }
+
+ @NonNull
+ @Override
+ public ModuleInfo getModuleInfo(@NonNull String packageName, int flags)
+ throws NameNotFoundException {
+ if (!mRegularMainlineModules.contains(packageName)) {
+ throw new NameNotFoundException("package does not exist");
+ }
+ return new ModuleInfo().setName(packageName);
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index c506485..2a4896a 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -134,6 +134,8 @@
private static final String NOTIFICATION_CHANNEL_ID = "test : sc";
private static final String PARENT_NOTIFICATION_CHANNEL_ID = "test";
private static final long MILLIS_PER_MINUTE = 1000L * 60L;
+ private static final String GENERIC_KEY = "key";
+ private static final String CUSTOM_KEY = "custom";
@Mock
private Context mContext;
@@ -158,7 +160,11 @@
@Mock
private JobScheduler mJobScheduler;
@Mock
- private StatusBarNotification mStatusBarNotification;
+ private StatusBarNotification mGenericSbn;
+ @Mock
+ private StatusBarNotification mConvoSbn;
+ @Mock
+ private NotificationListenerService.RankingMap mRankingMap;
@Mock
private Notification mNotification;
@Mock
@@ -202,8 +208,6 @@
mParentNotificationChannel = new NotificationChannel(
PARENT_NOTIFICATION_CHANNEL_ID, "test channel",
NotificationManager.IMPORTANCE_DEFAULT);
- when(mNotificationManagerInternal.getNotificationChannel(anyString(), anyInt(),
- anyString())).thenReturn(mParentNotificationChannel);
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
@@ -246,16 +250,26 @@
when(mPackageManager.getPackageUidAsUser(TEST_PKG_NAME, USER_ID_PRIMARY))
.thenReturn(TEST_PKG_UID);
- when(mStatusBarNotification.getNotification()).thenReturn(mNotification);
- when(mStatusBarNotification.getPackageName()).thenReturn(TEST_PKG_NAME);
- when(mStatusBarNotification.getUser()).thenReturn(UserHandle.of(USER_ID_PRIMARY));
- when(mStatusBarNotification.getPostTime()).thenReturn(System.currentTimeMillis());
- when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID);
- when(mNotification.getChannelId()).thenReturn(PARENT_NOTIFICATION_CHANNEL_ID);
-
mNotificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "test channel", NotificationManager.IMPORTANCE_DEFAULT);
- mNotificationChannel.setConversationId("test", TEST_SHORTCUT_ID);
+ mNotificationChannel.setConversationId(PARENT_NOTIFICATION_CHANNEL_ID, TEST_SHORTCUT_ID);
+ when(mNotificationManagerInternal.getNotificationChannel(anyString(), anyInt(),
+ eq(mNotificationChannel.getId()))).thenReturn(mNotificationChannel);
+ when(mNotificationManagerInternal.getNotificationChannel(anyString(), anyInt(),
+ eq(mParentNotificationChannel.getId()))).thenReturn(mParentNotificationChannel);
+
+ when(mGenericSbn.getKey()).thenReturn(GENERIC_KEY);
+ when(mGenericSbn.getNotification()).thenReturn(mNotification);
+ when(mGenericSbn.getPackageName()).thenReturn(TEST_PKG_NAME);
+ when(mGenericSbn.getUser()).thenReturn(UserHandle.of(USER_ID_PRIMARY));
+ when(mGenericSbn.getPostTime()).thenReturn(System.currentTimeMillis());
+ when(mConvoSbn.getKey()).thenReturn(CUSTOM_KEY);
+ when(mConvoSbn.getNotification()).thenReturn(mNotification);
+ when(mConvoSbn.getPackageName()).thenReturn(TEST_PKG_NAME);
+ when(mConvoSbn.getUser()).thenReturn(UserHandle.of(USER_ID_PRIMARY));
+ when(mConvoSbn.getPostTime()).thenReturn(System.currentTimeMillis());
+
+ when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID);
mCancellationSignal = new CancellationSignal();
@@ -449,10 +463,7 @@
buildPerson());
mDataManager.addOrUpdateConversationInfo(shortcut);
- NotificationListenerService listenerService =
- mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
-
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
List<Range<Long>> activeNotificationOpenTimeSlots = getActiveSlotsForTestShortcut(
Event.NOTIFICATION_EVENT_TYPES);
@@ -471,7 +482,7 @@
NotificationListenerService listenerService =
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationRemoved(mStatusBarNotification, null,
+ listenerService.onNotificationRemoved(mGenericSbn, null,
NotificationListenerService.REASON_CLICK);
List<Range<Long>> activeNotificationOpenTimeSlots = getActiveSlotsForTestShortcut(
@@ -495,20 +506,20 @@
shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
mDataManager.addOrUpdateConversationInfo(shortcut);
when(mNotification.getShortcutId()).thenReturn(shortcutId);
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
}
// Post another notification for the last conversation.
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
// Removing one of the two notifications does not un-cache the shortcut.
- listenerService.onNotificationRemoved(mStatusBarNotification, null,
+ listenerService.onNotificationRemoved(mGenericSbn, null,
NotificationListenerService.REASON_CANCEL);
verify(mShortcutServiceInternal, never()).uncacheShortcuts(
anyInt(), any(), anyString(), any(), anyInt(), anyInt());
// Removing the second notification un-caches the shortcut.
- listenerService.onNotificationRemoved(mStatusBarNotification, null,
+ listenerService.onNotificationRemoved(mGenericSbn, null,
NotificationListenerService.REASON_CANCEL_ALL);
verify(mShortcutServiceInternal).uncacheShortcuts(
anyInt(), any(), eq(TEST_PKG_NAME), anyList(), eq(USER_ID_PRIMARY),
@@ -526,7 +537,7 @@
NotificationListenerService listenerService =
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
mDataManager.addOrUpdateConversationInfo(shortcut);
@@ -626,19 +637,13 @@
buildPerson());
mDataManager.addOrUpdateConversationInfo(shortcut);
- NotificationListenerService listenerService =
- mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
-
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendConvoNotification();
shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
mDataManager.addOrUpdateConversationInfo(shortcut);
assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
TEST_SHORTCUT_ID)).isNotNull();
- listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
- mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
-
ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
TEST_SHORTCUT_ID);
assertThat(result).isNotNull();
@@ -661,9 +666,7 @@
assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
TEST_SHORTCUT_ID + "1")).isNull();
- NotificationListenerService listenerService =
- mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendConvoNotification();
ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build();
mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs);
@@ -673,15 +676,51 @@
assertEquals(shortcut.getId(), result.getShortcutInfo().getId());
assertEquals(1, result.getShortcutInfo().getPersons().length);
assertEquals(CONTACT_URI, result.getShortcutInfo().getPersons()[0].getUri());
+ assertEquals(mNotificationChannel.getId(), result.getNotificationChannel().getId());
assertEquals(mParentNotificationChannel.getId(),
- result.getParentNotificationChannel().getId());
- assertEquals(mStatusBarNotification.getPostTime(), result.getLastEventTimestamp());
+ result.getNotificationChannel().getParentChannelId());
+ assertEquals(mConvoSbn.getPostTime(), result.getLastEventTimestamp());
assertTrue(result.hasActiveNotifications());
assertFalse(result.hasBirthdayToday());
assertThat(result.getStatuses()).containsExactly(cs);
}
@Test
+ public void testOnNotificationChannelModified() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+ assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
+ TEST_SHORTCUT_ID)).isNull();
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ shortcut.setCached(ShortcutInfo.FLAG_PINNED);
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+
+ sendConvoNotification();
+
+ ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
+ TEST_SHORTCUT_ID);
+ assertFalse(result.getNotificationChannel().canBubble());
+
+ NotificationChannel updated = new NotificationChannel(mNotificationChannel.getId(),
+ mNotificationChannel.getDescription(), mNotificationChannel.getImportance());
+ updated.setConversationId(mNotificationChannel.getParentChannelId(),
+ mNotificationChannel.getConversationId());
+ updated.setAllowBubbles(true);
+ NotificationListenerService listenerService =
+ mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+ listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
+ updated, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
+
+ ConversationInfo ci = mDataManager.getConversationInfo(TEST_PKG_NAME, USER_ID_PRIMARY,
+ TEST_SHORTCUT_ID);
+ assertThat(ci).isNotNull();
+ assertEquals(mNotificationChannel.getId(), ci.getNotificationChannelId());
+ assertEquals(mParentNotificationChannel.getId(), ci.getParentNotificationChannelId());
+ assertTrue(ci.isBubbled());
+ }
+
+ @Test
public void testGetConversation_demoted() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
@@ -713,11 +752,8 @@
shortcut.setCached(ShortcutInfo.FLAG_PINNED);
mDataManager.addOrUpdateConversationInfo(shortcut);
- NotificationListenerService listenerService =
- mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationPosted(mStatusBarNotification);
- ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
- TEST_SHORTCUT_ID);
+ sendGenericNotification();
+ mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID);
verify(mShortcutServiceInternal).getShortcuts(
anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(),
@@ -1085,7 +1121,7 @@
shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
mDataManager.addOrUpdateConversationInfo(shortcut);
when(mNotification.getShortcutId()).thenReturn(shortcutId);
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
}
mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
@@ -1107,9 +1143,9 @@
shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
mDataManager.addOrUpdateConversationInfo(shortcut);
when(mNotification.getShortcutId()).thenReturn(shortcutId);
- when(mStatusBarNotification.getPostTime()).thenReturn(100L + i);
- listenerService.onNotificationPosted(mStatusBarNotification);
- listenerService.onNotificationRemoved(mStatusBarNotification, null,
+ when(mGenericSbn.getPostTime()).thenReturn(100L + i);
+ sendGenericNotification();
+ listenerService.onNotificationRemoved(mGenericSbn, null,
NotificationListenerService.REASON_CANCEL);
}
@@ -1162,9 +1198,7 @@
shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
mDataManager.addOrUpdateConversationInfo(shortcut);
- NotificationListenerService listenerService =
- mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
List<ConversationChannel> result = mDataManager.getRecentConversations(USER_ID_PRIMARY);
assertEquals(1, result.size());
@@ -1172,8 +1206,9 @@
assertEquals(1, result.get(0).getShortcutInfo().getPersons().length);
assertEquals(CONTACT_URI, result.get(0).getShortcutInfo().getPersons()[0].getUri());
assertEquals(mParentNotificationChannel.getId(),
- result.get(0).getParentNotificationChannel().getId());
- assertEquals(mStatusBarNotification.getPostTime(), result.get(0).getLastEventTimestamp());
+ result.get(0).getNotificationChannel().getId());
+ assertEquals(null, result.get(0).getNotificationChannel().getParentChannelId());
+ assertEquals(mGenericSbn.getPostTime(), result.get(0).getLastEventTimestamp());
assertTrue(result.get(0).hasActiveNotifications());
}
@@ -1186,11 +1221,9 @@
shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
mDataManager.addOrUpdateConversationInfo(shortcut);
- NotificationListenerService listenerService =
- mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
- List<ConversationChannel> result = mDataManager.getRecentConversations(USER_ID_PRIMARY);
+ mDataManager.getRecentConversations(USER_ID_PRIMARY);
verify(mShortcutServiceInternal).getShortcuts(
anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(),
@@ -1211,8 +1244,8 @@
NotificationListenerService listenerService =
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID);
- listenerService.onNotificationPosted(mStatusBarNotification);
- listenerService.onNotificationRemoved(mStatusBarNotification, null,
+ sendGenericNotification();
+ listenerService.onNotificationRemoved(mGenericSbn, null,
NotificationListenerService.REASON_CLICK);
mDataManager.pruneOldRecentConversations(USER_ID_PRIMARY,
@@ -1231,11 +1264,9 @@
buildPerson());
mDataManager.addOrUpdateConversationInfo(shortcut);
- NotificationListenerService listenerService =
- mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
- assertEquals(mStatusBarNotification.getPostTime(),
+ assertEquals(mGenericSbn.getPostTime(),
mDataManager.getLastInteraction(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID));
assertEquals(0L,
mDataManager.getLastInteraction("not_test_pkg", USER_ID_PRIMARY, TEST_SHORTCUT_ID));
@@ -1375,9 +1406,7 @@
TEST_SHORTCUT_ID, buildPerson());
mDataManager.addOrUpdateConversationInfo(shortcut);
- NotificationListenerService listenerService =
- mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
List<ConversationChannel> result = mDataManager.getRecentConversations(USER_ID_PRIMARY);
assertTrue(result.isEmpty());
@@ -1395,7 +1424,7 @@
// Post a notification and customize the notification settings.
NotificationListenerService listenerService =
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
@@ -1414,7 +1443,7 @@
NotificationListenerService listenerService =
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
// posting updates the last interaction time, so delay before deletion
try {
Thread.sleep(500);
@@ -1422,7 +1451,7 @@
e.printStackTrace();
}
long approxDeletionTime = System.currentTimeMillis();
- listenerService.onNotificationRemoved(mStatusBarNotification, null,
+ listenerService.onNotificationRemoved(mGenericSbn, null,
NotificationListenerService.REASON_CANCEL);
ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
@@ -1442,8 +1471,8 @@
NotificationListenerService listenerService =
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
- listenerService.onNotificationPosted(mStatusBarNotification);
- listenerService.onNotificationRemoved(mStatusBarNotification, null,
+ sendGenericNotification();
+ listenerService.onNotificationRemoved(mGenericSbn, null,
NotificationListenerService.REASON_CANCEL);
mDataManager.removeRecentConversation(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
USER_ID_PRIMARY);
@@ -1472,14 +1501,14 @@
// Post a notification and then dismiss it for conversation #1.
when(mNotification.getShortcutId()).thenReturn("1");
- listenerService.onNotificationPosted(mStatusBarNotification);
- listenerService.onNotificationRemoved(mStatusBarNotification, null,
+ sendGenericNotification();
+ listenerService.onNotificationRemoved(mGenericSbn, null,
NotificationListenerService.REASON_CANCEL);
// Post a notification for conversation #2, but don't dismiss it. Its shortcut won't be
// uncached when removeAllRecentConversations() is called.
when(mNotification.getShortcutId()).thenReturn("2");
- listenerService.onNotificationPosted(mStatusBarNotification);
+ sendGenericNotification();
mDataManager.removeAllRecentConversations(USER_ID_PRIMARY);
@@ -1562,6 +1591,58 @@
return (queryFlags & flag) != 0;
}
+ // "Sends" a notification to a non-customized notification channel - the notification channel
+ // is something generic like "messages" and the notification has a shortcut id
+ private void sendGenericNotification() {
+ when(mNotification.getChannelId()).thenReturn(PARENT_NOTIFICATION_CHANNEL_ID);
+ doAnswer(invocationOnMock -> {
+ NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
+ invocationOnMock.getArguments()[1];
+ ranking.populate(
+ (String) invocationOnMock.getArguments()[0],
+ 0,
+ false,
+ 0,
+ 0,
+ mParentNotificationChannel.getImportance(),
+ null, null,
+ mParentNotificationChannel, null, null, true, 0, false, -1, false, null, null,
+ false, false, false, null, 0, false);
+ return true;
+ }).when(mRankingMap).getRanking(eq(GENERIC_KEY),
+ any(NotificationListenerService.Ranking.class));
+ NotificationListenerService listenerService =
+ mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+ listenerService.onNotificationPosted(mGenericSbn, mRankingMap);
+ }
+
+ // "Sends" a notification to a customized notification channel - the notification channel
+ // is specific to a person, and the channel has a convo id matching the notification's shortcut
+ // and the channel has a parent channel id
+ private void sendConvoNotification() {
+ when(mNotification.getChannelId()).thenReturn(NOTIFICATION_CHANNEL_ID);
+ doAnswer(invocationOnMock -> {
+ NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
+ invocationOnMock.getArguments()[1];
+ ranking.populate(
+ (String) invocationOnMock.getArguments()[0],
+ 0,
+ false,
+ 0,
+ 0,
+ mNotificationChannel.getImportance(),
+ null, null,
+ mNotificationChannel, null, null, true, 0, false, -1, false, null, null, false,
+ false, false, null, 0, false);
+ return true;
+ }).when(mRankingMap).getRanking(eq(CUSTOM_KEY),
+ any(NotificationListenerService.Ranking.class));
+
+ NotificationListenerService listenerService =
+ mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+ listenerService.onNotificationPosted(mConvoSbn, mRankingMap);
+ }
+
private class TestContactsQueryHelper extends ContactsQueryHelper {
private Uri mContactUri;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 9b25d0d..4e350b6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -20,6 +20,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
@@ -29,6 +30,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.expectThrows;
import android.apex.ApexInfo;
import android.apex.ApexSessionInfo;
@@ -84,7 +86,7 @@
@Test
public void testGetPackageInfo_setFlagsMatchActivePackage() throws RemoteException {
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
final PackageInfo activePkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG,
@@ -101,7 +103,7 @@
@Test
public void testGetPackageInfo_setFlagsMatchFactoryPackage() throws RemoteException {
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
PackageInfo factoryPkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG,
@@ -118,7 +120,7 @@
@Test
public void testGetPackageInfo_setFlagsNone() throws RemoteException {
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
@@ -127,7 +129,7 @@
@Test
public void testGetActivePackages() throws RemoteException {
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, true));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, true));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
@@ -136,7 +138,7 @@
@Test
public void testGetActivePackages_noneActivePackages() throws RemoteException {
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
@@ -145,7 +147,7 @@
@Test
public void testGetFactoryPackages() throws RemoteException {
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
@@ -154,7 +156,7 @@
@Test
public void testGetFactoryPackages_noneFactoryPackages() throws RemoteException {
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
@@ -163,7 +165,7 @@
@Test
public void testGetInactivePackages() throws RemoteException {
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
@@ -172,7 +174,7 @@
@Test
public void testGetInactivePackages_noneInactivePackages() throws RemoteException {
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
@@ -181,7 +183,7 @@
@Test
public void testIsApexPackage() throws RemoteException {
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
@@ -276,11 +278,11 @@
@Test
public void testReportErrorWithApkInApex() throws RemoteException {
- when(mApexService.getActivePackages()).thenReturn(createApexInfo(true, true));
+ when(mApexService.getActivePackages()).thenReturn(createApexInfoForTestPkg(true, true));
final ApexManager.ActiveApexInfo activeApex = mApexManager.getActiveApexInfos().get(0);
assertThat(activeApex.apexModuleName).isEqualTo(TEST_APEX_PKG);
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, true));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, true));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
@@ -297,7 +299,7 @@
*/
@Test
public void testRegisterApkInApexDoesNotRegisterSimilarPrefix() throws RemoteException {
- when(mApexService.getActivePackages()).thenReturn(createApexInfo(true, true));
+ when(mApexService.getActivePackages()).thenReturn(createApexInfoForTestPkg(true, true));
final ApexManager.ActiveApexInfo activeApex = mApexManager.getActiveApexInfos().get(0);
assertThat(activeApex.apexModuleName).isEqualTo(TEST_APEX_PKG);
@@ -305,7 +307,7 @@
when(fakeApkInApex.getBaseApkPath()).thenReturn("/apex/" + TEST_APEX_PKG + "randomSuffix");
when(fakeApkInApex.getPackageName()).thenReturn("randomPackageName");
- when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, true));
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, true));
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
@@ -314,7 +316,112 @@
assertThat(mApexManager.getApksInApex(activeApex.apexModuleName)).isEmpty();
}
- private ApexInfo[] createApexInfo(boolean isActive, boolean isFactory) {
+ @Test
+ public void testInstallPackageFailsToInstallNewApex() throws Exception {
+ when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false));
+ mApexManager.scanApexPackagesTraced(mPackageParser2,
+ ParallelPackageParser.makeExecutorService());
+
+ File apex = extractResource("test.apex_rebootless_v1", "test.rebootless_apex_v1.apex");
+ PackageManagerException e = expectThrows(PackageManagerException.class,
+ () -> mApexManager.installPackage(apex, mPackageParser2));
+ assertThat(e).hasMessageThat().contains("It is forbidden to install new APEX packages");
+ }
+
+ @Test
+ public void testInstallPackageDowngrade() throws Exception {
+ File activeApex = extractResource("test.apex_rebootless_v2",
+ "test.rebootless_apex_v2.apex");
+ ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true,
+ /* isFactory= */ false, activeApex);
+ when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo});
+ mApexManager.scanApexPackagesTraced(mPackageParser2,
+ ParallelPackageParser.makeExecutorService());
+
+ File installedApex = extractResource("test.apex_rebootless_v1",
+ "test.rebootless_apex_v1.apex");
+ PackageManagerException e = expectThrows(PackageManagerException.class,
+ () -> mApexManager.installPackage(installedApex, mPackageParser2));
+ assertThat(e).hasMessageThat().contains(
+ "Downgrade of APEX package test.apex.rebootless is not allowed");
+ }
+
+ @Test
+ public void testInstallPackage() throws Exception {
+ ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true,
+ /* isFactory= */ false, extractResource("test.apex_rebootless_v1",
+ "test.rebootless_apex_v1.apex"));
+ when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo});
+ mApexManager.scanApexPackagesTraced(mPackageParser2,
+ ParallelPackageParser.makeExecutorService());
+
+ File finalApex = extractResource("test.rebootles_apex_v2", "test.rebootless_apex_v2.apex");
+ ApexInfo newApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true,
+ /* isFactory= */ false, finalApex);
+ when(mApexService.installAndActivatePackage(anyString())).thenReturn(newApexInfo);
+
+ File installedApex = extractResource("installed", "test.rebootless_apex_v2.apex");
+ mApexManager.installPackage(installedApex, mPackageParser2);
+
+ PackageInfo newInfo = mApexManager.getPackageInfo("test.apex.rebootless",
+ ApexManager.MATCH_ACTIVE_PACKAGE);
+ assertThat(newInfo.applicationInfo.sourceDir).isEqualTo(finalApex.getAbsolutePath());
+ assertThat(newInfo.applicationInfo.longVersionCode).isEqualTo(2);
+ }
+
+ @Test
+ public void testInstallPackageBinderCallFails() throws Exception {
+ ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true,
+ /* isFactory= */ false, extractResource("test.apex_rebootless_v1",
+ "test.rebootless_apex_v1.apex"));
+ when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo});
+ mApexManager.scanApexPackagesTraced(mPackageParser2,
+ ParallelPackageParser.makeExecutorService());
+
+ when(mApexService.installAndActivatePackage(anyString())).thenThrow(
+ new RuntimeException("install failed :("));
+
+ File installedApex = extractResource("test.apex_rebootless_v1",
+ "test.rebootless_apex_v1.apex");
+ assertThrows(PackageManagerException.class,
+ () -> mApexManager.installPackage(installedApex, mPackageParser2));
+ }
+
+ @Test
+ public void testInstallPackageSignedWithWrongCertificate() throws Exception {
+ File activeApex = extractResource("shim_v1", "com.android.apex.cts.shim.apex");
+ ApexInfo activeApexInfo = createApexInfo("com.android.apex.cts.shim", 1,
+ /* isActive= */ true, /* isFactory= */ false, activeApex);
+ when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo});
+ mApexManager.scanApexPackagesTraced(mPackageParser2,
+ ParallelPackageParser.makeExecutorService());
+
+ File installedApex = extractResource("shim_different_certificate",
+ "com.android.apex.cts.shim.v2_different_certificate.apex");
+ PackageManagerException e = expectThrows(PackageManagerException.class,
+ () -> mApexManager.installPackage(installedApex, mPackageParser2));
+ assertThat(e).hasMessageThat().contains("APK container signature of ");
+ assertThat(e).hasMessageThat().contains(
+ "is not compatible with currently installed on device");
+ }
+
+ @Test
+ public void testInstallPackageUnsignedApexContainer() throws Exception {
+ File activeApex = extractResource("shim_v1", "com.android.apex.cts.shim.apex");
+ ApexInfo activeApexInfo = createApexInfo("com.android.apex.cts.shim", 1,
+ /* isActive= */ true, /* isFactory= */ false, activeApex);
+ when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo});
+ mApexManager.scanApexPackagesTraced(mPackageParser2,
+ ParallelPackageParser.makeExecutorService());
+
+ File installedApex = extractResource("shim_unsigned_apk_container",
+ "com.android.apex.cts.shim.v2_unsigned_apk_container.apex");
+ PackageManagerException e = expectThrows(PackageManagerException.class,
+ () -> mApexManager.installPackage(installedApex, mPackageParser2));
+ assertThat(e).hasMessageThat().contains("Failed to collect certificates from ");
+ }
+
+ private ApexInfo[] createApexInfoForTestPkg(boolean isActive, boolean isFactory) {
File apexFile = extractResource(TEST_APEX_PKG, TEST_APEX_FILE_NAME);
ApexInfo apexInfo = new ApexInfo();
apexInfo.isActive = isActive;
@@ -327,6 +434,17 @@
return new ApexInfo[]{apexInfo};
}
+ private ApexInfo createApexInfo(String moduleName, int versionCode, boolean isActive,
+ boolean isFactory, File apexFile) {
+ ApexInfo apexInfo = new ApexInfo();
+ apexInfo.moduleName = moduleName;
+ apexInfo.versionCode = versionCode;
+ apexInfo.isActive = isActive;
+ apexInfo.isFactory = isFactory;
+ apexInfo.modulePath = apexFile.getPath();
+ return apexInfo;
+ }
+
private ApexSessionInfo getFakeStagedSessionInfo() {
ApexSessionInfo stagedSessionInfo = new ApexSessionInfo();
stagedSessionInfo.sessionId = TEST_SESSION_ID;
@@ -358,6 +476,7 @@
} catch (IOException e) {
throw new AssertionError("CreateTempFile IOException" + e);
}
+
try (
InputStream in = ApexManager.class.getClassLoader()
.getResourceAsStream(fullResourceName);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index f6baa6bb..7df2dd6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -635,8 +635,8 @@
}
@Override
- PendingIntent injectCreatePendingIntent(Context context, int requestCode,
- @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) {
+ PendingIntent injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents,
+ int flags, Bundle options, String ownerPackage, int ownerUserId) {
return new PendingIntent(mock(IIntentSender.class));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
index f9b8f26..bc0a540 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
@@ -69,7 +69,7 @@
private static final String DEX_METADATA_FILE_EXTENSION = ".dm";
private static final String DEX_METADATA_PACKAGE_NAME =
"com.android.frameworks.servicestests.install_split";
- private static long DEX_METADATA_VERSION_CODE = 30;
+ private static final long DEX_METADATA_VERSION_CODE = 9001;
@Rule
public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
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 2c7c3e3..70ba2cf 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -65,6 +65,8 @@
import static com.android.server.notification.NotificationManagerService.ACTION_ENABLE_NAS;
import static com.android.server.notification.NotificationManagerService.ACTION_LEARNMORE_NAS;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
@@ -261,6 +263,8 @@
@Mock
private ShortcutServiceInternal mShortcutServiceInternal;
@Mock
+ private UserManager mUserManager;
+ @Mock
ActivityManager mActivityManager;
@Mock
Resources mResources;
@@ -526,6 +530,7 @@
mShortcutHelper = mService.getShortcutHelper();
mShortcutHelper.setLauncherApps(mLauncherApps);
mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
+ mShortcutHelper.setUserManager(mUserManager);
// Capture PackageIntentReceiver
ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
@@ -567,6 +572,7 @@
when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
anyString(), anyInt(), any())).thenReturn(true);
+ when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true);
// Set the testable bubble extractor
RankingHelper rankingHelper = mService.getRankingHelper();
@@ -7506,6 +7512,13 @@
mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
assertEquals(si, conversations.get(0).getShortcutInfo());
assertEquals(si, conversations.get(1).getShortcutInfo());
+
+ // Returns null shortcuts when locked.
+ when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(false);
+ conversations =
+ mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
+ assertThat(conversations.get(0).getShortcutInfo()).isNull();
+ assertThat(conversations.get(1).getShortcutInfo()).isNull();
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java
index f43e5a8..11cb150 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java
@@ -34,6 +34,7 @@
import android.content.pm.ShortcutQueryWrapper;
import android.content.pm.ShortcutServiceInternal;
import android.os.UserHandle;
+import android.os.UserManager;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableLooper;
@@ -71,6 +72,8 @@
@Mock
ShortcutHelper.ShortcutListener mShortcutListener;
@Mock
+ UserManager mUserManager;
+ @Mock
ShortcutServiceInternal mShortcutServiceInternal;
@Mock
NotificationRecord mNr;
@@ -92,11 +95,12 @@
MockitoAnnotations.initMocks(this);
mShortcutHelper = new ShortcutHelper(
- mLauncherApps, mShortcutListener, mShortcutServiceInternal);
+ mLauncherApps, mShortcutListener, mShortcutServiceInternal, mUserManager);
when(mSbn.getPackageName()).thenReturn(PKG);
when(mShortcutInfo.getId()).thenReturn(SHORTCUT_ID);
when(mNotif.getBubbleMetadata()).thenReturn(mBubbleMetadata);
when(mBubbleMetadata.getShortcutId()).thenReturn(SHORTCUT_ID);
+ when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true);
setUpMockNotificationRecord(mNr, KEY);
}
@@ -317,6 +321,25 @@
.isSameInstanceAs(si);
}
+
+ @Test
+ public void testGetValidShortcutInfo_isValidButUserLocked() {
+ ShortcutInfo si = mock(ShortcutInfo.class);
+ when(si.getPackage()).thenReturn(PKG);
+ when(si.getId()).thenReturn(SHORTCUT_ID);
+ when(si.getUserId()).thenReturn(UserHandle.USER_SYSTEM);
+ when(si.isLongLived()).thenReturn(true);
+ when(si.isEnabled()).thenReturn(true);
+ when(si.getPersons()).thenReturn(new Person[]{PERSON});
+ ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+ shortcuts.add(si);
+ when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcuts);
+ when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(false);
+
+ assertThat(mShortcutHelper.getValidShortcutInfo("a", "p", UserHandle.SYSTEM))
+ .isNull();
+ }
+
@Test
public void testGetValidShortcutInfo_hasGetPersonsDataFlag() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index beff386..82c459c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -353,8 +353,22 @@
mTrampolineActivity.setVisibility(false);
notifyWindowsDrawn(mTopActivity);
- assertWithMessage("Trampoline activity is invisble so there should be no undrawn windows")
+ assertWithMessage("Trampoline activity is invisible so there should be no undrawn windows")
.that(mLaunchingState.allDrawn()).isTrue();
+
+ // Since the activity is drawn, the launch event should be reported.
+ notifyTransitionStarting(mTopActivity);
+ verifyOnActivityLaunchFinished(mTopActivity);
+ mLaunchTopByTrampoline = false;
+ clearInvocations(mLaunchObserver);
+
+ // Another round without setting visibility of the trampoline activity.
+ onActivityLaunchedTrampoline();
+ notifyWindowsDrawn(mTopActivity);
+ // If the transition can start, the invisible activities should be discarded and the launch
+ // event be reported successfully.
+ notifyTransitionStarting(mTopActivity);
+ verifyOnActivityLaunchFinished(mTopActivity);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 94297be..5bc4c82 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1386,11 +1386,11 @@
performLayout(mDisplayContent);
// Force the negative offset to verify it can be updated.
- mWallpaperWindow.mWinAnimator.mXOffset = mWallpaperWindow.mWinAnimator.mYOffset = -1;
+ mWallpaperWindow.mXOffset = mWallpaperWindow.mYOffset = -1;
assertTrue(mDisplayContent.mWallpaperController.updateWallpaperOffset(mWallpaperWindow,
false /* sync */));
- assertThat(mWallpaperWindow.mWinAnimator.mXOffset).isGreaterThan(-1);
- assertThat(mWallpaperWindow.mWinAnimator.mYOffset).isGreaterThan(-1);
+ assertThat(mWallpaperWindow.mXOffset).isGreaterThan(-1);
+ assertThat(mWallpaperWindow.mYOffset).isGreaterThan(-1);
// The wallpaper need to animate with transformed position, so its surface position should
// not be reset.
diff --git a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java
index 1ee646c..e6348a5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.hardware.display.DisplayManager;
import android.platform.test.annotations.Presubmit;
import android.view.Display.Mode;
import android.view.DisplayInfo;
@@ -56,6 +57,13 @@
private RefreshRatePolicy mRefreshRatePolicy;
private HighRefreshRateDenylist mDenylist = mock(HighRefreshRateDenylist.class);
+ WindowState createWindow(String name) {
+ WindowState window = createWindow(null, TYPE_APPLICATION, name);
+ when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType())
+ .thenReturn(DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS);
+ return window;
+ }
+
@Before
public void setUp() {
DisplayInfo di = new DisplayInfo(mDisplayInfo);
@@ -73,7 +81,7 @@
@Test
public void basicTest() {
- final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+ final WindowState appWindow = createWindow("appWindow");
assertNotNull("Window state is created", appWindow);
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
@@ -97,7 +105,7 @@
@Test
public void testApplicationInFocusWithoutModeId() {
- final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+ final WindowState appWindow = createWindow("appWindow");
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.getDisplayContent().getDisplayPolicy().getRefreshRatePolicy()
.getPreferredModeId(appWindow), 0);
@@ -128,7 +136,7 @@
@Test
public void testApplicationInFocusWithModeId() {
- final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+ final WindowState appWindow = createWindow("appWindow");
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
@@ -165,11 +173,11 @@
@Test
public void testApplicationNotInFocusWithModeId() {
- final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+ final WindowState appWindow = createWindow("appWindow");
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
- final WindowState inFocusWindow = createWindow(null, TYPE_APPLICATION, "inFocus");
+ final WindowState inFocusWindow = createWindow("inFocus");
appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow;
appWindow.updateFrameRateSelectionPriorityIfNeeded();
@@ -194,11 +202,11 @@
@Test
public void testApplicationNotInFocusWithoutModeId() {
- final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+ final WindowState appWindow = createWindow("appWindow");
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
- final WindowState inFocusWindow = createWindow(null, TYPE_APPLICATION, "inFocus");
+ final WindowState inFocusWindow = createWindow("inFocus");
appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow;
appWindow.updateFrameRateSelectionPriorityIfNeeded();
@@ -221,7 +229,7 @@
@Test
public void testPreferredRefreshRate() {
- final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+ final WindowState appWindow = createWindow("appWindow");
assertNotNull("Window state is created", appWindow);
when(appWindow.getDisplayContent().getDisplayPolicy()).thenReturn(mDisplayPolicy);
@@ -246,4 +254,31 @@
appWindow.getSurfaceControl(), 60,
Surface.FRAME_RATE_COMPATIBILITY_EXACT, Surface.CHANGE_FRAME_RATE_ALWAYS);
}
+
+ @Test
+ public void testSwitchingTypeNone() {
+ final WindowState appWindow = createWindow("appWindow");
+ when(appWindow.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType())
+ .thenReturn(DisplayManager.SWITCHING_TYPE_NONE);
+
+ assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
+ assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
+
+ // Update the mode ID to a requested number.
+ appWindow.mAttrs.preferredDisplayModeId = 1;
+ appWindow.updateFrameRateSelectionPriorityIfNeeded();
+
+ assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
+
+ // Remove the mode ID request.
+ appWindow.mAttrs.preferredDisplayModeId = 0;
+ appWindow.updateFrameRateSelectionPriorityIfNeeded();
+
+ assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
+
+ verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority(
+ appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET);
+ verify(appWindow.getPendingTransaction(), never()).setFrameRate(
+ any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
+ }
}
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 db7e437..d2270b5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -50,6 +50,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.same;
@@ -357,6 +358,11 @@
final WindowState window = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "window");
assertEquals(window, mActivity.findMainWindow());
+
+ spyOn(mActivity.mLetterboxUiController);
+ doReturn(true).when(mActivity.mLetterboxUiController)
+ .isSurfaceReadyAndVisible(any());
+
assertTrue(mActivity.mLetterboxUiController.shouldShowLetterboxUi(
mActivity.findMainWindow()));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index b3a0745..4c31ee2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -53,12 +53,12 @@
}
@Override
- public void insetsChanged(InsetsState insetsState) throws RemoteException {
+ public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) {
}
@Override
- public void insetsControlChanged(InsetsState insetsState, InsetsSourceControl[] activeControls)
- throws RemoteException {
+ public void insetsControlChanged(InsetsState insetsState,
+ InsetsSourceControl[] activeControls, boolean willMove, boolean willResize) {
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index ada58a5..3f0c13c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -212,7 +212,7 @@
// value did, and we do dispatch the zoom to the wallpaper service
dc.mWallpaperController.setWallpaperZoomOut(homeWindow, newZoom);
assertEquals(newZoom, wallpaperWindow.mWallpaperZoomOut, .01f);
- assertEquals(1f, wallpaperWindow.mWinAnimator.mWallpaperScale, .01f);
+ assertEquals(1f, wallpaperWindow.mWallpaperScale, .01f);
verify(wallpaperWindow.mClient).dispatchWallpaperOffsets(anyFloat(), anyFloat(), anyFloat(),
anyFloat(), eq(newZoom), anyBoolean());
}
diff --git a/services/translation/java/com/android/server/translation/TranslationManagerService.java b/services/translation/java/com/android/server/translation/TranslationManagerService.java
index 415f055..41ee6b5 100644
--- a/services/translation/java/com/android/server/translation/TranslationManagerService.java
+++ b/services/translation/java/com/android/server/translation/TranslationManagerService.java
@@ -294,6 +294,11 @@
synchronized (mLock) {
dumpLocked("", pw);
+ final int userId = UserHandle.getCallingUserId();
+ final TranslationManagerServiceImpl service = getServiceForUserLocked(userId);
+ if (service != null) {
+ service.dumpLocked(" ", fd, pw);
+ }
}
}
diff --git a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
index 2b01cdf..16a2d8d 100644
--- a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
+++ b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
@@ -45,12 +45,17 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
+import com.android.internal.os.TransferPipe;
import com.android.server.LocalServices;
import com.android.server.infra.AbstractPerUserSystemService;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal.ActivityTokens;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.util.List;
final class TranslationManagerServiceImpl extends
@@ -69,6 +74,9 @@
@GuardedBy("mLock")
private TranslationServiceInfo mTranslationServiceInfo;
+ @GuardedBy("mLock")
+ private WeakReference<ActivityTokens> mLastActivityTokens;
+
private ActivityTaskManagerInternal mActivityTaskManagerInternal;
private final TranslationServiceRemoteCallback mRemoteServiceCallback =
@@ -178,12 +186,35 @@
taskTopActivityTokens.getApplicationThread().updateUiTranslationState(
taskTopActivityTokens.getActivityToken(), state, sourceSpec, targetSpec,
viewIds, uiTranslationSpec);
+ mLastActivityTokens = new WeakReference<>(taskTopActivityTokens);
} catch (RemoteException e) {
Slog.w(TAG, "Update UiTranslationState fail: " + e);
}
invokeCallbacks(state, sourceSpec, targetSpec);
}
+ @GuardedBy("mLock")
+ public void dumpLocked(String prefix, FileDescriptor fd, PrintWriter pw) {
+ if (mLastActivityTokens != null) {
+ ActivityTokens activityTokens = mLastActivityTokens.get();
+ if (activityTokens == null) {
+ return;
+ }
+ try (TransferPipe tp = new TransferPipe()) {
+ activityTokens.getApplicationThread().dumpActivity(tp.getWriteFd(),
+ activityTokens.getActivityToken(), prefix,
+ new String[]{"--translation"});
+ tp.go(fd);
+ } catch (IOException e) {
+ pw.println(prefix + "Failure while dumping the activity: " + e);
+ } catch (RemoteException e) {
+ pw.println(prefix + "Got a RemoteException while dumping the activity");
+ }
+ } else {
+ pw.print(prefix); pw.println("No requested UiTranslation Activity.");
+ }
+ }
+
private void invokeCallbacks(
int state, TranslationSpec sourceSpec, TranslationSpec targetSpec) {
Bundle res = new Bundle();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 0bb09a9..17303a4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -34,6 +34,7 @@
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.MediaRecorder;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
@@ -48,6 +49,7 @@
import android.service.voice.IDspHotwordDetectionCallback;
import android.service.voice.IHotwordDetectionService;
import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
+import android.service.voice.VoiceInteractionManagerInternal.HotwordDetectionServiceIdentity;
import android.util.Pair;
import android.util.Slog;
import android.view.contentcapture.IContentCaptureManager;
@@ -56,6 +58,8 @@
import com.android.internal.app.IHotwordRecognitionStatusCallback;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.infra.ServiceConnector;
+import com.android.server.LocalServices;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
import java.io.Closeable;
import java.io.IOException;
@@ -94,20 +98,24 @@
private final AtomicBoolean mUpdateStateFinish = new AtomicBoolean(false);
final Object mLock;
+ final int mVoiceInteractionServiceUid;
final ComponentName mDetectionComponentName;
final int mUser;
final Context mContext;
final @NonNull ServiceConnector<IHotwordDetectionService> mRemoteHotwordDetectionService;
boolean mBound;
+ volatile HotwordDetectionServiceIdentity mIdentity;
@GuardedBy("mLock")
private ParcelFileDescriptor mCurrentAudioSink;
- HotwordDetectionConnection(Object lock, Context context, ComponentName serviceName,
- int userId, boolean bindInstantServiceAllowed, @Nullable PersistableBundle options,
- @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
+ HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid,
+ ComponentName serviceName, int userId, boolean bindInstantServiceAllowed,
+ @Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory,
+ IHotwordRecognitionStatusCallback callback) {
mLock = lock;
mContext = context;
+ mVoiceInteractionServiceUid = voiceInteractionServiceUid;
mDetectionComponentName = serviceName;
mUser = userId;
final Intent intent = new Intent(HotwordDetectionService.SERVICE_INTERFACE);
@@ -131,14 +139,26 @@
protected long getAutoDisconnectTimeoutMs() {
return -1;
}
+
+ @Override
+ public void binderDied() {
+ super.binderDied();
+ Slog.w(TAG, "binderDied");
+ try {
+ callback.onError(-1);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to report onError status: " + e);
+ }
+ }
};
mRemoteHotwordDetectionService.connect();
if (callback == null) {
updateStateLocked(options, sharedMemory);
return;
}
- updateStateWithCallbackLocked(options, sharedMemory, callback);
+ updateAudioFlinger();
updateContentCaptureManager();
+ updateStateWithCallbackLocked(options, sharedMemory, callback);
}
private void updateStateWithCallbackLocked(PersistableBundle options,
@@ -153,7 +173,15 @@
public void sendResult(Bundle bundle) throws RemoteException {
if (DEBUG) {
Slog.d(TAG, "updateState finish");
+ Slog.d(TAG, "updating hotword UID " + Binder.getCallingUid());
}
+ // TODO: Do this earlier than this callback and have the provider point to the
+ // current state stored in VoiceInteractionManagerServiceImpl.
+ final int uid = Binder.getCallingUid();
+ LocalServices.getService(PermissionManagerServiceInternal.class)
+ .setHotwordDetectionServiceProvider(() -> uid);
+ mIdentity =
+ new HotwordDetectionServiceIdentity(uid, mVoiceInteractionServiceUid);
future.complete(null);
try {
if (mUpdateStateFinish.getAndSet(true)) {
@@ -202,6 +230,15 @@
});
}
+ private void updateAudioFlinger() {
+ // TODO: Consider using a proxy that limits the exposed API surface.
+ IBinder audioFlinger = ServiceManager.getService("media.audio_flinger");
+ if (audioFlinger == null) {
+ throw new IllegalStateException("Service media.audio_flinger wasn't found.");
+ }
+ mRemoteHotwordDetectionService.post(service -> service.updateAudioFlinger(audioFlinger));
+ }
+
private void updateContentCaptureManager() {
IBinder b = ServiceManager
.getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
@@ -224,6 +261,9 @@
if (mBound) {
mRemoteHotwordDetectionService.unbind();
mBound = false;
+ LocalServices.getService(PermissionManagerServiceInternal.class)
+ .setHotwordDetectionServiceProvider(null);
+ mIdentity = null;
}
}
@@ -318,7 +358,7 @@
if (DEBUG) {
Slog.d(TAG, "onDetected");
}
- externalCallback.onKeyphraseDetected(recognitionEvent);
+ externalCallback.onKeyphraseDetected(recognitionEvent, result);
}
@Override
@@ -351,8 +391,7 @@
if (DEBUG) {
Slog.d(TAG, "onDetected");
}
- // TODO: Propagate the HotwordDetectedResult.
- externalCallback.onKeyphraseDetected(recognitionEvent);
+ externalCallback.onKeyphraseDetected(recognitionEvent, result);
}
@Override
@@ -396,7 +435,7 @@
mHotwordDetectionConnection.detectFromDspSource(
recognitionEvent, mExternalCallback);
} else {
- mExternalCallback.onKeyphraseDetected(recognitionEvent);
+ mExternalCallback.onKeyphraseDetected(recognitionEvent, null);
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index f3d80b1..a14912e 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -251,6 +251,26 @@
return TextUtils.equals(packageName, session.mSessionComponentName.getPackageName());
}
+
+ @Override
+ public HotwordDetectionServiceIdentity getHotwordDetectionServiceIdentity() {
+ // IMPORTANT: This is called when performing permission checks; do not lock!
+
+ // TODO: Have AppOpsPolicy register a listener instead of calling in here everytime.
+ // Then also remove the `volatile`s that were added with this method.
+
+ VoiceInteractionManagerServiceImpl impl =
+ VoiceInteractionManagerService.this.mServiceStub.mImpl;
+ if (impl == null) {
+ return null;
+ }
+ HotwordDetectionConnection hotwordDetectionConnection =
+ impl.mHotwordDetectionConnection;
+ if (hotwordDetectionConnection == null) {
+ return null;
+ }
+ return hotwordDetectionConnection.mIdentity;
+ }
}
// implementation entry point and binder service
@@ -258,7 +278,7 @@
class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub {
- VoiceInteractionManagerServiceImpl mImpl;
+ volatile VoiceInteractionManagerServiceImpl mImpl;
private boolean mSafeMode;
private int mCurUser;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 2206b0a..ca30bc5 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -98,7 +98,7 @@
final ComponentName mHotwordDetectionComponentName;
boolean mBound = false;
IVoiceInteractionService mService;
- HotwordDetectionConnection mHotwordDetectionConnection;
+ volatile HotwordDetectionConnection mHotwordDetectionConnection;
VoiceInteractionSessionConnection mActiveSession;
int mDisabledShowContext;
@@ -447,8 +447,8 @@
if (mHotwordDetectionConnection == null) {
mHotwordDetectionConnection = new HotwordDetectionConnection(mServiceStub, mContext,
- mHotwordDetectionComponentName, mUser, /* bindInstantServiceAllowed= */ false,
- options, sharedMemory, callback);
+ mInfo.getServiceInfo().applicationInfo.uid, mHotwordDetectionComponentName,
+ mUser, /* bindInstantServiceAllowed= */ false, options, sharedMemory, callback);
} else {
mHotwordDetectionConnection.updateStateLocked(options, sharedMemory);
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8fb805b..7f1ea8f 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -33,6 +33,7 @@
import android.os.RemoteException;
import android.service.carrier.CarrierService;
import android.telecom.TelecomManager;
+import android.telephony.data.DataCallResponse;
import android.telephony.gba.TlsParams;
import android.telephony.gba.UaSecurityProtocolIdentifier;
import android.telephony.ims.ImsReasonInfo;
@@ -1052,6 +1053,21 @@
"carrier_data_call_apn_retry_after_disconnect_long";
/**
+ * The maximum times for telephony to retry data setup on the same APN requested by
+ * network through the data setup response retry timer
+ * {@link DataCallResponse#getRetryDurationMillis()}. This is to prevent that network keeps
+ * asking device to retry data setup forever and causes power consumption issue. For infinite
+ * retring same APN, configure this as 2147483647 (i.e. {@link Integer#MAX_VALUE}).
+ *
+ * Note if network does not suggest any retry timer, frameworks uses the retry configuration
+ * from {@link #KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS}, and the maximum retry times could
+ * be configured there.
+ * @hide
+ */
+ public static final String KEY_CARRIER_DATA_CALL_RETRY_NETWORK_REQUESTED_MAX_COUNT_INT =
+ "carrier_data_call_retry_network_requested_max_count_int";
+
+ /**
* Data call setup permanent failure causes by the carrier
*/
public static final String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS =
@@ -2680,8 +2696,8 @@
/**
* List of EARFCN (E-UTRA Absolute Radio Frequency Channel Number,
- * Reference: 3GPP TS 36.104 5.4.3) inclusive ranges on which lte_rsrp_boost_int
- * will be applied. Format of the String array is expected to be {"erafcn1_start-earfcn1_end",
+ * Reference: 3GPP TS 36.104 5.4.3) inclusive ranges on which lte_earfcns_rsrp_boost_int
+ * will be applied. Format of the String array is expected to be {"earfcn1_start-earfcn1_end",
* "earfcn2_start-earfcn2_end" ... }
* @hide
*/
@@ -2689,6 +2705,24 @@
"boosted_lte_earfcns_string_array";
/**
+ * Offset to be reduced from rsrp threshold while calculating signal strength level.
+ * @hide
+ */
+ public static final String KEY_NRARFCNS_RSRP_BOOST_INT_ARRAY = "nrarfcns_rsrp_boost_int_array";
+
+ /**
+ * List of NR ARFCN (5G Absolute Radio Frequency Channel Number,
+ * Reference: 3GPP TS 36.108) inclusive ranges on which corresponding
+ * nrarfcns_rsrp_boost_int_array will be applied. The size of this array and
+ * nrarfcns_rsrp_boost_int_array must be the same.
+ * Format of the String array is expected to be {"nrarfcn1_start-nrarfcn1_end",
+ * "nrarfcn2_start-nrarfcn2_end" ... }
+ * @hide
+ */
+ public static final String KEY_BOOSTED_NRARFCNS_STRING_ARRAY =
+ "boosted_nrarfcns_string_array";
+
+ /**
* Determine whether to use only RSRP for the number of LTE signal bars.
* @hide
*
@@ -5130,6 +5164,7 @@
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG, 20000);
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG, 3000);
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_RETRY_AFTER_DISCONNECT_LONG, 10000);
+ sDefaults.putInt(KEY_CARRIER_DATA_CALL_RETRY_NETWORK_REQUESTED_MAX_COUNT_INT, 3);
sDefaults.putString(KEY_CARRIER_ERI_FILE_NAME_STRING, "eri.xml");
sDefaults.putInt(KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT, 7200);
sDefaults.putStringArray(KEY_CARRIER_METERED_APN_TYPES_STRINGS,
@@ -5338,6 +5373,8 @@
sDefaults.putBoolean(KEY_SUPPORT_IMS_CALL_FORWARDING_WHILE_ROAMING_BOOL, true);
sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
sDefaults.putStringArray(KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY, null);
+ sDefaults.putIntArray(KEY_NRARFCNS_RSRP_BOOST_INT_ARRAY, null);
+ sDefaults.putStringArray(KEY_BOOSTED_NRARFCNS_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL, false);
sDefaults.putBoolean(KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL, false);
sDefaults.putInt(IMSI_KEY_AVAILABILITY_INT, 0);
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 7addf33..9211482 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -314,7 +314,7 @@
int rsrpBoost = 0;
if (ss != null) {
- rsrpBoost = ss.getLteEarfcnRsrpBoost();
+ rsrpBoost = ss.getArfcnRsrpBoost();
}
int rsrp = inRangeOrUnavailable(mRsrp + rsrpBoost, MIN_LTE_RSRP, MAX_LTE_RSRP);
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index ac01afa..72150dd 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -419,7 +419,11 @@
int ssRsrqLevel = SignalStrength.INVALID;
int ssSinrLevel = SignalStrength.INVALID;
if (isLevelForParameter(USE_SSRSRP)) {
- ssRsrpLevel = updateLevelWithMeasure(mSsRsrp, mSsRsrpThresholds);
+ int rsrpBoost = 0;
+ if (ss != null) {
+ rsrpBoost = ss.getArfcnRsrpBoost();
+ }
+ ssRsrpLevel = updateLevelWithMeasure(mSsRsrp + rsrpBoost, mSsRsrpThresholds);
if (VDBG) {
Rlog.i(TAG, "Updated 5G NR SSRSRP Level: " + ssRsrpLevel);
}
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 4d5b6ac..88efe1f 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1069,6 +1069,13 @@
*/
public static final int NO_DEFAULT_DATA = 0x10008;
+ /**
+ * Data service is temporarily unavailable.
+ *
+ * @hide
+ */
+ public static final int SERVICE_TEMPORARILY_UNAVAILABLE = 0x10009;
+
private static final Map<Integer, String> sFailCauseMap;
static {
sFailCauseMap = new HashMap<>();
@@ -1500,6 +1507,7 @@
sFailCauseMap.put(HANDOVER_FAILED, "HANDOVER_FAILED");
sFailCauseMap.put(DUPLICATE_CID, "DUPLICATE_CID");
sFailCauseMap.put(NO_DEFAULT_DATA, "NO_DEFAULT_DATA");
+ sFailCauseMap.put(SERVICE_TEMPORARILY_UNAVAILABLE, "SERVICE_TEMPORARILY_UNAVAILABLE");
}
private DataFailCause() {
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 2d06062..6da61b7 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -353,9 +353,11 @@
private int mChannelNumber;
private int[] mCellBandwidths = new int[0];
- /* EARFCN stands for E-UTRA Absolute Radio Frequency Channel Number,
- * Reference: 3GPP TS 36.104 5.4.3 */
- private int mLteEarfcnRsrpBoost = 0;
+ /**
+ * ARFCN stands for Absolute Radio Frequency Channel Number. This field is current used for
+ * LTE where it represents the boost for EARFCN (Reference: 3GPP TS 36.104 5.4.3) and for NR
+ * where it's for NR ARFCN (Reference: 3GPP TS 36.108) */
+ private int mArfcnRsrpBoost = 0;
private final List<NetworkRegistrationInfo> mNetworkRegistrationInfos = new ArrayList<>();
@@ -439,7 +441,7 @@
mChannelNumber = s.mChannelNumber;
mCellBandwidths = s.mCellBandwidths == null ? null :
Arrays.copyOf(s.mCellBandwidths, s.mCellBandwidths.length);
- mLteEarfcnRsrpBoost = s.mLteEarfcnRsrpBoost;
+ mArfcnRsrpBoost = s.mArfcnRsrpBoost;
synchronized (mNetworkRegistrationInfos) {
mNetworkRegistrationInfos.clear();
mNetworkRegistrationInfos.addAll(s.getNetworkRegistrationInfoList());
@@ -473,7 +475,7 @@
mCdmaEriIconIndex = in.readInt();
mCdmaEriIconMode = in.readInt();
mIsEmergencyOnly = in.readInt() != 0;
- mLteEarfcnRsrpBoost = in.readInt();
+ mArfcnRsrpBoost = in.readInt();
synchronized (mNetworkRegistrationInfos) {
in.readList(mNetworkRegistrationInfos, NetworkRegistrationInfo.class.getClassLoader());
}
@@ -501,7 +503,7 @@
out.writeInt(mCdmaEriIconIndex);
out.writeInt(mCdmaEriIconMode);
out.writeInt(mIsEmergencyOnly ? 1 : 0);
- out.writeInt(mLteEarfcnRsrpBoost);
+ out.writeInt(mArfcnRsrpBoost);
synchronized (mNetworkRegistrationInfos) {
out.writeList(mNetworkRegistrationInfos);
}
@@ -890,7 +892,7 @@
mCdmaEriIconIndex,
mCdmaEriIconMode,
mIsEmergencyOnly,
- mLteEarfcnRsrpBoost,
+ mArfcnRsrpBoost,
mNetworkRegistrationInfos,
mNrFrequencyRange,
mOperatorAlphaLongRaw,
@@ -1101,7 +1103,7 @@
.append(", mCdmaDefaultRoamingIndicator=").append(mCdmaDefaultRoamingIndicator)
.append(", mIsEmergencyOnly=").append(mIsEmergencyOnly)
.append(", isUsingCarrierAggregation=").append(isUsingCarrierAggregation())
- .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
+ .append(", mArfcnRsrpBoost=").append(mArfcnRsrpBoost)
.append(", mNetworkRegistrationInfos=").append(mNetworkRegistrationInfos)
.append(", mNrFrequencyRange=").append(Build.IS_DEBUGGABLE
? mNrFrequencyRange : FREQUENCY_RANGE_UNKNOWN)
@@ -1132,7 +1134,7 @@
mCdmaEriIconIndex = -1;
mCdmaEriIconMode = -1;
mIsEmergencyOnly = false;
- mLteEarfcnRsrpBoost = 0;
+ mArfcnRsrpBoost = 0;
mNrFrequencyRange = FREQUENCY_RANGE_UNKNOWN;
synchronized (mNetworkRegistrationInfos) {
mNetworkRegistrationInfos.clear();
@@ -1364,7 +1366,7 @@
m.putBoolean("emergencyOnly", mIsEmergencyOnly);
m.putBoolean("isDataRoamingFromRegistration", getDataRoamingFromRegistration());
m.putBoolean("isUsingCarrierAggregation", isUsingCarrierAggregation());
- m.putInt("LteEarfcnRsrpBoost", mLteEarfcnRsrpBoost);
+ m.putInt("ArfcnRsrpBoost", mArfcnRsrpBoost);
m.putInt("ChannelNumber", mChannelNumber);
m.putIntArray("CellBandwidths", mCellBandwidths);
m.putInt("mNrFrequencyRange", mNrFrequencyRange);
@@ -1455,13 +1457,13 @@
}
/** @hide */
- public int getLteEarfcnRsrpBoost() {
- return mLteEarfcnRsrpBoost;
+ public int getArfcnRsrpBoost() {
+ return mArfcnRsrpBoost;
}
/** @hide */
- public void setLteEarfcnRsrpBoost(int LteEarfcnRsrpBoost) {
- mLteEarfcnRsrpBoost = LteEarfcnRsrpBoost;
+ public void setArfcnRsrpBoost(int arfcnRsrpBoost) {
+ mArfcnRsrpBoost = arfcnRsrpBoost;
}
/** @hide */
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index 363e47a..d082715 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -63,6 +63,11 @@
public static final int RESULT_ERROR_BUSY = 3;
/** Request sent in illegal state */
public static final int RESULT_ERROR_ILLEGAL_STATE = 4;
+ /**
+ * Service is temporarily unavailable. Frameworks should retry the request again.
+ * @hide
+ */
+ public static final int RESULT_ERROR_TEMPORARILY_UNAVAILABLE = 5;
private final IDataServiceCallback mCallback;
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PictureCaptureDemo.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PictureCaptureDemo.java
index 029e302..15568ac 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PictureCaptureDemo.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PictureCaptureDemo.java
@@ -34,13 +34,14 @@
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ProgressBar;
+import android.widget.TextView;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
import java.util.Random;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
public class PictureCaptureDemo extends Activity {
@Override
@@ -77,6 +78,12 @@
iv2.setImageBitmap(Bitmap.createBitmap(picture, 100, 100, Bitmap.Config.HARDWARE));
inner.addView(iv2, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ TextView hello = new TextView(this);
+ hello.setText("I'm on a layer!");
+ hello.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ inner.addView(hello,
+ new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+
layout.addView(inner,
new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
// For testing with a functor in the tree
@@ -84,11 +91,13 @@
wv.setWebViewClient(new WebViewClient());
wv.setWebChromeClient(new WebChromeClient());
wv.loadUrl("https://google.com");
- layout.addView(wv, new LayoutParams(LayoutParams.MATCH_PARENT, 400));
+ LayoutParams wvParams = new LayoutParams(LayoutParams.MATCH_PARENT, 400);
+ wvParams.bottomMargin = 50;
+ layout.addView(wv, wvParams);
SurfaceView mySurfaceView = new SurfaceView(this);
layout.addView(mySurfaceView,
- new LayoutParams(LayoutParams.MATCH_PARENT, 600));
+ new LayoutParams(LayoutParams.MATCH_PARENT, 600, 1f));
setContentView(layout);
@@ -98,22 +107,29 @@
@Override
public void surfaceCreated(SurfaceHolder holder) {
final Random rand = new Random();
+ OutputStream renderingStream = new ByteArrayOutputStream() {
+ @Override
+ public void flush() throws IOException {
+ Picture picture = Picture.createFromStream(
+ new ByteArrayInputStream(buf, 0, count));
+ Canvas canvas = holder.lockCanvas();
+ if (canvas != null && picture != null) {
+ canvas.drawPicture(picture);
+ holder.unlockCanvasAndPost(canvas);
+ }
+ reset();
+ }
+ };
+
mStopCapture = ViewDebug.startRenderingCommandsCapture(mySurfaceView,
- mCaptureThread, (picture) -> {
+ Executors.newSingleThreadExecutor(), () -> {
if (rand.nextInt(20) == 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
- Canvas canvas = holder.lockCanvas();
- if (canvas == null) {
- return false;
- }
- canvas.drawPicture(picture);
- holder.unlockCanvasAndPost(canvas);
- picture.close();
- return true;
+ return renderingStream;
});
}
@@ -134,20 +150,4 @@
}
});
}
-
- ExecutorService mCaptureThread = Executors.newSingleThreadExecutor();
- ExecutorService mExecutor = Executors.newSingleThreadExecutor();
-
- Picture deepCopy(Picture src) {
- try {
- PipedInputStream inputStream = new PipedInputStream();
- PipedOutputStream outputStream = new PipedOutputStream(inputStream);
- Future<Picture> future = mExecutor.submit(() -> Picture.createFromStream(inputStream));
- src.writeToStream(outputStream);
- outputStream.close();
- return future.get();
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
}
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index 9fd190c..ccd63f9 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -139,6 +139,7 @@
* Tests that duplicate packages in apk-in-apex and apk should fail to install.
*/
@Test
+ @LargeTest
public void testDuplicateApkInApexShouldFail() throws Exception {
pushTestApex();
runPhase("testDuplicateApkInApexShouldFail_Commit");
@@ -290,6 +291,7 @@
}
@Test
+ @LargeTest
public void testOrphanedStagingDirectoryGetsCleanedUpOnReboot() throws Exception {
//create random directories in /data/app-staging folder
getDevice().enableAdbRoot();
@@ -305,6 +307,7 @@
}
@Test
+ @LargeTest
public void testFailStagedSessionIfStagingDirectoryDeleted() throws Exception {
// Create a staged session
runPhase("testFailStagedSessionIfStagingDirectoryDeleted_Commit");
diff --git a/tests/UpdatableSystemFontTest/Android.bp b/tests/UpdatableSystemFontTest/Android.bp
index ea5a431..e07fbbf 100644
--- a/tests/UpdatableSystemFontTest/Android.bp
+++ b/tests/UpdatableSystemFontTest/Android.bp
@@ -27,6 +27,7 @@
libs: ["android.test.runner"],
static_libs: [
"androidx.test.ext.junit",
+ "androidx.test.uiautomator_uiautomator",
"compatibility-device-util-axt",
"platform-test-annotations",
"truth-prebuilt",
diff --git a/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml b/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml
index 5d8f5fc..8c3d876 100644
--- a/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml
+++ b/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/AndroidManifest.xml
@@ -19,5 +19,6 @@
package="com.android.emojirenderingtestapp">
<application>
<activity android:name=".EmojiRenderingTestActivity"/>
+ <activity android:name=".GetAvailableFontsTestActivity"/>
</application>
</manifest>
diff --git a/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/src/com/android/emojirenderingtestapp/GetAvailableFontsTestActivity.java b/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/src/com/android/emojirenderingtestapp/GetAvailableFontsTestActivity.java
new file mode 100644
index 0000000..b9a9149
--- /dev/null
+++ b/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/src/com/android/emojirenderingtestapp/GetAvailableFontsTestActivity.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.emojirenderingtestapp;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import android.app.Activity;
+import android.graphics.fonts.Font;
+import android.graphics.fonts.SystemFonts;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class GetAvailableFontsTestActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ String emojiFontPath = "<Not found>";
+ for (Font font : SystemFonts.getAvailableFonts()) {
+ // Calls font attribute getters to make sure that they don't open font files.
+ font.getAxes();
+ font.getFile();
+ font.getLocaleList();
+ font.getStyle();
+ font.getTtcIndex();
+ if ("NotoColorEmoji.ttf".equals(font.getFile().getName())) {
+ emojiFontPath = font.getFile().getAbsolutePath();
+ }
+ }
+ LinearLayout container = new LinearLayout(this);
+ container.setOrientation(LinearLayout.VERTICAL);
+ TextView textView = new TextView(this);
+ textView.setText(emojiFontPath);
+ container.addView(textView, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
+ setContentView(container);
+ }
+}
diff --git a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
index 80b0dfe..6bd07d0 100644
--- a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
+++ b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
@@ -40,6 +40,9 @@
import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
import com.android.compatibility.common.util.StreamUtil;
import com.android.compatibility.common.util.SystemUtil;
@@ -101,6 +104,9 @@
EMOJI_RENDERING_TEST_APP_ID + "/.EmojiRenderingTestActivity";
private static final long ACTIVITY_TIMEOUT_MILLIS = SECONDS.toMillis(10);
+ private static final String GET_AVAILABLE_FONTS_TEST_ACTIVITY =
+ EMOJI_RENDERING_TEST_APP_ID + "/.GetAvailableFontsTestActivity";
+
private static final Pattern PATTERN_FONT_FILES = Pattern.compile("\\.(ttf|otf|ttc|otc)$");
private static final Pattern PATTERN_TMP_FILES = Pattern.compile("^/data/local/tmp/");
private static final Pattern PATTERN_DATA_FONT_FILES = Pattern.compile("^/data/fonts/files/");
@@ -109,6 +115,7 @@
private String mKeyId;
private FontManager mFontManager;
+ private UiDevice mUiDevice;
@Before
public void setUp() throws Exception {
@@ -120,6 +127,7 @@
mKeyId = insertCert(CERT_PATH);
mFontManager = context.getSystemService(FontManager.class);
expectCommandToSucceed("cmd font clear");
+ mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
}
@After
@@ -287,6 +295,19 @@
assertThat(countMatch(openFiles, patternEmojiVPlus1)).isEqualTo(0);
}
+ @Test
+ public void getAvailableFonts() throws Exception {
+ String fontPath = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME);
+ startActivity(EMOJI_RENDERING_TEST_APP_ID, GET_AVAILABLE_FONTS_TEST_ACTIVITY);
+ // GET_AVAILABLE_FONTS_TEST_ACTIVITY shows the NotoColorEmoji path it got.
+ mUiDevice.wait(
+ Until.findObject(By.pkg(EMOJI_RENDERING_TEST_APP_ID).text(fontPath)),
+ ACTIVITY_TIMEOUT_MILLIS);
+ // The font file should not be opened just by querying the path using
+ // SystemFont.getAvailableFonts().
+ assertThat(isFileOpenedBy(fontPath, EMOJI_RENDERING_TEST_APP_ID)).isFalse();
+ }
+
private static String insertCert(String certPath) throws Exception {
Pair<String, String> result;
try (InputStream is = new FileInputStream(certPath)) {
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index c59dcf8..4ce78aa 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -92,10 +92,6 @@
builder.addExposedCapability(caps);
}
- for (int caps : UNDERLYING_CAPS) {
- builder.addRequiredUnderlyingCapability(caps);
- }
-
return builder.build();
}
@@ -141,9 +137,7 @@
@Test
public void testBuilderRequiresNonEmptyExposedCaps() {
try {
- newBuilder()
- .addRequiredUnderlyingCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build();
+ newBuilder().build();
fail("Expected exception due to invalid exposed capabilities");
} catch (IllegalArgumentException e) {
@@ -187,10 +181,6 @@
Arrays.sort(exposedCaps);
assertArrayEquals(EXPOSED_CAPS, exposedCaps);
- int[] underlyingCaps = config.getRequiredUnderlyingCapabilities();
- Arrays.sort(underlyingCaps);
- assertArrayEquals(UNDERLYING_CAPS, underlyingCaps);
-
assertEquals(TUNNEL_CONNECTION_PARAMS, config.getTunnelConnectionParams());
assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis());
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 3360d40..b7a6d0f 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -57,6 +57,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
@@ -707,10 +708,9 @@
@Test(expected = SecurityException.class)
public void testAddVcnUnderlyingNetworkPolicyListenerInvalidPermission() {
- doThrow(new SecurityException())
+ doReturn(PackageManager.PERMISSION_DENIED)
.when(mMockContext)
- .enforceCallingOrSelfPermission(
- eq(android.Manifest.permission.NETWORK_FACTORY), any());
+ .checkCallingOrSelfPermission(any());
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
}
@@ -724,10 +724,9 @@
@Test(expected = SecurityException.class)
public void testRemoveVcnUnderlyingNetworkPolicyListenerInvalidPermission() {
- doThrow(new SecurityException())
+ doReturn(PackageManager.PERMISSION_DENIED)
.when(mMockContext)
- .enforceCallingOrSelfPermission(
- eq(android.Manifest.permission.NETWORK_FACTORY), any());
+ .checkCallingOrSelfPermission(any());
mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
}
@@ -919,10 +918,9 @@
@Test(expected = SecurityException.class)
public void testGetUnderlyingNetworkPolicyInvalidPermission() {
- doThrow(new SecurityException())
+ doReturn(PackageManager.PERMISSION_DENIED)
.when(mMockContext)
- .enforceCallingOrSelfPermission(
- eq(android.Manifest.permission.NETWORK_FACTORY), any());
+ .checkCallingOrSelfPermission(any());
mVcnMgmtSvc.getUnderlyingNetworkPolicy(new NetworkCapabilities(), new LinkProperties());
}
diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
index a36fd79..f91575b 100644
--- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
@@ -61,7 +61,6 @@
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Set;
import java.util.UUID;
@@ -146,7 +145,6 @@
mVcnContext,
SUB_GROUP,
mSubscriptionSnapshot,
- Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET),
mNetworkTrackerCb);
}
@@ -187,7 +185,6 @@
vcnContext,
SUB_GROUP,
mSubscriptionSnapshot,
- Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET),
mNetworkTrackerCb);
verify(cm)
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index 0a4fcbc..b97023a 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -177,7 +177,7 @@
doReturn(mUnderlyingNetworkTracker)
.when(mDeps)
- .newUnderlyingNetworkTracker(any(), any(), any(), any(), any());
+ .newUnderlyingNetworkTracker(any(), any(), any(), any());
doReturn(mWakeLock)
.when(mDeps)
.newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any());